package pacman;

import games.math.Vector2d;

import java.util.Collection;
import java.util.ArrayList;
import java.awt.*;

/**
 * The purpose of this is to capture the state of the game to
 * give to a decision making agent.
 * <p/>
 * The state is based on analysing a screen image, and may
 * give incorrect readings at any given instant - for example,
 * power pills flash, but no account is taken of this, so if
 * a power pill is still in the game, but the screen was captured
 * while it was in the 'blinked off' state, then the GameState will
 * indicate that there is no power pill at that location (in fact,
 * the power pills flash in unison, so it could appear that there
 * were no power pills, when in fact they were all present in the
 * true game state.
 */
public class GameState implements Drawable {
    // might as well have separate collections for each item?

    static int strokeWidth = 5;
    static Stroke stroke =  new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
    Collection<ConnectedSet> pills;

    Board gameBoard;

    Collection<ConnectedSet> ghosts;
    Agent agent;

    Vector2d closestPill;
    Vector2d closestPowerPill;

    Vector2d secondPill;

    // Masirhaye tablo
    // junction haye por emtiaz
    // emtiazhaye khoone

    Vector2d closestGhost;
    Vector2d secondGhost;
    Vector2d thirdGhost;
    Vector2d fourthGhost;

    Vector2d closestEdible;
    Vector2d secondEdible;
    Vector2d thirdEdible;
    Vector2d fourthEdible;

    Vector2d tmp;

    Vector2d blinky;
    Vector2d inky;
    Vector2d pinky;
    Vector2d sue;


    // Play Modes
    final static int PacmanIsSafe=0;
    final static int PacmanIsInDanger=1;
    final static int PacmanIsInDanger2=2;
    final static int PacmanIsInDanger3=3;
    final static int PacmanInInDanger4=4;

     static double safety=0;

     static int pillsLeft=754;
     static int pillsEaten=0;
     static int powerPillsLeft=4;

    static int regin;
    boolean edible=false;

    static ArrayList pacmode=new ArrayList();

    public GameState(Board board) {
        agent = new Agent();
        tmp = new Vector2d();
        this.gameBoard=board;
    }

    public double calculateSafety(){

        int nearGhostCount=0;
        double total=0;

            if (blinky !=null ){//blinky
               if(agent !=null){

                   total=total+blinky.dist(agent.cur);
                   if(blinky.dist(agent.cur) < 20){
                       System.out.println("Blinky is close to pacman");
                       nearGhostCount++;
                   }
               }
            }

            if (pinky !=null ){//pinky
               if(agent !=null){
                   total=total+pinky.dist(agent.cur);
                   if(pinky.dist(agent.cur) < 20){
                       System.out.println("Pinky is close to pacman");
                       nearGhostCount++;
                   }
               }
            }

           if (inky !=null ){//inky
               if(agent !=null){

                   total=total+inky.dist(agent.cur);
                   if(inky.dist(agent.cur) < 20){
                       System.out.println("Inky is close to pacman");
                       nearGhostCount++;
                   }
               }
            }

           if (sue !=null ){//Sue
               if(agent !=null){

                   total=total+sue.dist(agent.cur);
                   if(sue.dist(agent.cur) < 20){
                       System.out.println("Sue is close to pacman");
                       nearGhostCount++;
                   }
               }
            }

        double temp= total;

        //2332.3807579381201883496611510182 max e fasele *4

        return temp/2332.380757;

    }

    public ArrayList rawFeatures(){


        ArrayList rawFeat=new ArrayList();

        // Safety Degree


        // in which Region


        //
        double d=calculateSafety();
        rawFeat.add(d);
        rawFeat.add(whichRegion());

        return rawFeat;
    }

    public ArrayList wiseFeatures(){

        ArrayList wiseFeat=new ArrayList();

        return wiseFeat;
    }

    public void reset() {
        closestPill = null;
        closestPowerPill=null;
        closestEdible=null;
        closestGhost=null;

        secondPill=null;
    }

    public void update(ConnectedSet cs, int[] pix) {

   //     System.out.println("UPDATE IS CALLED");
        if (cs.isPacMan()) {
            agent.update(cs, pix);
        } else if (cs.ghostLike()) {
            edible=false;
           tmp.set(cs.x, cs.y);
            if (closestGhost == null)
                closestGhost = new Vector2d(tmp);
             else if (gameBoard.distance(tmp,agent.cur) < gameBoard.distance(closestGhost,agent.cur))
                closestGhost.set(tmp);
            else if (secondGhost == null)
                    secondGhost = new Vector2d(tmp);
             else if(gameBoard.distance(tmp,agent.cur) < gameBoard.distance(secondGhost,agent.cur))
                    secondGhost.set(tmp);
            else if (thirdGhost == null)
                    thirdGhost = new Vector2d(tmp);
             else if(gameBoard.distance(tmp,agent.cur) < gameBoard.distance(thirdGhost,agent.cur))
                    thirdGhost.set(tmp);
            else if (fourthGhost == null)
                    fourthGhost = new Vector2d(tmp);
             else {
                   fourthGhost.set(tmp);
            }
        }
        else if(cs.edibleGhost()){

            edible=true;
            safety=1;

            tmp.set(cs.x, cs.y);
             if (closestEdible == null)
                 closestEdible = new Vector2d(tmp);
              else if (gameBoard.distance(tmp,agent.cur) < gameBoard.distance(closestEdible,agent.cur))
                 closestEdible.set(tmp);
             else if (secondEdible == null)
                     secondEdible = new Vector2d(tmp);
              else if(gameBoard.distance(tmp,agent.cur) < gameBoard.distance(secondEdible,agent.cur))
                     secondEdible.set(tmp);
             else if (thirdEdible == null)
                     thirdEdible = new Vector2d(tmp);
              else if(gameBoard.distance(tmp,agent.cur) < gameBoard.distance(thirdEdible,agent.cur))
                     thirdEdible.set(tmp);
             else if (fourthEdible == null)
                     fourthEdible = new Vector2d(tmp);
              else {
                    fourthEdible.set(tmp);
             }



        }else if (cs.pill()) {

            // keep track  of the position of the closest pill
            tmp.set(cs.x, cs.y);
            if (closestPill == null) {
                closestPill = new Vector2d(tmp);
            } else if (gameBoard.distance(tmp,agent.cur) < gameBoard.distance(closestPill,agent.cur)) {
                closestPill.set(tmp);
            }

            else if (secondPill == null)
                secondPill = new Vector2d(tmp);
             else if (gameBoard.distance(tmp,agent.cur) < gameBoard.distance(secondPill,agent.cur))
                secondPill.set(tmp);

        }else if(cs.powerPill()){
            tmp.set(cs.x, cs.y);

            if (closestPowerPill == null) {
                closestPowerPill = new Vector2d(tmp);
            } else if (gameBoard.distance(tmp,agent.cur) < gameBoard.distance(closestPowerPill,agent.cur)) {
                closestPowerPill.set(tmp);
            }
        }
    }

    public int whichRegion(){
        int reg=0;
        int x=gameBoard.pac.x;
        int y=gameBoard.pac.y;
        if(x<13){
            if(y<14)
                reg=1;
            else
                reg=3;
        }
        else{
            if(y<14)
                reg=2;
            else
                reg=4;
        }
        regin=reg;
        return reg;
    }

    public void draw(Graphics gg, int w, int h) {
        //To change body of implemented methods use File | Settings | File Templates.
        Graphics2D g = (Graphics2D) gg;

        if (agent != null) {
            agent.draw(g, w, h);
        }
        if (closestPill != null && agent != null) {
            g.setStroke(stroke);
            g.setColor(Color.cyan);
            g.drawLine((int) closestPill.x, (int) closestPill.y, (int) agent.cur.x, (int) agent.cur.y);

        }

        if (closestGhost != null && agent != null) {
            g.setStroke(stroke);
            g.setColor(Color.white);
            g.drawLine((int) closestGhost.x, (int) closestGhost.y, (int) agent.cur.x, (int) agent.cur.y);

        }

        if (closestPowerPill != null && agent != null) {
            g.setStroke(stroke);
            g.setColor(Color.yellow);
            g.drawLine((int) closestPowerPill.x, (int) closestPowerPill.y, (int) agent.cur.x, (int) agent.cur.y);

        }

        if (closestEdible != null && agent != null) {
            g.setStroke(stroke);
            g.setColor(Color.BLUE);
            g.drawLine((int) closestEdible.x, (int) closestEdible.y, (int) agent.cur.x, (int) agent.cur.y);

        }
    }

}

