/*
 * @(#)EllipseFigure.java 5.1
 *
 */

package de.renew.fa.figures;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.Vector;

import CH.ifa.draw.figures.AttributeFigure;
import CH.ifa.draw.figures.ChopEllipseConnector;
import CH.ifa.draw.standard.BoxHandleKit;
import CH.ifa.draw.util.Geom;
import de.renew.draw.storables.ontology.Connector;
import de.renew.draw.storables.ontology.StorableInput;
import de.renew.draw.storables.ontology.StorableOutput;
import de.renew.draw.ui.ontology.FigureHandle;

/**
 * An ellipse figure.
 */
public class HalfMoonFigure extends AttributeFigure {
    /*
     * Serialization support.
     */
    static final long serialVersionUID = -6856203289355118951L;

    /**
     * Determines position and size of the ellipse by specifying position and
     * size of its bounding box.
     *
     * @serial
     */
    private Rectangle _fDisplayBox;

    /**
     * Constructs a new HalfMoonFigure with default values.
     */
    public HalfMoonFigure() {
        this(new Point(0, 0), new Point(0, 0));
    }

    /**
     * Constructs a new HalfMoonFigure from two points.
     *
     * @param origin The origin of the figure.
     * @param corner The corner of the figure. The figure will be scaled according to this.
     */
    public HalfMoonFigure(Point origin, Point corner) {
        basicDisplayBox(origin, corner);
    }


    @Override
    public void basicDisplayBox(Point origin, Point corner) {
        _fDisplayBox = new Rectangle(origin);
        _fDisplayBox.add(corner);
    }

    /**
     * Moves the shape by a given offset.
     *
     * @param x - Offset on the X-axis.
     * @param y - Offset on the Y-axis.
     */
    @Override
    protected void basicMoveBy(int x, int y) {
        _fDisplayBox.translate(x, y);
    }


    @Override
    public Insets connectionInsets() {
        Rectangle r = _fDisplayBox;
        int cx = r.width / 2;
        int cy = r.height / 2;
        return new Insets(cy, cx, cy, cx);
    }


    @Override
    public Connector connectorAt(int x, int y) {
        return new ChopEllipseConnector(this);
    }

    @Override
    public boolean containsPoint(int x, int y) {
        if (super.containsPoint(x, y)) {
            return Geom.ellipseContainsPoint(displayBox(), x, y);
        } else {
            return false;
        }
    }

    @Override
    public Rectangle displayBox() {
        return new Rectangle(
            _fDisplayBox.x, _fDisplayBox.y, _fDisplayBox.width, _fDisplayBox.height);
    }

    /**
     * Draws the background of the halfmoon figure.
     *
     * @param g The graphics object that is drawn on.
     */
    @Override
    public void drawBackground(Graphics g) {
        Rectangle r = displayBox();

        //g.fillOval(r.x, r.y, r.width, r.height);
        //        System.out.println("====================================== ");
        //        System.out.println("x "+displayBox().x);
        //        System.out.println("y "+displayBox().y);
        //        System.out.println("X "+getXabs());
        //        System.out.println("Y "+getYabs());
        //        System.out.println("W "+r.width % 2);
        //        System.out.println("H "+Double.valueOf(getYprime()).intValue());
        //        System.out.println("YPrine "+ getYprime());
        g.fillArc(r.x, r.y, (r.width - 1), r.height - 1, 120, 120);
        g.setColor(Color.white);
        g.fillRect(
            getXabs() + displayBox().width / 4, getYabs(),
            Double.valueOf(displayBox().width / 2).intValue(),
            Double.valueOf(getYprime() * 2).intValue());


        //g.fillArc(getXabs(),getYabs(),Double.valueOf(r.width / 2).intValue(), new
        // Double(getYprime()*2).intValue(),110,160);
    }

    /**
     * Draws a frame around the display box.
     *
     * @param g The graphics object that is drawn on.
     */
    @Override
    public void drawFrame(Graphics g) {
        Rectangle r = displayBox();

        //g.drawOval(r.x, r.y, r.width - 1, r.height - 1);
        //g.drawArc(r.x,r.y,r.width - 1, r.height - 1,90,180);
        g.drawArc(r.x, r.y, (r.width - 1), r.height - 1, 120, 120);
        //g.setColor(Color.white);
        g.drawLine(
            getXabs() + displayBox().width / 4, getYabs(), getXabs() + displayBox().width / 4,
            Double.valueOf(getYprime() * 2).intValue());
    }

    /**
     * Returns the x coordinate of the upper left corner of the display box.
     *
     * @return The position of the displayBox on the X-Axis.
     */
    private int getXabs() {
        //float a = displayBox().width / 2;
        return displayBox().x;
    }

    /**
     * Returns slightly more than the display boxes height.
     *
     * @return absolute Y value.
     */
    private int getYabs() {
        //float a = displayBox().width / 2;
        float b = displayBox().height / 2;

        // TODO: If someone knows what this is supposed to to exactly,
        //  Im very sure it can be simplified to be more readable and update the comment to a better description.
        return Double.valueOf(displayBox().y + b - getYprime()).intValue();
    }

    /**
     * Returns slightly less than half of the display boxes height.
     *
     * @return Y-prime
     */
    private double getYprime() {
        //float a = displayBox().width / 2;
        float b = displayBox().height / 2;
        return Math.sqrt(((1 - (.25)) * b * b));
    }

    @Override
    public Vector<FigureHandle> handles() {
        Vector<FigureHandle> handles = new Vector<FigureHandle>();
        BoxHandleKit.addHandles(this, handles);
        return handles;
    }

    @Override
    public void read(StorableInput dr) throws IOException {
        super.read(dr);
        _fDisplayBox = new Rectangle(dr.readInt(), dr.readInt(), dr.readInt(), dr.readInt());
    }

    @Override
    public void write(StorableOutput dw) {
        super.write(dw);
        dw.writeInt(_fDisplayBox.x);
        dw.writeInt(_fDisplayBox.y);
        dw.writeInt(_fDisplayBox.width);
        dw.writeInt(_fDisplayBox.height);
    }
}