package chess2;
import java.util.ArrayList;
public class Rook extends ChessPiece {
   boolean hasMoved = false;
   public Rook(Side SIDE, int XPOS, int YPOS, ChessBoard YOURBOARD, ChessGame GAME){
        super(SIDE, XPOS, YPOS, YOURBOARD, GAME);
    }
   public Rook(Side SIDE, int XPOS, int YPOS, boolean HASMOVED, ChessBoard YOURBOARD, ChessGame GAME){
        super(SIDE, XPOS, YPOS, YOURBOARD, GAME);
        hasMoved = HASMOVED;
    }
   public boolean canEnterTankAt(int XPOS, int YPOS){
        if (side==ChessApplet.yourSide&&!ChessApplet.entertank){
            return false;
        }
        if (yourBoard.getTank(XPOS, YPOS)==null){
            return false;
        }
        if (yourBoard.pieceOccupyingSquare(XPOS, YPOS)!=Piece.TANK){
            return false;
        }
        ChessBoard simulaBoard = new ChessBoard (yourBoard);
        Tank targetTank = simulaBoard.getTank(XPOS, YPOS);
        simulaBoard.clearTank(targetTank);
        simulaBoard.tanks.remove(targetTank);
        if (simulaBoard.getRook(xPos, yPos).canMoveToMinusTank(XPOS, YPOS)){
            return true;
        }
        return false;
    }
   public Decision castleRookDecision(){
          King rookKing = yourBoard.yourKing(this.side);
          int XPOS;
          int YPOS = rookKing.yPos;
          if (this.xPos<rookKing.xPos){
               XPOS = rookKing.xPos-100;
          }
          else{
               XPOS = rookKing.xPos+100;
          }
          return new Decision(XPOS, YPOS);
      }
      public Decision castleKingDecision(){
          Decision deci = castleRookDecision();
          King king = yourBoard.yourKing(side);
            if (king.xPos>deci.xPos){
                deci.xPos -= 100;
            }
            else if (king.xPos<deci.xPos){
                deci.xPos += 100;
            }
          return deci;
      }
   public boolean canCastle(){

          King rookKing = yourBoard.yourKing(this.side);
          if (rookKing.hasCastled)
          {
              return false;
          }
          if (rookKing==null){
              return false;
          }
          if (rookKing.inCheck()){
              return false;
          }
          if (this.hasMoved||rookKing.hasMoved){
              return false;
          }
          Decision kingDeci = castleKingDecision();
          if (rookKing.inCheck(kingDeci.xPos, kingDeci.yPos)){
              return false;
          }

          int XPOS;
          int YPOS = rookKing.yPos;
          int dif;
          if (this.xPos<rookKing.xPos){
              XPOS = rookKing.xPos-100;
              dif = -1;
          }
          else{
              XPOS = rookKing.xPos+100;
              dif = 1;
          }
          if (!(XPOS!=this.xPos&&YPOS==this.yPos)){
            return false;
        }
         if (dif==-1){

             for (int i=xPos+100;i<=XPOS;i+=100){
                if (yourBoard.sideOccupyingSquare(i, this.yPos)==side&&yourBoard.pieceOccupyingSquare(i, this.yPos)!=Piece.KING){

                    return false;
                }
                if (yourBoard.sideOccupyingSquare(i, this.yPos)==Side.CORPSE){

                        return false;
                }
                if (yourBoard.sideOccupyingSquare(i, this.yPos)==Side.WALL){

                        return false;
                }
                if (inBarrel(i, this.yPos)&&!inBarrel(XPOS, YPOS)){

                    return false;
                }
                if (yourBoard.level(i, this.yPos)<yourBoard.level(i+1, this.yPos)-1&&i!=0){

                        return false;
                }
            }
         }
             else if (dif==1){

                 for (int i=xPos-100;i>=XPOS;i-=100){
                    if (yourBoard.sideOccupyingSquare(i, this.yPos)==side&&yourBoard.pieceOccupyingSquare(i, this.yPos)!=Piece.KING){
                        return false;
                    }
                    if (yourBoard.sideOccupyingSquare(i, this.yPos)==Side.CORPSE){
                            return false;
                    }
                    if (yourBoard.sideOccupyingSquare(i, this.yPos)==Side.WALL){
                            return false;
                    }
                    if (inBarrel(i, this.yPos)&&!inBarrel(XPOS, YPOS)){
                        return false;
                    }
                    if (yourBoard.level(i, this.yPos)<yourBoard.level(i+1, this.yPos)-1&&i!=0){
                            return false;
                    }
                }
             }
        Decision landingsquare = castleRookDecision();
        if (yourBoard.sideOccupyingSquare(landingsquare.xPos, landingsquare.yPos)!=Side.NONE){

            return false;
        }
          return true;
      }
    @Override
    public ArrayList<Decision> possibleDecisions(){
        ArrayList<Decision> possibleDecisions = new ArrayList();

        if (canCastle()){
            Decision deci = castleRookDecision();
            possibleDecisions.add(new Decision(deci.xPos, deci.yPos, DeciType.CASTLES));
            if (ChessApplet.castle||side!=ChessApplet.yourSide){
                return possibleDecisions;
            }
        }

        for (int i=xPos-100;inRangeOfBoard(i, yPos);i-=100){
             if (canMoveLeftTo(i, yPos)&&(!kingWouldBeInCheck(i, yPos))){
                 if (yourBoard.level(i, yPos)<yourBoard.level(i+100, yPos)-1){
                    possibleDecisions.add(new Decision(i, yPos, DeciType.SUICIDE));
                }
                else{
                    possibleDecisions.add(new Decision(i, yPos));
                }
             }
             if (canEnterTankAt(i, yPos)){
                 possibleDecisions.add(new Decision(i, yPos, DeciType.ENTERS));
             }
         }
         for (int i=xPos;inRangeOfBoard(i, yPos);i-=100){
             if (canAttackLeftTo(i, yPos)&&(!kingWouldBeInCheck(i, yPos))){
                 possibleDecisions.add(new Decision(i, yPos, DeciType.ATTACKS));
             }
         }
        for (int i=xPos+100;inRangeOfBoard(i, yPos);i+=100){
             if (canMoveRightTo(i, yPos)&&(!kingWouldBeInCheck(i, yPos))){
                 if (yourBoard.level(i, yPos)<yourBoard.level(i-100, yPos)-1){
                    possibleDecisions.add(new Decision(i, yPos, DeciType.SUICIDE));
                }
                else{
                    possibleDecisions.add(new Decision(i, yPos));
                }
             }
             if (canEnterTankAt(i, yPos)){
                 possibleDecisions.add(new Decision(i, yPos, DeciType.ENTERS));
             }
         }
         for (int i=xPos;inRangeOfBoard(i, yPos);i+=100){
             if (canAttackRightTo(i, yPos)&&(!kingWouldBeInCheck(i, yPos))){
                 possibleDecisions.add(new Decision(i, yPos, DeciType.ATTACKS));
             }
         }
        for (int i=yPos-100;inRangeOfBoard(xPos, i);i-=100){
             if (canMoveUpTo(xPos, i)&&(!kingWouldBeInCheck(xPos, i))){
                 if (yourBoard.level(xPos, i)<yourBoard.level(xPos, i+100)-1){
                    possibleDecisions.add(new Decision(xPos, i, DeciType.SUICIDE));
                }
                else{
                    possibleDecisions.add(new Decision(xPos, i));
                }
             }
             if (canEnterTankAt(xPos, i)){
                 possibleDecisions.add(new Decision(xPos, i, DeciType.ENTERS));
             }
         }
        for (int i=yPos;inRangeOfBoard(xPos, i);i-=100){
             if (canAttackUpTo(xPos, i)&&(!kingWouldBeInCheck(xPos, i))){
                 possibleDecisions.add(new Decision(xPos, i, DeciType.ATTACKS));
             }
         }
        for (int i=yPos+100;inRangeOfBoard(xPos, i);i+=100){
             if (canMoveDownTo(xPos, i)&&(!kingWouldBeInCheck(xPos, i))){
                 if (yourBoard.level(xPos, i)<yourBoard.level(xPos, i-100)-1){
                    possibleDecisions.add(new Decision(xPos, i, DeciType.SUICIDE));
                }
                else{
                    possibleDecisions.add(new Decision(xPos, i));
                }
             }
             if (canEnterTankAt(xPos, i)){
                 possibleDecisions.add(new Decision(xPos, i, DeciType.ENTERS));
             }
         }
         for (int i=yPos;inRangeOfBoard(xPos, i);i+=100){
             if (canAttackDownTo(xPos, i)&&(!kingWouldBeInCheck(xPos, i))){
                 possibleDecisions.add(new Decision(xPos, i, DeciType.ATTACKS));
             }
         }

        int [] xPosits2 = {xPos, xPos, xPos+100, xPos-100, xPos+100, xPos+100, xPos-100, xPos-100};
        int [] yPosits2 = {yPos+100, yPos-100, yPos, yPos, yPos+100, yPos-100, yPos+100, yPos-100};

       for (int n=0;n<8;n++){
           if (canMarry(xPosits2[n], yPosits2[n])){
               possibleDecisions.add(new Decision(xPosits2[n], yPosits2[n], DeciType.WEDS));
           }
       }
        return possibleDecisions;
    }
    @Override
    public boolean canMoveTo(int XPOS, int YPOS){
       ArrayList<Decision> possibleDecisions = possibleDecisions();
       if (possibleDecisions.size()==0){
            return false;
        }
        for (int i=0;i<possibleDecisions.size();i++){
            if (possibleDecisions.get(i).xPos==XPOS&&possibleDecisions.get(i).yPos==YPOS){
                break;
            }
            if (i==possibleDecisions.size()-1){
                return false;
            }
        }
       if (kingWouldBeInCheck(XPOS, YPOS)){
            return false;
        }
        if (canCastle()){
            return true;
        }

        return canMoveToMinusChecking(XPOS, YPOS);
    }

   public boolean canMoveToMinusChecking(int XPOS, int YPOS){
        if (!inRangeOfBoard(XPOS, YPOS)){
            return false;
        }

        if (canMoveUpTo(XPOS, YPOS)){
            return true;
        }
        if (canAttackUpTo(XPOS, YPOS)){
            return true;
        }
        if (canMoveDownTo(XPOS, YPOS)){
            return true;
        }
        if (canAttackDownTo(XPOS, YPOS)){
            return true;
        }
        if (canMoveLeftTo(XPOS, YPOS)){
            return true;
        }
        if (canAttackLeftTo(XPOS, YPOS)){
            return true;
        }
        if (canMoveRightTo(XPOS, YPOS)){
            return true;
        }
        if (canAttackRightTo(XPOS, YPOS)){
            return true;
        }
        if (canEnterTankAt(XPOS, YPOS)){
            return true;
        }
        return false;
    }
   public boolean canMoveToMinusTank(int XPOS, int YPOS){
       if (kingWouldBeInCheck(XPOS, YPOS)){
            return false;
        }
        if (canMoveUpTo(XPOS, YPOS)){
            return true;
        }
        if (canMoveDownTo(XPOS, YPOS)){
            return true;
        }
        if (canMoveLeftTo(XPOS, YPOS)){
            return true;
        }
        if (canMoveRightTo(XPOS, YPOS)){
            return true;
        }
        if (canAttackRightTo(XPOS, YPOS)){
            return true;
        }

       return false;
   }
   public void controlMind(){
       System.out.println("The program compiled again");
        if (numberOfChecks()>=3){
            if (side==Side.WHITE){
                side=Side.BLACK;
                opponentSide = Side.WHITE;
            }
            else{
                side = side.WHITE;
                opponentSide = Side.BLACK;
            }
        }

    }
    public void move(int XPOS, int YPOS){
            boolean killedTank = false;
            if (yourBoard.sideOccupyingSquare(XPOS, YPOS)==opponentSide&&yourBoard.pieceOccupyingSquare(XPOS, YPOS)==Piece.TANK){
                killedTank = true;
            }
            if ((side==ChessApplet.yourSide&&ChessApplet.castle&&canCastle())^(side!=ChessApplet.yourSide&&canCastle())){
                Decision deci = castleRookDecision();
                if (game!=ChessGame.NORMAL&&game!=ChessGame.INSECURE&&yourBoard.level(xPos, yPos)==0){
                    yourBoard.walls.add(new Wall(xPos, yPos));
                }
                xPos = deci.xPos;
                yPos = deci.yPos;
                King king = yourBoard.yourKing(side);
                if (king.xPos>xPos){
                    king.xPos = xPos-100;
                }
                else if (king.xPos<xPos){
                    king.xPos = xPos+100;
                }
                hasMoved=true;
                yourBoard.yourKing(side).hasCastled = true;
                return;
            }
           if (ChessApplet.wed&&canMarry(XPOS, YPOS)){
                 yourBoard.marry(XPOS, YPOS, side);
                 return;
             }
            if (canAttackUpTo(XPOS, YPOS)){
                yourBoard.kill(this, XPOS, YPOS);
            }
            if (canAttackDownTo(XPOS, YPOS)){
               yourBoard.kill(xPos, yPos, XPOS, YPOS);
               if (game==ChessGame.MONKEY||game==ChessGame.PEASANT){
                    yourBoard.corpses.add(new Corpse(Side.WALL, XPOS, YPOS, yourBoard, game));
                }
            }
            if (canAttackLeftTo(XPOS, YPOS)){
                yourBoard.kill(this, XPOS, YPOS);
            }
            if (canAttackRightTo(XPOS, YPOS)){
                yourBoard.kill(xPos, yPos, XPOS, YPOS);
                if (game==ChessGame.MONKEY||game==ChessGame.PEASANT){
                    yourBoard.corpses.add(new Corpse(Side.WALL, XPOS, YPOS, yourBoard, game));
                }
            }
            yourBoard.addWall(xPos, yPos);
            if (yourBoard.level(XPOS, YPOS)<yourBoard.level(xPos, yPos)-1){
                for (int i=0;i<yourBoard.rooks.size();i++){
                    if (yourBoard.rooks.get(i).xPos==xPos&&yourBoard.rooks.get(i).yPos==yPos){
                        yourBoard.rooks.remove(i);
                        break;
                    }
                }
            }
            else{
                if (inDisco(XPOS, YPOS)&&!inDisco(xPos, yPos)){yourBoard.wildCards.add(new WildCard(side, XPOS, YPOS, yourBoard, game, Piece.ROOK));yourBoard.rooks.remove(this);}
                else{
                   if (!killedTank){
                        xPos=XPOS;
                        yPos=YPOS;
                        if (game==ChessGame.ADULTERY){
                            if (yourBoard.blackKing!=null&&xPos==yourBoard.blackKing.xPos&&yPos==yourBoard.blackKing.yPos){
                                yourBoard.rooks.remove(this);
                            }
                            if (yourBoard.whiteKing!=null&&xPos==yourBoard.whiteKing.xPos&&yPos==yourBoard.whiteKing.yPos){
                                yourBoard.rooks.remove(this);
                            }
                            for (int i=0;i<yourBoard.queens.size();i++){
                                if (xPos==yourBoard.queens.get(i).xPos&&yPos==yourBoard.queens.get(i).yPos){
                                    yourBoard.rooks.remove(this);
                                }
                            }
                        }
                    }
                    hasMoved = true;
                }
            }
        }

}