/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package woaley;

import algorithm.MoveOffer;
import database.UserGame;
import database.encoding.Encode;
import database.operations.InsertPlayerTable;
import database.operations.ReadPlayerTable;
import frame.Gamestate;
import frame.NoSuchPlayerException;
import frame.Operator;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Ani
 */
public class NegamaxAlfaBetaWoaley extends MoveOffer{
    public static final int DEPTH = 6;
    public static final int MAX_VALUE = Integer.MAX_VALUE;
    public static final int MIN_VALUE = -MAX_VALUE;

    private int alfa;
    private int beta;
    private Boolean caninsert;
    private String table;

    private NegamaxAlfaBetaWoaley ng;
    private UserGame ug;
    private Encode e;
    private Gamestate newstate;
    private List<Operator> usableOperators;
    private Random rand;


    public NegamaxAlfaBetaWoaley(Gamestate state, int depth, String table) throws SQLException, IOException, NoSuchPlayerException {
        this(state, depth, MIN_VALUE, MAX_VALUE, false, table);
    }

    public NegamaxAlfaBetaWoaley(Gamestate state, int depth, int alfa, int beta,
            Boolean dm, String table) throws SQLException, IOException, NoSuchPlayerException {
        this.state = state;
        this.depth = depth;
        this.alfa = alfa;
        this.beta = beta;
        this.caninsert = dm;
        this.table = table;
        rand = new Random();
        negamax();
    }

    public void negamax() throws SQLException, IOException, NoSuchPlayerException{
  
      if (depth==0 || state.isEndstate()){

            e = new Encode((Woaley) state);
            ug = ReadPlayerTable.heuristicForState(e.getCode(), table);
            
            if (ug==null){
                useful = state.negaMaxAlfaBetaUsefulness();

                if (state.isEndstate()){
                    caninsert =true;
                    ug = new UserGame(e.getCode(), useful);
                    InsertPlayerTable.insertHeusristicForState(ug, table);
                }
                else{
                    caninsert=false;
                }                
            }
            else{
                caninsert=true;
                useful = ug.getHeuristic();
            }
            return;
        }
        else{
            usableOperators = selectUsableOperators();

            for (Operator o: usableOperators){
                newstate = state.use(o);
                e = new Encode((Woaley) newstate);
                ug = ReadPlayerTable.heuristicForState(e.getCode(), table);

                if(ug!=null){
                    select(ug.getHeuristic(), o);
                }
                else{
                    ng = new NegamaxAlfaBetaWoaley(newstate, depth-1, -beta, -alfa, caninsert, table);
                    select(-ng.useful, o);
                }

                if (alfa>=beta){
                    break;
                }
            }
            useful = alfa;
            ug = ReadPlayerTable.heuristicForState((Woaley) state.use(operator), table);
            if (ug==null){
                e = new Encode((Woaley) state.use(operator));
                ug = new UserGame(e.getCode(), useful);
                InsertPlayerTable.insertHeusristicForState(ug, table);
            }
        }
    }

    
    private List<Operator> selectUsableOperators() throws NoSuchPlayerException{
        List<Operator> list = new ArrayList<Operator>();
        for (Operator op: Gamestate.getOperators()){
            if (state.isUsable(op)){
                list.add(op);
            }
        }
        return list;
    }

    private void select(int value, Operator op){
        if (value>=alfa){

            if (value==alfa){

                if (!rand.nextBoolean()){
                    return;
                }
            }

            alfa=value;
            operator = op;
        }
    }


}

