///////////////////////////////////////////////////////////////////////////////
// $Id: PlayingDeck.cxx,v 1.1 1995/01/08 06:45:30 bmott Exp $
///////////////////////////////////////////////////////////////////////////////
//
// PlayingDeck.cxx - Oonsoo playing deck
//
//
// Bradford W. Mott
// Copyright (C) 1994
// December 11,1994
//
///////////////////////////////////////////////////////////////////////////////
// $Log: PlayingDeck.cxx,v $
// Revision 1.1  1995/01/08  06:45:30  bmott
// Initial revision
//
///////////////////////////////////////////////////////////////////////////////

#include "UIApplication.hxx"
#include "Sprite.hxx"
#include "SpriteCollection.hxx"
#include "Card.hxx"
#include "PlayingDeck.hxx"
#include "PlainDeck.hxx"
#include "DeckMoveCommand.hxx"

///////////////////////////////////////////////////////////////////////////////
// Construct an empty deck of playing cards
///////////////////////////////////////////////////////////////////////////////
PlayingDeck::PlayingDeck(ContainerWidget* parent, const char *const widgetName,
    int x, int y, int width, int maxHeight, SpriteCollection* sprites,
    Command* command)
    : Deck(parent, widgetName, x, y, width, maxHeight, sprites),
      myCommand(command)
{
  // Update my view
  updateView();
}

///////////////////////////////////////////////////////////////////////////////
// Construct a partial deck of playing cards
///////////////////////////////////////////////////////////////////////////////
PlayingDeck::PlayingDeck(ContainerWidget* parent, const char *const widgetName,
    int x, int y, int width, int maxHeight, SpriteCollection* sprites,
    LinkedList<Card>* cards, Command* command)
    : Deck(parent, widgetName, x, y, width, maxHeight, sprites),
      myCommand(command)
{
  // Move each of the cards from the LinkedList into myListOfCards
  for(Card* card = cards->remove(); card != (Card*)0; card = cards->remove())
  {
    myListOfCards.prepend(card);
  }

  // Update my view
  updateView();
}

///////////////////////////////////////////////////////////////////////////////
// Destructor
///////////////////////////////////////////////////////////////////////////////
PlayingDeck::~PlayingDeck()
{ 
  // Free my command
  delete myCommand;
}

///////////////////////////////////////////////////////////////////////////////
// See if the deck consists of one complete suit in order
///////////////////////////////////////////////////////////////////////////////
int PlayingDeck::checkCompleteSuitInOrder()
{
  // There has to be 4 cards on the deck for it to be complete
  if(myListOfCards.size() != 4)
    return(0);

  Card* top = myListOfCards.first();
  for(Card* card = myListOfCards.next(); card != NULL; card = myListOfCards.next())
  {
    // Suites have to be the same
    if(top->suite() != card->suite()) 
      return(0);

    // Top card has to be the same or next priority in the suite
    if((top->priority() != card->priority()) &&
       (top->priority() != (card->priority() + 1)))
        return(0); 

    top = card;
  }
  return(1);
}


///////////////////////////////////////////////////////////////////////////////
// See if these cards form a legal oonsoo move
///////////////////////////////////////////////////////////////////////////////
int PlayingDeck::checkValidAddition(LinkedList<Card>* cards)
{
  // Get the top card
  Card* top = myListOfCards.tail();

  for(Card* card = cards->first(); card != NULL; card = cards->next())
  {
    if(top == NULL)
    { 
      // Only highest level cards can be added to an empty deck
      if(card->priority() != 4)
        return(0);
    }
    else
    {
      // Suites have to be the same
      if(top->suite() != card->suite()) 
        return(0);

      // Top card has to be the same or next priority in the suite
      if((top->priority() != card->priority()) &&
         (top->priority() != (card->priority() + 1)))
        return(0); 
    }
    top = card;
  }
  return(1);
}


///////////////////////////////////////////////////////////////////////////////
// Called whenever an event arrives for me (I need to override the default)
///////////////////////////////////////////////////////////////////////////////
void PlayingDeck::handleEvent(XEvent* event)
{
  if ((event->type == ButtonPress) && (event->xbutton.button == Button1))
  {
    int done = 0;
    int t;

    // Return if there are no cards to move
    if (myListOfCards.size() == 0)
      return;

    // Calculate the root x and y coordinate of my parent widget
    int parentRootX = event->xbutton.x_root - event->xbutton.x - x();
    int parentRootY = event->xbutton.y_root - event->xbutton.y - y();

    // Calculate how many cards to remove from myself
    int num = myListOfCards.size() - cardIndexFromCoordinate(event->xbutton.y);

    // Remove cards from myself and place them in a temporary list
    LinkedList<Card> tmpListOfCards;
    for(t = 0; t < num; ++t)
    {
      tmpListOfCards.prepend(myListOfCards.remove());
    }
  
    // Create a plain deck with the temporary list of cards
    PlainDeck* plainDeck = new PlainDeck(myParent, "plainDeck",
        x() + event->xbutton.x - (width()/2), y() + event->xbutton.y - 24, 
        width(), myMaximumHeight, mySprites, &tmpListOfCards); 
    plainDeck->manage();

    // Update my view
    updateView();

    while(!done)
    {
      XEvent event;

      XNextEvent(application->display(), &event);

      switch(event.type)
      {
        case MotionNotify:
          int newX = event.xmotion.x_root - parentRootX - width()/2;
          int newY = event.xmotion.y_root - parentRootY - 24;

          plainDeck->move(newX, newY);
          break; 

        case ButtonRelease:
          done = 1;
          break;

        default:
          application->dispatchEvent(&event);
          break;
      }
    }

    // Build the command arguments
    DeckMoveCommandArguments args(this, plainDeck);
    
    // Execute my command passing the arguments
    myCommand->execute(&args);
  }
}

