
import java.awt.event.MouseEvent;
import javax.swing.*;

public class GameMaster {
    private final Field fieldA;
    private final Field fieldB;
    private final Grave graveA;
    private final Grave graveB;
    private int healthA;
    private int healthB;
    private int phase;
    private int monsterAttacking;
    private final Hand handA;
    private final Hand handB;
    private boolean ACanPlayCard;
    private boolean BCanPlayCard;
    private boolean firstTurn;
    
    public static final int DRAW_A = 1;
    //public static final int STAND_A = 1;
    public static final int MAIN_A = 2;
    public static final int BATTLE_A = 3;
    public static final int END_A = 4;
    public static final int DRAW_B = 5;
    //public static final int STAND_B = 6;
    public static final int MAIN_B = 6;
    public static final int BATTLE_B = 7;
    public static final int END_B = 8;
    
    public static final int SELECT_B = 12;
    public static final int SELECT_A = 13;
    
    public static final int END_OF_GAME = 15;
    
    private static final int FACEUP_ATKPOS = 1;
    private static final int FACEUP_DEFPOS = 2;
    private static final int FACEDOWN_DEFPOS = 3;
    
    GameMaster(Field fieldA, Field fieldB, Hand handA, Hand handB, Grave graveA, Grave graveB)
    {
        this.fieldA = fieldA;
        this.handA = handA;
        this.fieldB = fieldB;
        this.handB = handB;
        this.graveA = graveA;
        this.graveB = graveB;
        healthA = 8000;
        healthB = 8000;
        phase = DRAW_A;
        ACanPlayCard = true;
        BCanPlayCard = true;
        firstTurn = true;
        
    }


    //field.getDamage(i) retorna como int att o def del monstruo i en field
    //field.getState(i) retorna en bool si esta en posicion de att o def boca abajo o arriba
    public void playCard(MouseEvent mouse, int cardPosInHand){
      //Es el turno de A y aun no juega una carta
      int battlePosition = (SwingUtilities.isRightMouseButton(mouse))?FACEDOWN_DEFPOS:FACEUP_ATKPOS;
      if((phase == MAIN_A)&&(ACanPlayCard))
      {
         //Si el campo esta lleno no puede jugar mas cartas
         if(fieldA.isFieldFull()) return;
         fieldA.playCard(handA.getCard(cardPosInHand), battlePosition);
         handA.removeCard(cardPosInHand);
         ACanPlayCard = false;
      }
      //Es el turno de B y aun no juega una carta
      else if((phase == MAIN_B)&&(BCanPlayCard))
      {
         //Si el campo esta lleno no puede jugar mas cartas
         if(fieldB.isFieldFull()) return;
         fieldB.playCard(handB.getCard(cardPosInHand), battlePosition);
         handB.removeCard(cardPosInHand);
         BCanPlayCard = false;
      }
    }
    public void selectAttacker(int monsterAttacking)
    {
        //Turno de A
        if((phase == BATTLE_A)&&(fieldA.getBattlePos(monsterAttacking) == FACEUP_ATKPOS)&&(fieldA.getCard(monsterAttacking).getATKStatus()))
        {
           fieldA.getCard(monsterAttacking).cardAttacked();
           //Si B no tiene algo en el campo se le ataca directo
           if(fieldB.getSize() == 0)
           {              
              healthB -= fieldA.getDamage(monsterAttacking);
              phase = ((healthA <= 0)||( healthB <= 0))?END_OF_GAME:BATTLE_A;
           }
           //Se pasa a la fase para elegir a quien atacar
           else{
              phase = SELECT_B;
              this.monsterAttacking = monsterAttacking;
           }
        }
        //Turno de B
        else if((phase == BATTLE_B)&&(fieldB.getBattlePos(monsterAttacking) == FACEUP_ATKPOS)&&(fieldB.getCard(monsterAttacking).getATKStatus())){
           fieldB.getCard(monsterAttacking).cardAttacked();
           //Si A no tiene algo en el campo se le ataca directo
           if(fieldA.getSize() == 0)
           {   
              healthA -= fieldB.getDamage(monsterAttacking);
              //Si algun jugador queda sin LF se termina el juego
              phase = ((healthA <= 0)||( healthB <= 0))?END_OF_GAME:BATTLE_B;
           }
           //Se pasa a la fase para elegir a quien atacar
           else{
              phase = SELECT_A;
              //Si algun jugador queda sin LF se termina el juego
              this.monsterAttacking = monsterAttacking;
           }
        }
    }
    public void battle(int monsterDefending)
    {
         //A atacando a B
        if(phase == SELECT_B)
        {
            //A>B
            if(fieldA.getDamage(monsterAttacking) > fieldB.getDamage(monsterDefending))
            {
                
                //B esta en att
                if(fieldB.getBattlePos(monsterDefending) == FACEUP_ATKPOS)
                {
                    healthB -= fieldA.getDamage(monsterAttacking) - fieldB.getDamage(monsterDefending);
                }
                graveB.add(fieldB.getCard(monsterDefending));
                fieldB.removeCard(monsterDefending);
            }
            //B>A
            else if(fieldA.getDamage(monsterAttacking) < fieldB.getDamage(monsterDefending))
            {
                healthA -= fieldB.getDamage(monsterDefending) - fieldA.getDamage(monsterAttacking);
                //B esta en att
                if(fieldB.getBattlePos(monsterDefending) == FACEUP_ATKPOS)
                {
                    graveA.add(fieldA.getCard(monsterAttacking));
                    fieldA.removeCard(monsterAttacking);
                }
                //B esta en def boca arriba
                else if(fieldB.getBattlePos(monsterDefending) == FACEDOWN_DEFPOS) 
                {
                    fieldB.forceBattlePos(monsterDefending);
                } 
                
                
            }
            //B=A
            else
            {
                //B esta en att
                if(fieldB.getBattlePos(monsterDefending) == FACEUP_ATKPOS)
                {
                    graveA.add(fieldA.getCard(monsterAttacking));
                    fieldA.removeCard(monsterAttacking);
                    graveB.add(fieldB.getCard(monsterDefending));
                    fieldB.removeCard(monsterDefending);
                }
                //B esta en def boca arriba
                else if(fieldB.getBattlePos(monsterDefending) == FACEDOWN_DEFPOS)
                {
                    fieldB.forceBattlePos(monsterDefending);
                } 

            }            
            phase = ((healthA <= 0)||( healthB <= 0))?END_OF_GAME:BATTLE_A;
        }
        
        
        
        //B atacando a A
        else if(phase == SELECT_A)
        {
            //B>A
            if(fieldB.getDamage(monsterAttacking) > fieldA.getDamage(monsterDefending))
            {
                //A esta en att
                if(fieldA.getBattlePos(monsterDefending) == FACEUP_ATKPOS) 
                healthA -= fieldB.getDamage(monsterAttacking) - fieldA.getDamage(monsterDefending);
                
                graveA.add(fieldA.getCard(monsterDefending));
                fieldA.removeCard(monsterDefending);
            }
            //A>B
            else if(fieldB.getDamage(monsterAttacking) < fieldA.getDamage(monsterDefending))
            {
                healthB -= fieldA.getDamage(monsterDefending) - fieldB.getDamage(monsterAttacking);
                //A esta en att
                if(fieldA.getBattlePos(monsterDefending) == FACEUP_ATKPOS){
                    graveB.add(fieldB.getCard(monsterAttacking));
                    fieldB.removeCard(monsterAttacking);
                }
                
                //A esta en def
                else if(fieldA.getBattlePos(monsterDefending) == FACEDOWN_DEFPOS)
                {
                    fieldA.forceBattlePos(monsterDefending);
                } 
                
                
            }
            //B=A
            else
            {
                //A esta en att
                if(fieldA.getBattlePos(monsterDefending) == FACEUP_ATKPOS)
                {
                    graveB.add(fieldB.getCard(monsterAttacking));
                    fieldB.removeCard(monsterAttacking);
                    graveA.add(fieldA.getCard(monsterDefending));
                    fieldA.removeCard(monsterDefending);
                }
                //A esta en def
                else if(fieldA.getBattlePos(monsterDefending) == FACEDOWN_DEFPOS)
                {
                    fieldA.forceBattlePos(monsterDefending);
                } 

            }
            phase = ((healthA <= 0)||( healthB <= 0))?END_OF_GAME:BATTLE_B;
        }
    }
    public int getPhase()
    {
        return phase;
    }
    public String getPhaseStr()
    {
        switch(phase)
        {
            case 1: return "DRAW A";
            //case 1: return "STANDBY A";
            case 2: return "MAIN A";
            case 3: return "BATTLE A";
            case 4: return "END A";
            case 5: return "DRAW B";
            //case 6: return "STANBY B";
            case 6: return "MAIN B";
            case 7: return "BATTLE B";
            case 8: return "END B";
            case 12: return "SELECTING B";
            case 13: return "SELECTING A";
            case 15: return "GAME OVER";
            default: System.out.println("Error en la phase");
            return null;
        }
    }
    public void nextPhase()
    {
      if(phase == SELECT_B) phase = BATTLE_A;
      else if((firstTurn)&&(phase ==  MAIN_A))
      {
          phase = END_A;
      }
      else if(phase == SELECT_A) phase = BATTLE_B;
      else if(phase == END_B)
      {
        for(int i=0;i<5;i++)
        {
            if(fieldA.getCard(i) != null)
            {
                fieldA.getCard(i).resetValues();
            }
            
        }
         ACanPlayCard = true;
         phase = DRAW_A;
      }
      else if(phase == END_A)
      {
        firstTurn = false;
        for(int i=0;i<5;i++)
        {
            if(fieldB.getCard(i) != null)
            {
                fieldB.getCard(i).resetValues();
            }
        }
         BCanPlayCard = true;
         phase++;
      }
      else if(phase == END_OF_GAME);
      else phase++;
    }
    public String getHealthA()
    {
        if(healthA > 0) return String.valueOf(healthA);
        else return "0";
    }
    public String getHealthB()
    {
        if(healthB > 0) return String.valueOf(healthB);
        else return "0";
    }
    public void ForceEnd()
    {
        phase = END_OF_GAME;
    }
    
}
