use search::apply_move;
use bitboard::Bitboard;
use game::Game;
use search::*;
use std::io::Write;
use movegen::*;
use log::{info};
use std::time::{Duration, Instant};



use std::sync::mpsc::{Receiver, Sender};

pub enum EngineMsg {
    SetBoard(Game),
    SetPiece(Bitboard),
    Search(i32),
    Ping,
    Stop,
    NewGame,
    GetState,
    GetInfo,
}


pub enum EngineState {
    Idle,
    Searching
}


pub enum InterfaceMsg {
    BestMove(Move),
    State(EngineState)
}


pub fn run_engine(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) {
    let mut game = Game::default();
    loop {
        //game.pieces[0] = 0x00ff_0000_0000_0100;
        //game.pieces[QUEEN as usize] = 0x0000_0000_0000_0080;
        //game.pieces[10] = 0x4000_0000_0000_0000;

        let msg = r.recv().unwrap();

        match msg {
            EngineMsg::SetBoard(g) => {
                //println!("SetBoard");
                game = g;
            },
            EngineMsg::SetPiece(_) => { println!("SetPiece") },
            EngineMsg::Search(depth) => {
                //info!("searching in pos\n {}", game.beautiful_print());
                //println!("Search {}", depth);

                let check_fn = || -> bool {
                    if let Ok(msg) = r.try_recv() {
                        return true;
                    }
                    return false;
                };

                let mut sc = SearchControl{ nodes: 0, check: &check_fn };

                let before = Instant::now();
                let best_move = search(&game, &mut sc, depth);
                let time = before.elapsed();
                println!("bestmove {}", best_move.to_string());
                info!("bestmove {}", best_move.to_string());
                info!("searched {} nodes in {} ms ({} nodes/s)", sc.nodes, time.as_millis(), (sc.nodes as f64 / time.as_millis() as f64 * 1000.0) as i64);
            },
            EngineMsg::Ping => { println!("Ping") },
            EngineMsg::Stop => { println!("Stop") },
            EngineMsg::NewGame => {
                //println!("NewGame")
            },
            EngineMsg::GetState => { println!("GetState") },
            EngineMsg::GetInfo => { println!("GetInfo") },
        }

        //println!("{}", game.beautiful_print());

        //let moves = generate_moves(&game, WHITE);
    }
}