/***************************************************************************
 *   Copyright (C) 2005 by Tavarez Arnaud Bakoula                          *
 *   tbakoula@yahoo.fr                                                     *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "sitemanager.h"
#include "site.h"
#include "siterow.h"
#include "dragpion.h"
#include "utilities.h"

SiteManager::SiteManager( uint r, uint c, QWidget* parent, const char* name )
    :  CellManager( r, c, parent, name )
{
    activeCell = 0;
    setMinimumSize( sizeHint() );
    setAcceptDrops( TRUE );
}

SiteManager::~SiteManager()
{
    activeCell = 0;
}

/**
   This function must be called after the instanciation of the
   widget. So it will create the appropriate type of cells it
   has to manage.
 */
void SiteManager::createRows()
{
    for ( uint i=0; i<row; i++ )
    {
      CellRow* cellrow = new SiteRow( i, col );
      cellrow_list->push_back( cellrow );
      computePosition( cellrow, i );
      cellrow->createCells();
    }
    activeRow = (SiteRow*) cellrow_list->at(row-1);
}

/**
   This function adds the specified number of rows.
 */
void SiteManager::appendCellRow( uint ap )
{
    for ( uint i=0; i<ap; i++ )
    {
      CellRow* cellrow = new SiteRow( row+i, col );
      cellrow_list->push_back( cellrow );
      computePosition( cellrow, row+i );
      cellrow->createCells();
    }
    row += ap;
    setMinimumSize( sizeHint() );
    placeRows();
    // the widget must be redrawn
    refreshPixmap();
}

/**
   Installs the content of the row \a cellrow in the active row
   of this manager.
   The cellrow argument must be of type SiteRow for the expected
   behaviour. If it is not the case there's no warranty on its
   behaviour.
 */
bool SiteManager::installActiveRow( CellRow* cellrow )
{
    uint i;
    uint dim = activeRow->getDim();

    if( dim != cellrow->getDim() )
      return false;

    for ( i=0; i < dim; i++ )
    {
      Site* site1 = (Site*) cellrow->getCellAt( i );
      Site* site2 = (Site*) activeRow->getCellAt( i );
      site2->setColor( site1->getColor() );
    }
    dirty = true;
    refreshPixmap();
    return true;
}

void SiteManager::paintCell( Cell* cell, QPainter* p )
{
    cell->draw( p, cell->rect().topLeft() );
}

void SiteManager::drawReady( Cell* )
{
}

/**
 *  This reimplementation is used to start the displacement the piece of a cell
 *  to another one or to remove it.
 */
void SiteManager::mousePressEvent( QMouseEvent* event )
{
    if ( read_only )
      return;

    delivered = FALSE;
    SiteRow* cellrow = (SiteRow*) getCellRowAt( event->x(), event->y() );

    if ( activeRow == cellrow )
    {
      activeCell = (Site*) activeRow->getCellAt( event->x(), event->y() );
      if ( activeCell && !activeCell->isEmpty() )
      {
        dragging = TRUE;
      }
    }
}

void SiteManager::mouseMoveEvent( QMouseEvent* )
{
    if ( read_only )
      return;

    if ( dragging /*activeCell*/)
    {
      DragPion* d = new DragPion( activeCell->getColor(), this, "pion" );
      d->setPixmap( colorToPixmap( activeCell->getColor() ), QPoint(8,8) );
      d->dragMove();

      if ( !delivered )  // has it been delivered
      {
        activeCell->setColor( Shade );
        activeCell->empty( TRUE );
        dirty = true;
        delItem();
        refreshPixmap();
      }
      activeCell = 0;
      dragging = FALSE;
    }
}

void SiteManager::mouseReleaseEvent( QMouseEvent* )
{
    dragging = FALSE;
    activeCell = 0;
}

void SiteManager::dragEnterEvent( QDragEnterEvent* event )
{
    if ( read_only )
      return;
    dirty = true;
    event->accept( DragPion::canDecode(event) );
}

void SiteManager::dropEvent( QDropEvent* event )
{
    uint color;
    // where the mouse was it dropped ?
    int x = event->pos().x();
    int y = event->pos().y();
    // on which cellrow ?
    SiteRow* cellrow = (SiteRow*) getCellRowAt( x, y );

    if ( !DragPion::decode( event, color ) )
    {
      activeCell = 0;
      return;
    }

    // if the row is the active one we can
    // continue to process the event
    if ( cellrow && cellrow == activeRow )
    {
      // we retrieve the cell at the specified position
      Site* cell = (Site*) activeRow->getCellAt( x, y );

      // can the cell receive the drag ?
      if ( cell )
      {
        if ( cell->isEmpty() )
        {
          // the drag comes from another site
          if( activeCell && cell != activeCell )
          {
            activeCell->setColor( Shade );
            activeCell->empty( TRUE );
            delivered = TRUE;
            // the internal counter must NOT be modified
            // and the ready state must be displayed
          }
          else{ /* the internal counter MUST be modified*/
            addItem();
          }
          cell->setColor( color );
          cell->empty( FALSE );
          // the cell must be drawn
          dirty = true;
          refreshPixmap();
        }
        else
        {
          // we cancel the operation
          delivered = TRUE;
        }
      }
      else if( !cell && activeCell )
      {
        // we want to remove the piece from the activeCell
        // cause we drag it on a invalid cell
        activeCell->setColor( Shade );
        activeCell->empty( TRUE );
        dirty = true;
        refreshPixmap();
      }
    }
    dirty = true;
}

AnswerManager::AnswerManager( uint c, QWidget* parent, const char* name )
    : SiteManager( 1, c, parent, name ), hidden(true)
{
    showLabels( FALSE, TRUE );
}

AnswerManager::~ AnswerManager()
{
}

void AnswerManager::hideMe( bool hd )
{
    hidden = hd;
    dirty = true;
    refreshPixmap();
}

void AnswerManager::drawCellContent( QPainter* p )
{
    if ( !hidden )
      CellManager::drawCellContent( p );
    else
      drawHidden( p );
}

void AnswerManager::drawHidden( QPainter* painter )
{
    if ( cellrow_list->empty() )
      return;

    cellrow_iterator it = cellrow_list->begin();
    for ( uint i=0; i<col; i++ )
    {
      Cell* cell = (*it)->getCellAt( i );
      painter->drawPixmap( cell->rect().topLeft(), theIconLoader->loadIcon( "question", KIcon::Toolbar, icon_res ) );
    }
}
