/***********************************************************************
 *
 * Copyright (C) 2010-2017 Innocent De Marchi <tangram.peces@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ***********************************************************************/
//#include <QtGui>
#include <QtWidgets/QGraphicsSceneMouseEvent>


#include "fitxa.h"
#include "frmprincipal.h"
#include "tauler.h"
#include "rellotge.h"

Fitxa::Fitxa(Tauler*  taulerJoc, QGraphicsItem* parent)
         : QGraphicsEllipseItem(0, 0, 32, 32, parent),
         m_taulerJoc(taulerJoc)
{
    m_estat=1; //Estat inicial normal
    p_tipusMoviment=1;
    p_esMou=false;
    p_aillada=false;
    p_nivellAillament=0;
    p_fitxaFinalJoc=false;
    p_fitxaUsadaGeneracioSolitariAtzar=false;
    p_numConjunt=0;
    setFitxaSolitariPersonalitzat(false);
}


void Fitxa::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,  QWidget *){

 QLinearGradient gradientLinear(0, 0, 0, 30);
 gradientLinear.setColorAt(0, QColor(Qt::white));
 gradientLinear.setColorAt(1, QColor(Qt::blue));
 painter->setBrush(gradientLinear);

 QRadialGradient gradientRadial(QPointF( 15,15),15);
 gradientRadial.setColorAt(0, QColor(Qt::white));
 gradientRadial.setColorAt(1, QColor(Qt::lightGray));

 //Marcar les fitxes que son final obligat del joc
 if (p_fitxaFinalJoc){
     painter->setPen(QPen(Qt::darkBlue,3) );
 }
 else if (p_fitxaUsadaGeneracioSolitariAtzar){
     painter->setPen(QPen(Qt::red) );
 }
 else painter->setPen( Qt::NoPen );

//

 switch (m_estat) {
    // case -1: //lloc buit sense dibuixar
    //   painter->setPen( Qt::red);
     case 0: // Lloc buit
       painter->setBrush(gradientRadial);
       painter->drawEllipse(1,1,30,30);
      // painter->setPen( Qt::NoPen );
       break;
     case 1:  //estat normal de la fitxa
       painter->setBrush(gradientLinear);
       painter->drawEllipse(1,1,30,30);
      // painter->setPen( Qt::blue );
       break;
     case 2: //Fitxa Seleccionada per a un moviment
       gradientLinear.setColorAt(1, QColor(Qt::yellow));
       painter->setBrush(gradientLinear);
       painter->drawEllipse(1,1,30,30);
      // painter->setPen( Qt::NoPen );
       break;
     case 3: //destí d'un moviment
       painter->setBrush(gradientRadial);
       painter->setPen(QPen(Qt::red,3));
       painter->drawEllipse(1,1,30,30);
       break;
     case 4: //Fitxa al final de joc resolt
       gradientLinear.setColorAt(1, QColor(Qt::green));
       painter->setBrush(gradientLinear);
       painter->drawEllipse(1,1,30,30);
      // painter->setPen( Qt::NoPen );
       break;
     case 5: //El joc s'ha acabat ja que no hi ha més moviments
         gradientLinear.setColorAt(1, QColor(Qt::red));
         painter->setBrush(gradientLinear);
         painter->drawEllipse(1,1,30,30);
     //  painter->setPen( Qt::NoPen );
       break;
     case 6: //Lloc disponible per posar fitxes (joc personalitzat)
         gradientLinear.setColorAt(1, QColor(Qt::black));         
         painter->setBrush(Qt::NoBrush);
         painter->setPen( Qt::black );
         painter->drawRect(1,1,30,30);
         break;
     default: //estat normal de la fitxa
       painter->setPen( Qt::blue );
       painter->drawEllipse(1,1,30,30);
 }
 /*
 if (p_esMou){
     painter->drawRect(0,0,30,30);
 }
 */

 if (p_aillada){
    painter->setBrush(Qt::magenta);
 }



// if(p_numConjunt>0){

//   if(p_numConjunt==1){
//     painter->setPen( Qt::blue );
//     painter->setBrush(Qt::blue);
//     if(p_distanciaAillament>1){
//       painter->setPen( Qt::darkBlue );
//       painter->setBrush(Qt::darkBlue);
//     }
//     painter->drawEllipse(1,1,30,30);
//    }
//   else if(p_numConjunt==2){
//     painter->setPen(Qt::yellow);
//     painter->setBrush(Qt::yellow);
//     if(p_distanciaAillament>1){
//       painter->setPen(Qt::darkYellow);
//       painter->setBrush(Qt::darkYellow);
//     }
//     painter->drawEllipse(1,1,30,30);
//   }
//   else if(p_numConjunt==3){
//     painter->setPen(Qt::green);
//     painter->setBrush(Qt::green);
//     if(p_distanciaAillament>1){
//       painter->setPen(Qt::darkGreen);
//       painter->setBrush(Qt::darkGreen);
//     }
//     painter->drawEllipse(1,1,30,30);
//   }
//   else if(p_numConjunt==4){
//       painter->setPen(Qt::cyan);
//     painter->setBrush(Qt::cyan);
//     if(p_distanciaAillament>1){
//         painter->setPen(Qt::darkCyan);
//       painter->setBrush(Qt::darkCyan);
//     }
//     painter->drawEllipse(1,1,30,30);
//   }
//   else if(p_numConjunt==5){
//       painter->setPen(Qt::gray);
//     painter->setBrush(Qt::gray);
//     if(p_distanciaAillament>1){
//       painter->setPen(Qt::darkGray);
//       painter->setBrush(Qt::darkGray);
//     }
//     painter->drawEllipse(1,1,30,30);
//   }

//   painter->setPen( Qt::black );
////   painter->drawText(QPoint(5,10),QString("%1 %2").arg(p_numConjunt).arg(p_distanciaAillament));
//   painter->drawText(QPoint(5,10),QString("%1 %2").arg(p_numConjunt).arg(p_distanciaAillamentConjunt));
// }

// if (m_estat==6){
//   painter->setBrush(Qt::NoBrush);
//   painter->setPen( Qt::black );
//   painter->drawRect(1,1,30,30);}
// else{
//   painter->drawEllipse(1,1,30,30);
// }
}

void Fitxa::mousePressEvent(QGraphicsSceneMouseEvent* event) {
    if ( (event->modifiers().testFlag ( Qt::ControlModifier ))
        && !(m_taulerJoc->p_rellotge->rellotgeEnMarxa()) ){
        /* S'està fent una modificació del solitari
         * (de l'ítem Personalitzat o bé d'un joc d'arbre)
         */
        m_taulerJoc->setSolitariModificat(true);
        /* Això és important per permetre que, després
         * de fer les modificacions, sigui possible jugar
         */
        p_fitxaSolitariPersonalitzat=true;
        /* Ara es modifica l'estat de la fitxa i d'altres propietats
         * que permeten controlar el tipus de modificació
         */
        switch (m_estat) {
            case 0:
              if(p_fitxaSolitariPersonalitzat && p_fitxaFinalJoc){
                  p_fitxaFinalJoc=false;
                  setEstat(6);
              }
              else if(p_fitxaSolitariPersonalitzat){
                   setEstat(10);}
              else setEstat(1);
              break;
            case 1:
               if( p_fitxaFinalJoc){
                   p_fitxaFinalJoc=false;
                   setEstat(0);
               }
               else if(p_fitxaSolitariPersonalitzat){
                   setEstat(11);}
               else setEstat(0);
              break;
             case 6:
              setEstat(1);
              setFitxaSolitariPersonalitzat(true);
              break;
        }
    }//final if plantejament problema
    else{
      if ( !m_taulerJoc->p_rellotge->rellotgeEnMarxa()){
          /* 02/01/12
           * Si es clica sobre una fitxa de joc personalitzat,
           * abans de deixar jugar, cal recalcular el joc
           */
          if(p_fitxaSolitariPersonalitzat){
             m_taulerJoc->p_frmPrinci->solitariPersonalitzat_dadesFitxes();
           return;
          }
          /* 02/01/12
           * Afegida aquesta condició per assegurar que en els jocs personalitzats
           * si es juga directament, s'actualitzi el nombre de fitxes del joc.
           * La condició està per evitar que es posi "en marxa" el joc
           * quan no hi ha fitxes actives
           */
          if( (m_estat > -1) && (m_estat < 6) ){
            m_taulerJoc->configuracioActual(true);
            m_taulerJoc->p_rellotge->iniciaRellotge();
            m_taulerJoc->p_movimentsUndoStack->clear();
           }
          }

      switch (m_estat) {
      case 3: // Lloc buit final d'un moviment. La fitxa és el destí d'un moviment que cal fer
          ferMoviment();
          //Eliminam marques de moviments
          m_taulerJoc->eliminaMarquesMoviments(m_coordenades);
          break;
      case 1: //Fitxa activa. Cal iniciar un moviment
          setEstat(2);
          calculaMovimentsFitxa();
          m_taulerJoc->marcaMovimentsFitxa(movimentsFitxa);
          break;
      case 2: // Fitxa seleccionada prèviament per a un moviment. S'anula la selecció
          setEstat(1);
          //Eliminam marques de moviments anteriors
          m_taulerJoc->eliminaMarquesMoviments(m_coordenades);
          break;
   }
}
QGraphicsEllipseItem::mousePressEvent(event);
}

bool Fitxa::esPotMoure(){
    calculaMovimentsFitxa();
    return movimentsFitxa.size()>0;
}

/*
  Calcula els possibles moviments de la fitxa i els conserva
  a la llista movimentsFitxa
  */
void Fitxa::calculaMovimentsFitxa(){
    movimentsFitxa.clear();
    int estatFitxaFinal = 0;
    int estatFitxaBotada = 1;
    switch (p_tipusMoviment) {
     case 2:
         estatFitxaBotada = 0;
         break;
     case 5:
        estatFitxaBotada = 0;
        break;
     }
    //Eliminam marques de moviments anteriors
    m_taulerJoc->eliminaMarquesMoviments(m_coordenades);
    for (int fila = -1; fila < 2; ++fila) {
                for (int columna = -1; columna < 2; ++columna) {
                    QPoint coord(fila,columna);
                    if( ( (m_taulerJoc->estatFitxaJoc(coord*2+m_coordenades)==estatFitxaFinal) &&
                        (m_taulerJoc->estatFitxaJoc(coord+m_coordenades)==estatFitxaBotada) ) )
                        {
                        //Això per garantir que la fitxa destí està a la mateixa fila o columna que la clicada
                        if(  (columna*2+m_coordenades.x()==m_coordenades.x()
                            || fila*2+m_coordenades.y()==m_coordenades.y()) &&  (p_tipusMoviment < 3)  ) {
                           movimentsFitxa.append(coord*2+m_coordenades)  ;
                           }
                        //estan permesos els movimens en diagonal
                        else if (p_tipusMoviment>=3){
                           movimentsFitxa.append(coord*2+m_coordenades) ;
                        }
                    }
                }
            }
}

/*
  Realitza un moviment del qual la fitxa actual és el destí
  */
void Fitxa::ferMoviment(){
    int estatFitxaInicial =2; //fitxa marcada com a destí del moviment
    int estatFitxaBotada = 1;
    switch (p_tipusMoviment) {
     case 2:
         estatFitxaBotada = 0;
         break;
     case 5:
        estatFitxaBotada = 0;
        break;
     }
    for (int fila = -1; fila < 2; ++fila) {
                for (int columna = -1; columna < 2; ++columna) {
                    QPoint coord(fila,columna);
                    if( ( (m_taulerJoc->estatFitxaJoc(coord*2+m_coordenades)==estatFitxaInicial) &&
                        (m_taulerJoc->estatFitxaJoc(coord+m_coordenades)==estatFitxaBotada) ) )
                        {
                        //Això per garantir que la fitxa destí està a la mateixa fila o columna que la clicada
                        if(  (columna*2+m_coordenades.x()==m_coordenades.x()
                            || fila*2+m_coordenades.y()==m_coordenades.y()) &&  (p_tipusMoviment < 3) ){
                          m_taulerJoc->ferMoviment( (coord*2+m_coordenades).x()*100+(coord*2+m_coordenades).y(),
                                                 (coord+m_coordenades).x()*100+(coord+m_coordenades).y(),
                                                 m_coordenades.x()*100+m_coordenades.y());
                         }
                        //estan permesos els movimens en diagonal
                        else if (p_tipusMoviment>2){
                           m_taulerJoc->ferMoviment( (coord*2+m_coordenades).x()*100+(coord*2+m_coordenades).y(),
                                                 (coord+m_coordenades).x()*100+(coord+m_coordenades).y(),
                                                 m_coordenades.x()*100+m_coordenades.y());
                        }
                    }
                }
            }
}

void Fitxa::calculaMovimentsPosiblesFitxa(){
    movimentsPossibles.clear();
    for (int fila = -1; fila < 2; ++fila) {
        for (int columna = -1; columna < 2; ++columna) {
            QPoint coord(fila,columna);
            if(  (m_taulerJoc->estatFitxaJoc(coord*2+m_coordenades)>-1) &&
                 (m_taulerJoc->estatFitxaJoc(coord+m_coordenades)>-1)  &&
                 (coord != QPoint(0,0)))
            {
                //Això per garantir que la fitxa destí està a la mateixa fila o columna que la clicada
                if(  (columna*2+m_coordenades.x()==m_coordenades.x()
                    //  || fila*2+m_coordenades.y()==m_coordenades.y()) &&  (p_tipusMoviment != 3) ) {
                    || fila*2+m_coordenades.y()==m_coordenades.y()) &&  (p_tipusMoviment < 3) ) {
                    //posam l'index de la fitxa botada i de la fitxa final
                    movimentsPossibles.append(QPoint(
                                                  (coord+m_coordenades).x()*100+(coord+m_coordenades).y(),
                                                  (coord*2+m_coordenades).x()*100+(coord*2+m_coordenades).y() ));
                }
                //estan permesos els moviments en diagonal
                else if (p_tipusMoviment>=3){//posam l'index de la fitxa botada i de la fitxa final
                    movimentsPossibles.append(QPoint(
                                                  (coord+m_coordenades).x()*100+(coord+m_coordenades).y(),
                                                  (coord*2+m_coordenades).x()*100+(coord*2+m_coordenades).y() ));

                }
            }
        }
    }
 setPreferenciaMoure(movimentsPossibles.count());
 /* 21/06/12
  * Les fitxes que són final de joc
  * tendràn preferència major
  * (seran les darreres en intentar moure)
  */
 if(p_fitxaFinalJoc){
     setPreferenciaMoure(1000);
 }
}

/*************************************************/
//GESTIÓ DE LES PROPIETATS DE LA FITXA

/*
  Lectura de la propietat estat
  */
/*
int Fitxa::estat() const
{
  return m_estat;
}
*/
/*
  Estableix el valor de l'estat
  */
void Fitxa::setEstat( int nouValor , bool canviarFitxaFinalJoc)
{
    //Fitxes que són final del joc
    // obligatori
    if ( (nouValor==10 ) || (nouValor==11)
         || (nouValor==-11)){
        setFitxaFinalJoc(true);
        //es modifica el paràmetre pel
        //valor estandar
        switch (nouValor) {
          case 10:
            nouValor=0;
            break;
          case 11:
            nouValor=1;
            break;
          case -11:
            nouValor=-1;
            break;
        }
    }
    /* 26/01/13 No està clar que això sigui necessari
     * (de fet, ara no hi ha cap cridada que es faci amb true
     */
    else if(canviarFitxaFinalJoc){ setFitxaFinalJoc(false);};

  if( (nouValor < -1)  || (nouValor >  6))
    m_estat = 0;

  //17/12/12 Eliminat per permetre marcar les fitxes
  //com a final de joc en el solitari personalitzat
 // if( (m_estat != nouValor) || (nouValor==0) ){
      m_estat = nouValor;
     //Si la fitxa es "mou", llavors reiniciam l'aïllament
     if(m_estat==0) {setFitxaAillada(false);}
     update();//}
}

QPoint Fitxa::coordenades() const{
    return m_coordenades;
}
/*
  Estableix les coordenades de la fitxa en el joc
  */
void  Fitxa::setCoordenades (QPoint coordenades){
    m_coordenades = coordenades;
    update();
   setToolTip(QString("(%1,%2)").arg(m_coordenades.x()).
                      arg(m_coordenades.y()));
}

/*
  Indica la preferència en moure la fitxa en el joc
  */
void Fitxa::setPreferenciaMoure(int preferencia){
    if( p_preferenciaMoure != preferencia ){
        p_preferenciaMoure = preferencia;}
}

/*
           Controla el tipus de moviment
           1: moviment directe (l'habitual del joc)
           2: moviment invers
           3: moviment en direcció perpendicular i diagonal
           4: proposta de problema
           5: moviment en direcció perpendicular/diagonal i invers
              (nou per a la generació a l'atzar)
           */
void Fitxa::setTipusMoviment (int nouTipus){
  if( (nouTipus < 0)  || (nouTipus >  5))
    p_tipusMoviment = 0;
  if( p_tipusMoviment != nouTipus ){
      p_tipusMoviment = nouTipus;}
}

void Fitxa::setEsMou(bool valor){
    if(p_esMou != valor){
      p_esMou=valor;
    }
}

/* Canvia la propietat fitxaFinalJoc que
 * determina si la fitxa és una posició
 * final del joc
 */
void Fitxa::setFitxaFinalJoc(bool valor){
    if (p_fitxaFinalJoc != valor){
      p_fitxaFinalJoc=valor;
    }
}

/* Canvia la propietat fitxaUsadaGeneracioSolitariAtzar
 * que determina si la fitxa s'ha fet servir en la generació
 * d'un solitari a l'atzar
 */
void Fitxa::setfitxaUsadaGeneracioSolitariAtzar(bool valor){
    if (p_fitxaUsadaGeneracioSolitariAtzar != valor){
      p_fitxaUsadaGeneracioSolitariAtzar=valor;
    }
}

/* Canvia el valor que controla si la fitxa
 * s'està fent servir a un solitari personalitzat
 */
void Fitxa::setFitxaSolitariPersonalitzat(bool valor){
    p_fitxaSolitariPersonalitzat=valor;
   /* if(valor){
    qDebug("S'ha marcat una fitxa com a personalitzada");}
    else qDebug("S'Ha marcat una fitxa com a NO personalitzada");*/
}

void Fitxa::setFitxaAillada(bool valor){
    if(p_aillada != valor){
        p_aillada=valor;
        p_nivellAillament=0;
        update();}
  if (p_aillada){incrementaNivellAillament();}
}


void Fitxa::setNivellAillament( int valor){
    if(p_nivellAillament != valor){
        p_nivellAillament=valor;}
  }

void Fitxa::incrementaNivellAillament(){
    ++p_nivellAillament;
}

void Fitxa::setConjuntAillament(int numConjunt){
    p_numConjunt=numConjunt;
    update();
}

void Fitxa::setDistanciaAillament(int distancia){
  if(p_distanciaAillament != distancia){
    p_distanciaAillament=distancia;
    update();}
}


void Fitxa::setDistanciaAillamentConjunt(int distancia){
    if(p_distanciaAillamentConjunt != distancia){
      p_distanciaAillamentConjunt=distancia;
//      qDebug("%d", p_distanciaAillamentConjunt);
      update();
  }
}
