#include <iostream>
#include <GL/glut.h>

#include "CMove.h"
#include "Pieces.h"
#include "CBoard.h"




//////////////
//          //
//   KING   //
//          //
//////////////

char CKing::GetChar() const
{
  return ((GetColor() == WHITE) ? 'K' : 'k');
}

CBasePiece* CKing::GetCopy(CBoard* par) const
{
  CKing* ret = new CKing(par, GetX(), GetY(), GetColor());
  ret->HasMoved = HasMoved;
  return ret;
}

type_piece CKing::GetType() const
{
  return KING;
}


bool CKing::IsCheck(type_color Col) const
{
  if ((Col == EMPTY) || (Col == GetColor()))
    return false;

  char King = ((Col == WHITE) ? 'K' : 'k');

  if (GetX() > 0)
    {
      if ((*GetParent())(GetX()-1, GetY())->GetChar() == King)
        return true;

      if (GetY() > 0)
        {
          if ((*GetParent())(GetX()-1, GetY()-1)->GetChar() == King)
            return true;
        }
      if (GetY() < 7)
        {
          if ((*GetParent())(GetX()-1, GetY()+1)->GetChar() == King)
            return true;
        }
    }

  if (GetX() < 7)
    {
      if ((*GetParent())(GetX()+1, GetY())->GetChar() == King)
        return true;

      if (GetY() > 0)
        {
          if ((*GetParent())(GetX()+1, GetY()-1)->GetChar() == King)
            return true;
        }
      if (GetY() < 7)
        {
          if ((*GetParent())(GetX()+1, GetY()+1)->GetChar() == King)
            return true;
        }
    }

  if (GetY() > 0)
    {
      if ((*GetParent())(GetX(), GetY()-1)->GetChar() == King)
        return true;
    }

  if (GetY() < 7)
    {
      if ((*GetParent())(GetX(), GetY()+1)->GetChar() == King)
        return true;
    }

  return false;
}

bool CKing::IsMoveValid(const CMove& move) const
{
  if ( (move.GetSourceX() != GetX()) || (move.GetSourceY() != GetY()) )
    return false;

  CBoard copy;

  // Check for roque
  if ( (!HasMoved) &&
       (!(GetParent()->IsCheck(GetColor())) &&
        (move.GetDestinationY() == ( (GetColor() == WHITE) ? 0 : 7 )) ) )
    {
      CCastle* castle;

      // right roque
      if (move.GetDestinationX() == 6) 
        {
          if ( ((*GetParent())(7,GetY())->GetType() != CASTLE) ||
               ((*GetParent())(7,GetY())->GetColor() != GetColor()) ||
               ((*GetParent())(5,GetY())->GetColor() != EMPTY) ||
               ((*GetParent())(6,GetY())->GetColor() != EMPTY) )
            return false;

          castle = (CCastle *) (*GetParent())(7,GetY());

          if (castle->GetHasMoved())
            return false;

          copy = *GetParent();
          copy.Move(CMove(4, GetY(), 5, GetY()));

          if (copy.IsCheck(GetColor()))
            return false;

          copy.Move(CMove(5, GetY(), 6, GetY()));

          if (copy.IsCheck(GetColor()))
            return false;

          return true;
        }
      // left roque
      else if (move.GetDestinationX() == 2)
        {
          if ( ((*GetParent())(0,GetY())->GetType() != CASTLE) ||
               ((*GetParent())(0,GetY())->GetColor() != GetColor()) ||
               ((*GetParent())(3,GetY())->GetColor() != EMPTY) ||
               ((*GetParent())(2,GetY())->GetColor() != EMPTY) ||
               ((*GetParent())(1,GetY())->GetColor() != EMPTY) )
            return false;

          castle = (CCastle *) (*GetParent())(0,GetY());

          if (castle->GetHasMoved())
            return false;

          copy = *GetParent();
          copy.Move(CMove(4, GetY(), 3, GetY()));

          if (copy.IsCheck(GetColor()))
            return false;

          copy.Move(CMove(3, GetY(), 2, GetY()));

          if (copy.IsCheck(GetColor()))
            return false;

          return true;
        }
    }


  // Normal moves
  if ( (abs(move.GetDestinationX() - move.GetSourceX()) > 1) ||
       (abs(move.GetDestinationY() - move.GetSourceY()) > 1) )
    return false;

  if ((*GetParent())(move.GetDestinationX(),
                     move.GetDestinationY())->GetColor() == GetColor())
    return false;

  copy = *GetParent();
  copy.Move(move);

  if (copy.IsCheck(GetColor()))
    return false;

  return true;
}

void CKing::MoveAlert(const CMove& move)
{
  if ( (move.GetSourceX() == GetX()) && (move.GetSourceY() == GetY()) )
    {
      HasMoved = true;

      // Check for right rook
      if (move.GetSourceX() - move.GetDestinationX() == -2)
        {
          CBasePiece* piece = (*GetParent())(7,GetY());
          piece->SetX(5);
          ((CCastle*) piece)->SetHasMoved(true);
          (*GetParent())(5,GetY())->SetX(7);
          (*GetParent())(7,GetY()) = (*GetParent())(5,GetY());
          (*GetParent())(5,GetY()) = piece;
        }
      // Check for left rook
      else if (move.GetSourceX() - move.GetDestinationX() == 2)
        {
          CBasePiece* piece = (*GetParent())(0,GetY());
          piece->SetX(3);
          ((CCastle*) piece)->SetHasMoved(true);
          (*GetParent())(3,GetY())->SetX(0);
          (*GetParent())(0,GetY()) = (*GetParent())(3,GetY());
          (*GetParent())(3,GetY()) = piece;
        }
    }
}
