/*
Copyright 2005-2013 Samuel Gesche

This file is part of ArcEnCiel.

ArcEnCiel 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.

ArcEnCiel 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 ArcEnCiel.  If not, see <http://www.gnu.org/licenses/>.
*/

package ihm.townto;

import ihm.Charte;

import java.awt.Component;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.Popup;
import javax.swing.JToolTip;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.GeneralPath;
import java.awt.geom.AffineTransform;

/**
 * This class provides methods for creating graphical links.
 * For now it only applies to arrows.
 *
 * @author Samuel Gesche
 * @version 1.4
 * @since Towntology 1.0
 */
public class LinkFactory{
  /**
   * The GeneralPath for drawing an arrow.
   * @since Towntology 1.0
   */
  protected final static GeneralPath GENERAL_ARROW = new GeneralPath();

  /**
   * The GeneralPath for drawing a symmetric arrow.
   * @since Towntology 1.2
   */
  protected final static GeneralPath SYMMETRIC_ARROW = new GeneralPath();



  static{
    GENERAL_ARROW.moveTo(10, 5);
    GENERAL_ARROW.lineTo(0, 2);
    GENERAL_ARROW.lineTo(3, 5);
    GENERAL_ARROW.lineTo(0, 8);
    GENERAL_ARROW.lineTo(10, 5);

    SYMMETRIC_ARROW.moveTo(10, 5);
    SYMMETRIC_ARROW.lineTo(5, 3);
    SYMMETRIC_ARROW.lineTo(0, 5);
    SYMMETRIC_ARROW.lineTo(5, 7);
    SYMMETRIC_ARROW.lineTo(10, 5);

  }

  /**
   * Creates a LinkFactory.
   * @since Towntology 1.0
   */
  public LinkFactory(){}

  /**
   * Creates a GeneralPath for drawing an arrow oriented from the coordinates
   * given in parameter.
   * @param xFrom the x-coordinate of the beginning point.
   * @param yFrom the y-coordinate of the beginning point.
   * @param xTo the x-coordinate of the end point.
   * @param yTo the y-coordinate of the end point.
   * @return the GeneralPath for drawing the arrow.
   * @since Towntology 1.0
   */
  public static GeneralPath createArrow(int xFrom, int yFrom, int xTo, int yTo){
    double dx = 1.0 * xTo - xFrom;
    double dy = 1.0 * yTo - yFrom;
    double alpha = Math.atan2(dy, dx); // -pi <= alpha <= pi
    double pi = Math.PI;
    GeneralPath result = new GeneralPath(GENERAL_ARROW);
    AffineTransform transform = AffineTransform.getRotateInstance(alpha, 5, 5);
    result.transform(transform);
    return result;
  }

  /**
   * Creates a GeneralPath for drawing a symmetric arrow oriented from the
   * coordinates given in parameter.
   * @param xFrom the x-coordinate of the beginning point.
   * @param yFrom the y-coordinate of the beginning point.
   * @param xTo the x-coordinate of the end point.
   * @param yTo the y-coordinate of the end point.
   * @return the GeneralPath for drawing the arrow.
   * @since Towntology 1.2
   */
  public static GeneralPath createSymmetricArrow(int xFrom, int yFrom, int xTo,
                                                 int yTo){
    double dx = 1.0 * xTo - xFrom;
    double dy = 1.0 * yTo - yFrom;
    double alpha = Math.atan2(dy, dx); // -pi <= alpha <= pi
    double pi = Math.PI;
    GeneralPath result = new GeneralPath(SYMMETRIC_ARROW);
    AffineTransform transform = AffineTransform.getRotateInstance(alpha, 5, 5);
    result.transform(transform);
    return result;
  }

  /**
   * Creates an ArrowComponent from the parameters.
   * @param text the text given when the mouse is on the component.
   * @param arrow the arrow to draw on the component.
   * @param color the color which will be used.
   * @param parent the owner of the component (for the popup).
   * @return the component to include in the container.
   * @since Towntology 1.0
   */
  public ArrowComponent createArrowComponent(String text, GeneralPath arrow,
                                             Color color, Component parent){
    ArrowComponent comp = new ArrowComponent(text, arrow, color, parent);
    return comp;
  }

  /**
   * This class is a component giving an arrow sensitive to the mouse.
   * When the mouse goes on the component, it will display a message
   * in a popup window.
   * <br>
   * Note : this component is not opaque, so it will only draw its arrow,
   * not clear its space when painting.
   *
   * <p>Title : Towntology Softwares</p>
   * <p>Description : </p>
   * <p>Copyright : Copyright (c) 2004</p>
   * <p>Company : LIRIS</p>
   * @author Samuel Gesche
   * @version 1.4
   * @since Towntology 1.0
   */
  class ArrowComponent
          extends JComponent{
    private GeneralPath arrow;
    private Color color;
    private JLabel txt;
    private Popup popup;
    private Component parent;

    /**
     * Creates an ArrowComponent from the parameters.
     * @param text the text given when the mouse is on the component.
     * @param arrow the arrow to draw on the component.
     * @param color the color which will be used.
     * @param parent the owner of the component (for the popup).
     * @since Towntology 1.0
     */
    public ArrowComponent(String text, GeneralPath arrow, Color color,
                          Component parent){
      this.arrow = arrow;
      this.color = color;
      this.parent = parent;
      /*      txt = new JLabel(text);
            txt.setOpaque(true);
            txt.setBackground(ColorTable.COLOR_CELL_BACKGROUND);
            txt.setForeground(ColorTable.COLOR_TEXT_TITLE);*/
      setOpaque(false);
      setLocation(0, 0);
      setToolTipText(text);
    }

    /**
     * Creates a custom ToolTip.
     * @return a custom ToolTip.
     * @since Towntology 1.2
     */
    public JToolTip createToolTip(){
      JToolTip toolTip = new JToolTip();
      //toolTip.setBackground(ColorTable.COLOR_CELL_BACKGROUND);
      //toolTip.setForeground(ColorTable.COLOR_TEXT_TITLE);
      return toolTip;
    }

    /**
     * Changes the drawing of the arrow.
     * @param arrow the new drawing.
     * @since Towntology 1.0
     */
    public void setArrow(GeneralPath arrow){
      this.arrow = arrow;
    }

    /**
     * Paints the component.
     * @param g the Graphics on which to paint the component.
     * @since Towntology 1.0
     */
    public void paint(Graphics g){
      Graphics2D gra = (Graphics2D)g;
      gra.setColor(Charte.getMiscellaneous());
      gra.fill(arrow);
    }

  }

}
