package de.renew.gui.pnml.parser;

import java.awt.Color;
import java.awt.Point;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import de.renew.gui.pnml.converter.GraphicConverter;
import de.renew.gui.pnml.converter.NetConverter;


/**
 * parse all graphic items
 */
public class GraphicParser extends ElementParser {
    private NodeList positions;
    private NodeList dimension;
    private Element offSet;
    private Element fill;
    private Element line;

    private static int parseRoundDouble(String s) {
        return (int) Math.round(Double.parseDouble(s));
    }

    public GraphicParser(Element graphic, NetConverter converter) {
        super(graphic, converter);
    }

    @Override
    protected void doParse() {
        if (getElement() != null) {
            positions = getElement().getElementsByTagName("position");
            dimension = getElement().getElementsByTagName("dimension");
            NodeList nodeList;
            nodeList = getElement().getElementsByTagName("offset");
            if (nodeList.getLength() > 0) {
                offSet = (Element) nodeList.item(0);
            }
            nodeList = getElement().getElementsByTagName("fill");
            if (nodeList.getLength() > 0) {
                fill = (Element) nodeList.item(0);
            }
            nodeList = getElement().getElementsByTagName("line");
            if (nodeList.getLength() > 0) {
                line = (Element) nodeList.item(0);
            }
        }
    }

    public Iterator<Point> positions() {
        List<Point> liste = new LinkedList<>();
        if (positions != null) {
            for (int pos = 0; pos < positions.getLength(); pos++) {
                Element position = (Element) positions.item(pos);
                int x = parseRoundDouble(position.getAttribute("x"));
                int y = parseRoundDouble(position.getAttribute("y"));
                liste.add(new Point(x, y));
            }
        }
        return liste.iterator();
    }

    public boolean hasPosition() {
        return positions != null && positions.getLength() > 0;
    }

    /**
      * @return a new Point of the new Dimension saved for the element
      */
    public Point getDimension() {
        if (dimension == null || dimension.getLength() == 0) {
            return null;
        }

        Point result = new Point();
        Element dim = (Element) dimension.item(0);
        result.x = parseRoundDouble(dim.getAttribute("x"));
        result.y = parseRoundDouble(dim.getAttribute("y"));
        return result;
    }

    /**
      * Returns the x offset of the element. 0 if not set
      * @return the X offset of the element
      */
    public int offsetX() {
        if (offSet == null) {
            return 0;
        }

        return parseRoundDouble(offSet.getAttribute("x"));
    }

    /**
     * Returns the y offset of the element. 0 if not set
     * @return the Y offset of the element
     */
    public int offsetY() {
        if (offSet == null) {
            return 0;
        }

        return parseRoundDouble(offSet.getAttribute("y"));
    }

    /**
     * @return true if the element has the fill attribute set
     */
    public boolean hasFill() {
        return fill != null;
    }

    /**
     * Returns the fill color set for this element
     * <p>
     * Returns {@code null} if {@link hasFill()} is {@code false}.
     * </p>
     * @return the fill color set
     */
    public Color getFill() {
        if (!hasFill()) {
            return null;
        }

        String textColor = fill.getAttribute("color");
        return GraphicConverter.instance().parseCSS2Color(textColor);
    }

    /**
     * @return true if the line attribute has been set
     */
    public boolean hasLine() {
        return line != null;
    }

    /**
     * The line attribute needs to be set.
     * @return true if the color attribute has been set for the line attribute
     */
    public boolean hasLineColor() {
        return line != null && !"".equals(line.getAttribute("color"));
    }

    /**
     * Returns the line color set for this element
     * <p>
     * Returns {@code null} if {@link hasLineColor()} is {@code false}.
     * </p>
     * @return the line color set
     */
    public Color getLineColor() {
        if (!hasLineColor()) {
            return null;
        }

        String textColor = line.getAttribute("color");
        return GraphicConverter.instance().parseCSS2Color(textColor);
    }

    /**
     * The line attribute needs to be set.
     * @return true if the style attribute has been set for the line attribute
     */
    public boolean hasLineStyle() {
        return line != null && !"".equals(line.getAttribute("style"));
    }

    /**
     * Returns the line style set for this element
     * <p>
     * Returns {@code null} if {@link hasLineStyle()} is {@code false}.
     * </p>
     * @return the line styleS
     */
    public String getLineStyle() {
        if (!hasLineStyle()) {
            return null;
        }

        String style = line.getAttribute("style");
        return GraphicConverter.instance().parsePNMLLineStyle(style);
    }
}