package fr.umlv.remix;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

import fr.umlv.remix.*;

public class RemixTest {

  static class TestItem {
    /*
     * Our TestItem will be represented by a square centered at a given position
     */
    private final Point2D center;
    private final int width;
    private final Color[] colors = { Color.pink, Color.blue };
    private int currentColor;

    public Color getColor() {
      return colors[currentColor];
    }

    public TestItem(int x, int y, int w) {
      center = new Point(x, y);
      width = w;
    }

    public int getWidth() {
      return width;
    }

    public Point2D getLocation() {
      return center;
    }

    public void swap() {
      currentColor = (currentColor == 0 ? 1 : 0);
    }
  }

  static class TestManager implements ItemManager<TestItem> {
    @Override
    public void draw(Graphics2D g, TestItem item) {
      Point2D pos = item.getLocation();
      int x = (int) pos.getX(), y = (int) pos.getY(), w = item.getWidth();
      g.setColor(item.getColor());
      g.fillRect(x - w / 2, y - w / 2, w, w);
      g.setColor(Color.white);
      g.drawLine(x - w / 2, y - w / 2, x + w / 2, y + w / 2);
    }

    @Override
    public boolean intersects(Shape selection, TestItem item) {
      return selection.contains(item.getLocation());
    }

    @Override
    public boolean contains(Point2D location, TestItem item) {
      return squareDistance(location, item.getLocation()) <= item.getWidth()
          * item.getWidth();
    }

    private static double squareDistance(Point2D p1, Point2D p2) {
      double dx = p1.getX() - p2.getX();
      double dy = p1.getY() - p2.getY();
      return dx * dx + dy * dy;
    }

    @Override
    public boolean isContained(Shape arg0, TestItem arg1) {
      Point2D pos = arg1.getLocation();
      int x = (int) pos.getX(), y = (int) pos.getY(), w = arg1.getWidth();
      return arg0.contains(new Rectangle(x - w / 2, y - w / 2, w, w));
    }
  }

  public static void main(String[] args) {
    Random random = new Random();
    ArrayList<TestItem> testItemList = new ArrayList<TestItem>();
    /*
     * Randomly position 25 TestItems in the Arena zone (defined afterwards)
     */
    for (int i = 0; i < 25; i++) {
      testItemList.add(new TestItem(random.nextInt(300), random.nextInt(200),
          10));
    }

    TestManager manager = new TestManager();

    /*
     * Call the run method of Application providing an initial item Collection,
     * an item manager and an ApplicationRunnable
     */
    Application.run(testItemList, manager, new ApplicationRunnable<TestItem>() {
      /*
       * This will be the instructions launch by the run method of Application
       * after creating the Arena arg0
       */
      @Override
      public void run(final Arena<TestItem> arg0,
          final Collection<? extends TestItem> arg1) {

        /*
         * This is our MouseHandler that will be called by the Arena in case of
         * mouse events
         */
        MouseHandler<TestItem> mouseHandler = new MouseHandler<TestItem>() {
          ArrayList<TestItem> dragList;
          /*
           * in case of a mouse click we swap the color of the corresponding
           * TestItems
           */
          @Override
          public void mouseClicked(ArrayList<TestItem> arg0,
              KeyPress arg1) {
            System.out.println("Select " + arg0);
            for (TestItem testItem : arg0) {
              testItem.swap();
            }
          }        
          
          /*
           * in case of mouse wheel move, we just print the set of TestItems
           * covered by the mouse when it appears, the key that was eventually
           * pressed among CTL, SHIFT, ALT-GR and the direction of the wheel
           * move (-1 or +1).
           */
          @Override
          public void mouseWheelMoved(ArrayList<TestItem> arg0,
              KeyPress arg1, int arg2) {
            System.out.println(arg0 + " using " + arg1.toString()
                + " wheel rotate " + arg2);
          }

          @Override
          public void mouseDrag(ArrayList<TestItem> itemsDrag,
              KeyPress key) {
               dragList=itemsDrag;
              System.out.println("Drag :"+dragList);
            
          }

          @Override
          public void mouseDragging(ArrayList<TestItem> itemsDragging,
              KeyPress key) {
              if(!itemsDragging.isEmpty())
                System.out.println("Dragging :"+itemsDragging);
            
          }

          @Override
          public void mouseDrop(ArrayList<TestItem> itemsDrop, KeyPress key) {
            System.out.println("Drag& Drop :"+dragList+" => "+itemsDrop + " using "+key.toString());            
          }

          @Override
          public void mouseOver(ArrayList<TestItem> itemsOver, KeyPress key) {
            if(!itemsOver.isEmpty())
              System.out.println("Over :"+itemsOver);
          }
        };

        /*
         * We build the graphical interface by adding the graphical component
         * corresponding to the Arena - by calling createComponent - to a
         * JFrame.
         */
        final JFrame frame = new JFrame("Test Arena");

        /*
         * This is our KeyHandler that will be called by the Arena in case of
         * key events
         */
        final KeyHandler keyHandler = new KeyHandler() {

          @Override
          public void keyPressed(char arg0) {
            // do nothing
          }

          @Override
          public void keyReleased(char arg0) {
            // do nothing
          }

          @Override
          public void keyTyped(char arg0) {            
            switch (arg0) {
            case '+':
              System.out.println("+ has been typed");
              break;
            case '-':
              System.out.println("- has been typed");
              break;
            default:
              //do nothing
              break;
            }
          }

          @Override
          public JFrame getParentFrame() {
            return frame;
          }

        };

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(arg0.createComponent(300, 200, mouseHandler, keyHandler));
        frame.pack();
        frame.setVisible(true);

        /*
         * We initially draw the component
         */
        arg0.refresh();

        /*
         * We ask the Application to call the following run function every
         * seconds. This method just refresh the component.
         */
        Application.timer(1000, new TimerRunnable() {

          public void run(TimerTask timerTask) {
            arg0.refresh();
          }

        });
      }

    });
  }
}
