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

package woaley;

import frame.Gamestate;
import frame.NoSuchPlayerException;
import frame.Operator;
import frame.Player;
import java.util.ArrayList;


/**
 *
 * @author Ani
 */
public class Woaley extends Gamestate{
    private Integer board[][];
    private Integer collectors[];
    private Boolean continuous;
    private Position position;

    static{
        operators = new ArrayList<Operator>();
        for (int i=1; i<3; i++){
            for (int j=1; j<7; j++){
                try {
                    operators.add(new Sow(new Player('A'), i, j));
                    operators.add(new Sow(new Player('B'), i, j));
                } catch (NoSuchPlayerException ex) {

                }
            }
        }

    }

    public Woaley() throws NoSuchPlayerException {
        board = new Integer[3][7];
        collectors = new Integer[3];
        continuous = false;
        position = new Position(0,0);
        player = new Player('A');

        for (int i=1; i<3; i++){
            for (int j=1; j<7; j++){
                board[i][j] = 4;
            }
            collectors[i] = 0;
        }
    }

    public Woaley(Woaley woaley) throws NoSuchPlayerException{
        board = new Integer[3][7];
        collectors = new Integer[3];

        for (int i=1; i<3; i++){
            for (int j=1; j<7; j++){
                board[i][j] = woaley.board[i][j];
            }
            collectors[i] = woaley.collectors[i];
        }

        continuous = woaley.continuous;
        position = new Position(woaley.position.getRow(), woaley.position.getHouse());
        player = new Player(woaley.player.getPlayer());
    }

    public Integer[][] getBoard() {
        return board;
    }

    public Integer[] getCollectors() {
        return collectors;
    }

    public Boolean getContinuous() {
        return continuous;
    }

    public Position getPosition() {
        return position;
    }

    @Override
    public boolean isUsable(Operator operator) throws NoSuchPlayerException {
        if (operator instanceof Sow){
            Sow sow = (Sow) operator;

            if (board[sow.getRow()][sow.getBeginningPosition()]==0){

                return false;
            }

            if (this.equals(new Woaley()) && sow.getRow()!=1){
                return false;
            }

            if (continuous && (sow.getRow()!= position.getRow() ||
                    sow.getBeginningPosition()!=position.getHouse())){
                return false;
            }

            if (!player.equals(sow.getPlayer())){
                return false;
            }

            return true;
        }
        return false;
    }

    @Override
    public Gamestate use(Operator operator) throws NoSuchPlayerException {
        Woaley newgamestate = new Woaley(this);

        if (operator instanceof Sow){
            Sow sow = (Sow) operator;
            Position lastpos = sowing(newgamestate, sow.getRow(),
                    sow.getBeginningPosition());
            collect(newgamestate, lastpos.getRow(), lastpos.getHouse());

            newgamestate.changeNextPlayer();
        }

        return newgamestate;
    }


    public Position sowing(Woaley w, int row, int house){
        int sowable = w.board[row][house];
        int lastplayer = row;
        int lasthouse = house;
        w.board[row][house] = 0;

        while (sowable>0){
            if (sowable>0){
                sowingAll(w, row, house+1, Math.min(6, sowable+house));
                lastplayer = row;
                lasthouse = Math.min(6, sowable+house);
                sowable = sowable - 6 + house;              
            }
            if (sowable>0){
                sowingAll(w, row == 1 ? 2 : 1, 1, Math.min(6, sowable));
                lastplayer = (row == 1 ? 2 : 1);
                lasthouse = Math.min(6, sowable);
                sowable =sowable - lasthouse;
            }
            if (sowable>0){
                sowingAll(w, row, 1, Math.min(house, sowable));
                lastplayer = row;
                lasthouse = Math.min(house, sowable);
                sowable = sowable - lasthouse;
            }
        }
        return new Position(lastplayer, lasthouse);
    }

    public void sowingAll(Woaley w, int p, int from, int to){
        for (int i=from; i<=to; i++){
            w.board[p][i] += 1;
        }
    }

    public void collect(Woaley w, int lastplayer, int lasthouse){
        if (w.board[lastplayer][lasthouse] == 2 || w.board[lastplayer][lasthouse] == 4){
            w.continuous = false;
            w.position.setHouse(0);
            w.position.setRow(0);
            if (collectRow(w, player.getPlayerAsInteger(), lastplayer, lasthouse, 1)){
                if (collectRow(w, player.getPlayerAsInteger(), lastplayer==1 ? 2 : 1, 6, 1)){
                    collectRow(w, player.getPlayerAsInteger(), lastplayer, 6, lasthouse+1);
                }
            }
        }
        else{
            w.continuous = true;
            w.position = new Position(lastplayer, lasthouse);
        }
    }

    public boolean collectRow(Woaley w, int who, int row, int from, int to){
        for (int i = from; i>=to; i--){
            if (w.board[row][i] == 2 || w.board[row][i] == 4){
                w.collectors[who] += w.board[row][i];
                w.board[row][i] = 0;
            }
            else{
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean isEndstate() {
        for (int i=1; i<3; i++){
            for (int j=1; j<7; j++){
                if (board[i][j]>1){
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public Character winner() {
        if (collectors[1]>collectors[2]){
            return Player.A;
        }
        else if (collectors[1]<collectors[2]){
            return Player.B;
        }
        else
            return 'D';
    }


    @Override
    public Integer negaMaxAlfaBetaUsefulness(){
        return collectors[player.getPlayerAsInteger()]-
                collectors[player.getPlayerAsInteger()==1 ? 2 : 1];
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Woaley)){
            return false;
        }

        Woaley w = (Woaley) obj;
        for (int i=1; i<3; i++){
            for (int j=1; j<7; j++){
                if (w.board[i][j] != this.board[i][j]){
                    return false;
                }
            }
            if (w.collectors[i] != this.collectors[i]){
                return false;
            }
        }
        return this.position.equals(w.position) && this.continuous == w.continuous
                && this.player.equals(w.player);
    }



    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(collectors[2] + " ");
        for (int i=6; i>0; i--){
            sb.append(board[2][i] +" ");
        }
        sb.append("\n\n");
        for (int i=1; i<7; i++){
            sb.append(board[1][i] + " ");
        }
        sb.append(collectors[1] + " ");

        sb.append("\n");

        return sb.toString();
    }





}
