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

package gamegraphics;


import gamegraphics.misc.WinnerStatistic;
import frame.*;
import gamegraphics.misc.Option;
import gamegraphics.elements.*;
import gamegraphics.image.ReadImage;
import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.sql.SQLException;
import javax.swing.*;
import javax.swing.text.html.HTMLEditorKit;
import woaley.*;

/**
 *
 * @author Ani
 */
public class WoaleyPanel extends JPanel implements Runnable{
    private JTextPane whosTurn;
    private Option option;
    private Gamestate startstate;
    private Gamestate state;
    private NegamaxAlfaBetaWoaley negamax;
    private Operator userOp;
    private Operator compOp;

    private Image redButton;
    private Image greenButton;
    private Image gametableImage;

    private JButton buttons[][];
    private Gametable gametable;
    private JTextField noFiguresInHouses[];
    private JTextField noFiguresInCollectors[];

    private House houses[][];
    private CollectorHouse[] collectorHouse;

    private Thread woaleythread;
    private WinnerStatistic winnerStatistic;

    private Player playerHuman;
    private Player playerComputer;

    private WoaleyJApplet container;
    private int noMoves;


    public WoaleyPanel(WoaleyJApplet container) {
        this.container = container;
    }

    public WinnerStatistic getWinnerStatistic() {
        return winnerStatistic;
    }

    public void setWinnerStatistic(WinnerStatistic winnerStatistic) {
        this.winnerStatistic = winnerStatistic;
    }

    public void startNewGame(Option option) throws IOException, NoSuchPlayerException{
            this.option = option;
            init();
    }

    private void init() throws IOException, NoSuchPlayerException{
        noMoves = 1;
        initPlayers();
        initSettings();
        initWhosTurn();
        initStates();
        initHouses();
        initImages();
        initButtons();
        initNoFiguresTextField();
        initGametablePanel();
        initThread();
        repaint();
    }

    private void initPlayers() throws NoSuchPlayerException{
        if (option.isHumanstart()){
            playerHuman = new Player(Player.A);
            playerComputer = new Player(Player.B);
        }
        else{
            playerHuman = new Player(Player.B);
            playerComputer = new Player(Player.A);
        }
    }

    private void initSettings(){
        setSize(800, 500);
        setBackground(new Color(30, 180, 30));
        setLayout(null);
    }

    private void initWhosTurn(){
        whosTurn = new JTextPane();
        whosTurn.setEditorKit(new HTMLEditorKit());
        whosTurn.setBounds(200, -20, 400, 50);
        whosTurn.setBackground(getBackground());
        if (option.isHumanstart()){
            whosTurn.setText("<h1 align=\"center\">" + noMoves +". lépés, Te következel!</h1>");
        }
        else{
            whosTurn.setText("<h1 align=\"center\">" + noMoves +". lépés, A számítógép következik!</h1>");
        }
        add(whosTurn);
    }

    private void initStates() throws NoSuchPlayerException{
        startstate = new Woaley();
        state = new Woaley((Woaley)startstate);
    }

    private void initHouses(){
        houses = new House[3][7];
        collectorHouse = new CollectorHouse[3];
        int human = 1;
        int comp = 2;

        if (!option.isHumanstart()){
            human=2;
            comp=1;
        }

        for (int i = 1; i < 7; i++){
            houses[human][i] = new House(162+(77*(i-1)+(i*2)), 204-(i-1)*2);
            houses[comp][7-i] = new House(162+(77*(i-1)+(i*2)), 96-(i-1)*2);
        }
        collectorHouse[comp] = new CollectorHouse(54, 134);
        collectorHouse[human] = new CollectorHouse(639, 120);
    }

    private void initImages() throws IOException{
        redButton = ReadImage.readImage(getClass().getResource("/gamegraphics/docs/design/red_spot.png"));
        greenButton = ReadImage.readImage(getClass().getResource("/gamegraphics/docs/design/green_spot.png"));
        gametableImage = ReadImage.readImage(getClass().getResource("/gamegraphics/docs/design/mancala.png"));
    }

    private void initButtons(){
        buttons = new JButton[3][7];

        for (int i=1;i<3; i++){
            for (int j=1; j<7; j++){
                buttons[i][j] = new JButton(new ImageIcon(greenButton));
                buttons[i][j].setDisabledIcon(new ImageIcon(redButton));
                buttons[i][j].setBackground(Color.black);
                if (option.isHumanstart()){
                    buttons[i][j].setBounds(houses[i][j].getCoorX(), i==1 ? 445 : 30, 52, 52);
                    if (i==2){
                        buttons[i][j].setEnabled(false);
                    }
                }
                else{
                    buttons[i][j].setBounds(houses[i][j].getCoorX(), i==2 ? 445 : 30, 52, 52);
                }
                buttons[i][j].addActionListener(new ButtonClicked(i, j));
                add(buttons[i][j]);
            }
        }
    }
     
    private void initNoFiguresTextField(){
        noFiguresInHouses = new JTextField[7];
        noFiguresInCollectors = new JTextField[3];

        for (int i=1; i<7; i++){
            noFiguresInHouses[i] = new JTextField();
            noFiguresInHouses[i].setBounds(houses[playerHuman.getPlayerAsInteger()][i].getCoorX()+15, 423, 22, 22);
            noFiguresInHouses[i].setEditable(false);
            noFiguresInHouses[i].setText("  " + houses[playerHuman.getPlayerAsInteger()][i].getNumberOfFigures());
            add(noFiguresInHouses[i]);
        }

        for (int i=1; i<3; i++){
            noFiguresInCollectors[i] = new JTextField();
            noFiguresInCollectors[i].setBounds(collectorHouse[i].getCoorX()+15, 423, 40, 40);
            noFiguresInCollectors[i].setEditable(false);
            noFiguresInCollectors[i].setText("     " + collectorHouse[i].getNumberOfFigures());
            add(noFiguresInCollectors[i]);
        }
    }

    private void initGametablePanel(){
        gametable = new Gametable(gametableImage, houses, collectorHouse, noFiguresInHouses,
                noFiguresInCollectors, playerHuman, this);
        gametable.setBounds(0, 80, 800, 350);
        add(gametable);
    }

    private void initThread(){
        woaleythread = new Thread(this);
        woaleythread.start();
    }

    private void disableButton(int x, int y){
        buttons[x][y].setEnabled(false);
    }

    private void disableButtons(){

        for (int i=1;i<3;i++){
            for (int j=1; j<7; j++){
                disableButton(i, j);
            }
        }
    }

    private void enableButton(int x, int y){
        buttons[x][y].setEnabled(true);
    }

    private void enableButtons(){

        for (int i=1;i<3;i++){
            for (int j=1; j<7; j++){
                enableButton(i, j);
            }
        }
    }

    public void run() {
        try{
            if (!option.isHumanstart()){
                noMoves++;
                computerMove();               
            }
            while (Thread.currentThread()==woaleythread && !state.isEndstate() && noMoves<101){
                if(userOp!=null){
                    noMoves++;
                    userMove();
                    
                    if (state.isEndstate() || noMoves>100){
                        break;
                    }
                    noMoves++;
                    computerMove();
                }
            }
            setWinnerStatistic();

        } catch (Exception ex) {
            SomethingFailedPanel sf = new SomethingFailedPanel(ex.getMessage());
            removeAll();
            add(sf);
            repaint();
        }
    }

    private void userMove() throws NoSuchPlayerException{
        disableButtons();

        state = state.use(userOp);
        Sow sow = (Sow) userOp;
        gametable.sowAndCollectAnimation(playerHuman, sow.getRow(), sow.getBeginningPosition());
        if (!compareGamestateAndGraphics()){
            
        }
        userOp=null;
        whosTurn.setText("<h1 align=\"center\">" + noMoves +". lépés, A számítógép következik!</h1>");
    }

    private void computerMove() throws SQLException, IOException, NoSuchPlayerException{
        disableButtons();
        int depth = NegamaxAlfaBetaWoaley.DEPTH + 2*option.getLevel();
        negamax = new NegamaxAlfaBetaWoaley(state, depth, container.getData().getTablename());
        compOp = negamax.getOperator();
        state = state.use(compOp);
        Sow sow = (Sow) compOp;
        gametable.sowAndCollectAnimation(playerComputer, sow.getRow(), sow.getBeginningPosition());
        Woaley w = (Woaley) state;
        if (w.getContinuous()){
            enableButton(w.getPosition().getRow(), w.getPosition().getHouse());
        }
        else{
            for (int i=1; i<3; i++){
                for (int j=1;j<7;j++){
                    if (houses[i][j].getNumberOfFigures()!=0){
                        enableButton(i, j);
                    }
                }
            }
        }
        if (!compareGamestateAndGraphics()){
                      
        }
        compOp = null;
        whosTurn.setText("<h1 align=\"center\">" + noMoves + ". lépés, Te következel!</h1>");
    }

    private boolean compareGamestateAndGraphics(){
        Woaley woaleystate = (Woaley) state;
        for (int i=1;i<3;i++){
            for (int j=1;j<7;j++){
                if (houses[i][j].getNumberOfFigures()!=woaleystate.getBoard()[i][j]){
                    return false;
                }
            }
            if (collectorHouse[i].getNumberOfFigures()!=woaleystate.getCollectors()[i]){
                return false;
            }
        }
        return true;
    }

    private void setWinnerStatistic(){
        Woaley w = (Woaley) state;

        WinnerStatistic ws = new WinnerStatistic();
        if (w.winner()==playerComputer.getPlayer()){
            ws.setWinner(Option.COMPUTER);
            ws.setPointsOfWinner(w.getCollectors()[playerComputer.getPlayerAsInteger()]);
            ws.setPointsOfLooser(w.getCollectors()[playerHuman.getPlayerAsInteger()]);
        }
        else if(w.winner()==playerHuman.getPlayer()){
            ws.setWinner(Option.HUMAN);
            ws.setPointsOfWinner(w.getCollectors()[playerHuman.getPlayerAsInteger()]);
            ws.setPointsOfLooser(w.getCollectors()[playerComputer.getPlayerAsInteger()]);
        }
        else{
            ws.setDrawn(true);
            ws.setPointsOfWinner(w.getCollectors()[1]);
            ws.setPointsOfLooser(w.getCollectors()[2]);
        }
        winnerStatistic = ws;
    }


    class ButtonClicked implements ActionListener{
        private int x;
        private int y;


        public ButtonClicked(int x, int y) {
            this.x = x;
            this.y = y;
        }


        public void actionPerformed(ActionEvent e) {
            userOp = new Sow(playerHuman, x, y);
        }

    }




}
