package kiyut.sketsa.modules.symbollibrary.general;

import java.awt.Component;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import kiyut.sketsa.canvas.VectorCanvas;
import kiyut.sketsa.modules.symbollibrary.general.GeneralSymbol;
import kiyut.sketsa.undo.DOMUndoManager;
import kiyut.sketsa.util.ColorConvertion;
import kiyut.sketsa.util.DOMUtilities;
import kiyut.sketsa.util.SVGConstants;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGElement;
import org.w3c.dom.svg.SVGPathElement;
import org.w3c.dom.svg.SVGPathSegClosePath;
import org.w3c.dom.svg.SVGPathSegCurvetoCubicAbs;
import org.w3c.dom.svg.SVGPathSegMovetoAbs;



/** Implementation of Moon Symbol
 *
 * @author Kiyut
 */
public class MoonSymbol extends GeneralSymbol {
    /** Icon */
    protected Icon icon;
    
    /** Tooltip Text */
    protected String tooltipText;
    
    protected double radius;
    
    protected double phase;
    
    /** Creates a new instance of MoonSymbol */
    public MoonSymbol() {
        icon = new ImageIcon(getClass().getResource("/kiyut/sketsa/modules/symbollibrary/general/moon32.png"));
        tooltipText = "Moon";
        radius = 50;
        phase = 0.25;
    }
    
    /** {@inheritDoc} */
    public Icon getIcon() {
        return icon;
    }
    
    /** {@inheritDoc} */
    public String getTooltipText() {
        return tooltipText;
    }
    
    /** {@inheritDoc} */
    public void insertSymbol(VectorCanvas canvas, Point location) {
        SVGElement elt = createSVGElement(canvas,location);
        SVGDocument doc = canvas.getSVGDocument();
        Element svgRoot = doc.getDocumentElement();
        
        DOMUndoManager undoManager = canvas.getUndoManager();
        undoManager.start("Add " + tooltipText);
        try {
            svgRoot.appendChild(elt);
        } finally {
            undoManager.end();
        }
        
        List<SVGElement> newList = new ArrayList<SVGElement>();
        newList.add(elt);
        
        canvas.getCanvasSelection().setSelectionList(newList);
        canvas.refresh();
    }
    
    /** Create SVGElement
     * @param canvas VectorCanvas
     * @param location The location where the insertion should take place
     * @return SVGElement
     */
    protected SVGElement createSVGElement(VectorCanvas canvas, Point location) {
        SVGDocument doc = canvas.getSVGDocument();
        
        float[] coords = new float[6];
        coords[0] = (float)location.getX();
        coords[1] = (float)location.getY();
        
        AffineTransform at = canvas.getTransform(true);
        try {
            at = at.createInverse();
        } catch (NoninvertibleTransformException e) {}
        at.transform(coords,0,coords,0,2);
        
        float cx = (float)coords[0];
        float cy = (float)coords[1];
        
        PathIterator pi = generateShape(cx,cy).getPathIterator(null);
        
        SVGPathElement elt = (SVGPathElement)doc.createElementNS(SVGConstants.SVG_NAMESPACE_URI, SVGConstants.SVG_PATH_TAG);
        
        // adding the path seg
        while (!pi.isDone()) {
            int segment = pi.currentSegment(coords);
            if (segment == PathIterator.SEG_MOVETO) {
                SVGPathSegMovetoAbs svgMoveTo = elt.createSVGPathSegMovetoAbs(coords[0],coords[1]);
                elt.getPathSegList().appendItem(svgMoveTo);
            } else if (segment == PathIterator.SEG_CLOSE) {
                SVGPathSegClosePath svgClosePath = elt.createSVGPathSegClosePath();
                elt.getPathSegList().appendItem(svgClosePath);
            } else if (segment == PathIterator.SEG_CUBICTO) {
                SVGPathSegCurvetoCubicAbs svgCubic = elt.createSVGPathSegCurvetoCubicAbs(coords[4],coords[5],coords[0],coords[1],coords[2],coords[3]);
                elt.getPathSegList().appendItem(svgCubic);
            }
            
            pi.next();
        }
        
        
        DOMUtilities.updateProperty(elt, null, SVGConstants.SVG_STROKE_ATTRIBUTE,ColorConvertion.toHexString(java.awt.Color.BLACK));
        DOMUtilities.updateProperty(elt, null, SVGConstants.SVG_FILL_ATTRIBUTE,SVGConstants.SVG_NONE_VALUE);
        
        return elt;
    }
    
    /** It is created by substration 2 ellipse
     * @param cx center x coord
     * @param cy center y coord
     * @return Area
     */
    protected Area generateShape(double cx, double cy) {
        Area area1 = new Area(new Ellipse2D.Double(cx-radius,cy-radius,radius*2,radius*2));
        Area area2 = new Area(new Ellipse2D.Double((cx-radius)+(radius*phase),cy-radius,radius*2,radius*2));
        
        area1.subtract(area2);
        
        // center the area
        Rectangle2D r = area1.getBounds2D();
        double tx = cx - r.getCenterX();
        double ty = cy - r.getCenterY();
        area1.transform(AffineTransform.getTranslateInstance(tx,ty));
        
        return area1;
    }
    
    /** {@inheritDoc} */
    public void showOptionDialog(Component parentComponent) {
        MoonSymbolOptionPane option = new MoonSymbolOptionPane();
        option.setValue(phase,radius);
        int choice = JOptionPane.showConfirmDialog(parentComponent,option,getTooltipText(),JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
        if (choice == JOptionPane.OK_OPTION) {
            try {
                option.validateValue();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(parentComponent,ex.getMessage(),getTooltipText(), JOptionPane.ERROR_MESSAGE);
            }
            phase = option.getPhase();
            radius = option.getRadius();
        }
    }
    
}
