/* PlayingDesk.java --
 Copyright (C) 2005 Free Software Foundation, Inc.

 This file is part of GNU Classpath.

 GNU Classpath 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, or (at your option)
 any later version.

 GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301 USA.

 Linking this library statically or dynamically with other modules is
 making a combined work based on this library.  Thus, the terms and
 conditions of the GNU General Public License cover the whole
 combination.

 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */


package gnu.classpath.examples.CORBA.swing.x5;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.swing.JComponent;

import org.omg.CORBA.ORB;

/**
 * Manages actions, related to the game rules and also does all painting.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class PlayingDesk
  extends JComponent
  implements MouseListener, State
{
  /**
   * Use serialVersionUID for interoperability.
   */
  private static final long serialVersionUID = 1;

  /**
   * Indicates that the field point state is the red oval.
   */
  public static final int RED = 0;

  /**
   * Indicates that the field point state is the black cross.
   */
  public static final int BLACK = 1;

  /**
   * Indicates that the field point state is the hint, suggested by the fan.
   */
  public static final int HINT = 2;

  /**
   * The access to the main frame methods.
   */
  ClientFrame frame;

  /**
   * The access to the player communicator.
   */
  PlayerImpl player;

  /**
   * The game manager.
   */
  GameManager manager;

  /**
   * The player ORB.
   */
  ORB orb;

  /**
   * The player IOR.
   */
  String ior;

  /**
   * True if the player ORB started ok.
   */
  boolean ok;

  /**
   * The grid spacing.
   */
  static int W = 16;

  /**
   * The radius of the dots being painted.
   */
  static int R = W / 3;

  /**
   * The collection of the red dots.
   */
  ArrayList reds = new ArrayList();

  /**
   * The collection of the black dots.
   */
  ArrayList blacks = new ArrayList();

  /**
   * The array of hints.
   */
  ArrayList hints = new ArrayList();

  /**
   * When the game is completed, obtains the value of the two end points of the
   * created line.
   */
  Point[] endOfGame;

  public PlayingDesk()
  {
    try
      {
        player = new PlayerImpl();
        player.desk = this;

        OrbStarter.startPlayer(player, this);

        jbInit();
      }
    catch (Exception e)
      {
        e.printStackTrace();
      }
  }

  /**
   * Paint this component.
   */
  public void paintComponent(Graphics g)
  {
    int w = getWidth();
    int h = getHeight();

    g.setColor(Color.white);
    g.fillRect(0, 0, w, h);

    drawGrid(w, h, g);
    drawFigures(g);
  }

  /**
   * Check maybe a game is finished after setting the point N
   */
  public Point[] checkFinished(Collection x, Point N)
  {
    Iterator iter = x.iterator();
    Point p;

    // The victory, if happens, must occur inside these boundaries:
    int ax = N.x - 5;
    int bx = N.x + 5;

    int ay = N.y - 5;
    int by = N.y + 5;

    while (iter.hasNext())
      {
        p = (Point) iter.next();

        if (p.x > ax && p.x < bx && p.y > ay && p.y < by)
          {
            // Check the vertical line down
            if (pointPresent(p.x, p.y + 1, x))
              if (pointPresent(p.x, p.y + 2, x))
                if (pointPresent(p.x, p.y + 3, x))
                  if (pointPresent(p.x, p.y + 4, x))
                    return new Point[] { p, new Point(p.x, p.y + 4) };

            // Check the horizontal line left
            if (pointPresent(p.x + 1, p.y, x))
              if (pointPresent(p.x + 2, p.y, x))
                if (pointPresent(p.x + 3, p.y, x))
                  if (pointPresent(p.x + 4, p.y, x))
                    return new Point[] { p, new Point(p.x + 4, p.y) };

            // Check the diagonal line right down.
            if (pointPresent(p.x + 1, p.y + 1, x))
              if (pointPresent(p.x + 2, p.y + 2, x))
                if (pointPresent(p.x + 3, p.y + 3, x))
                  if (pointPresent(p.x + 4, p.y + 4, x))
                    return new Point[] { p, new Point(p.x + 4, p.y + 4) };

            // Check the diagonal line left down.
            if (pointPresent(p.x - 1, p.y + 1, x))
              if (pointPresent(p.x - 2, p.y + 2, x))
                if (pointPresent(p.x - 3, p.y + 3, x))
                  if (pointPresent(p.x - 4, p.y + 4, x))
                    return new Point[] { p, new Point(p.x - 4, p.y + 4) };
          }
      }
    return null;
  }

  /**
   * Called when the "end of the game" situation is detected.
   */
  public void drawFinishLine(int xa, int ya, int xb, int yb, Graphics g)
  {
    g.setColor(Color.blue);

    int hW = W / 2;
    g.drawLine(xa * W + hW, ya * W + hW, xb * W + hW, yb * W + hW);
  }

  /**
   * Check for the presence of the given point in the collection.
   */
  public final boolean pointPresent(int x, int y, Collection in)
  {
    Iterator iter = in.iterator();
    Point p;
    while (iter.hasNext())
      {
        p = (Point) iter.next();
        if (p.x == x && p.y == y)
          return true;
      }
    return false;
  }

  public void drawGrid(int w, int h, Graphics g)
  {
    g.setColor(Color.lightGray);

    // Draw vertical lines:
    for (int x = 0; x < w; x += W)
      {
        g.drawLine(x, 0, x, h);
      }

    // Draw horizontal lines:
    for (int y = 0; y < h; y += W)
      {
        g.drawLine(0, y, w, y);
      }
      
    g.setColor(Color.gray);
    g.drawRect(0,0, frame.DESK_SIZE.width, frame.DESK_SIZE.height);
    g.drawRect(0,0, frame.DESK_SIZE.width+3, frame.DESK_SIZE.height+3);    
  }

  public void drawFigures(Graphics g)
  {
    g.setColor(Color.red);
    drawDots(reds, g, RED);

    g.setColor(Color.black);
    drawDots(blacks, g, BLACK);

    g.setColor(Color.lightGray);
    drawDots(hints, g, HINT);

    if (endOfGame != null)
      drawFinishLine(endOfGame[0].x, endOfGame[0].y, endOfGame[1].x,
        endOfGame[1].y, g);
  }

  public Point makePoint(int x, int y)
  {
    return new Point(x / W, y / W);
  }

  /**
   * Draw a collection of dots (the collor must be set before calling the
   * method).
   */
  public void drawDots(Collection dots, Graphics g, int mode)
  {
    Iterator iter = dots.iterator();
    int x;
    int y;

    int hW = W / 2;
    int RR = R * 2;
    int hR = R / 2;
    Point p;
    while (iter.hasNext())
      {
        p = (Point) iter.next();
        x = p.x * W + hW;
        y = p.y * W + hW;

        if (mode == RED)
          g.drawOval(x - R, y - R, RR, RR);
        else if (mode == BLACK)
          {
            g.drawLine(x - R, y - R, x + R, y + R);
            g.drawLine(x - R, y + R, x + R, y - R);
          }
        else
          {
            // Hint.
            g.drawOval(x - hR, y - hR, R, R);
          }
      }
  }

  private void jbInit()
    throws Exception
  {
    addMouseListener(this);
  }

  public void mouseClicked(MouseEvent e)
  {
    try
      {
        int state = player.get_current_state();

        // Check if the state is correct.
        if (state == I_WAIT_FOR_YOUR_MOVE)
          {
            frame.talk(Color.black,
              "It is now time for our partner's move, not ours. Please wait.");
          }
        else if (state == DISCONNECTED)
          {
            frame.talk(Color.black,
              "We are not connected to the playing partner yet.");
          }
        else if (state == I_HAVE_LOST)
          {
            frame.talk(Color.black,
              "We have already lost this battle, but why not to try again?");
          }
        else if (state == I_HAVE_WON)
          {
            frame.talk(Color.black,
              "The victory is ours, nothing more to do here.");
          }
        else if (player.partner == null)
          frame.talk(Color.black, "No other player so far.");
        else
          {
            int x = e.getX();
            int y = e.getY();

            if (x>frame.DESK_SIZE.width ||
                y>frame.DESK_SIZE.height)
            {
              frame.talk(Color.black,"Outside the game area.");
              return;
            }

            Point p = makePoint(x, y);

            // Ignore clicks on the occupied cells.
            if (pointPresent(p.x, p.y, reds)
              || (pointPresent(p.x, p.y, blacks)))
              {
                frame.talk(Color.black,
                  "This is against the rules, select the unoccupied cell.");
                return;
              }

            reds.add(p);

            endOfGame = checkFinished(reds, p);
            repaint();

            if (endOfGame != null)
              {
                frame.talk(Color.red, "Our move " + p.x + "-" + p.y
                  + " and we win!");
                player.set_current_state(I_HAVE_WON);
              }
            else
              {
                frame.talk(Color.black, "Our move " + p.x + "-" + p.y
                  + ". Waiting for the other side move...");
                player.set_current_state(I_WAIT_FOR_YOUR_MOVE);
              }

            player.partner.receive_move(p.x, p.y, endOfGame);
          }
      }
    catch (RemoteException ex)
      {
        // We will print the exception because this is a demo application
        // that may be modified for learning purposes.
        ex.printStackTrace();
      }
  }

  /**
   * Handle the move of the other playing side.
   */
  public void friendsMove(int x, int y, Point[] victory)
  {
    try
      {
        int state = player.get_current_state();
        if (state != I_WAIT_FOR_YOUR_MOVE || pointPresent(x, y, blacks))
          {
            stateFailed("Move " + x + "-" + y);
          }
        else
          {
            blacks.add(new Point(x, y));

            if (victory != null)
              {
                frame.talk(Color.red,
                  " We have lost this time, unfortunately..");
                player.set_current_state(I_HAVE_LOST);
                endOfGame = victory;
              }
            else
              {
                frame.talk(Color.black, "Partner goes " + x + "-" + y
                  + ". Your move?");
                player.set_current_state(I_THINK);
              }            
            repaint();            
          }
      }
    catch (RemoteException rex)
      {
        rex.printStackTrace();
      }
  }

  /**
   * Prepare for the new game.
   */
  public void reset()
  {
    blacks.clear();
    reds.clear();
    hints.clear();
    endOfGame = null;
    repaint();
  }

  public void mouseEntered(MouseEvent m)
  {
    // Nothing to do.
  }

  public void mousePressed(MouseEvent m)
  {
    // Nothing to do.
  }

  public void mouseReleased(MouseEvent m)
  {
    // Nothing to do.
  }

  public void mouseExited(MouseEvent m)
  {
    // Nothing to do.
  }

  /**
   * The systems detected the error conditions. The game cannot continue (the
   * chat is still possible).
   */
  public void stateFailed(String reason)
  {
    try
      {
        player.receive_chat(ChatConstants.REMOTE_PLAYER,
          "Wrong move, game cannot continue (our state was "
            + player.get_current_state() + ")");
        frame.talk(Color.red, "The remote side violates communicating rules.");
        player.set_current_state(State.ERROR);
      }
    catch (RemoteException ex)
      {
        // We will print the exception because this is a demo application
        // that may be modified for learning purposes.
        ex.printStackTrace();
      }
  }
}