/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pivot.wtk.skin;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.util.Iterator;

import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.util.ImmutableIterator;
import org.apache.pivot.wtk.Bounds;
import org.apache.pivot.wtk.text.Element;
import org.apache.pivot.wtk.text.ElementListener;
import org.apache.pivot.wtk.text.Node;

/**
 * Abstract base class for element views.
 */
abstract class TextPaneSkinElementView extends TextPaneSkinNodeView implements
    Sequence<TextPaneSkinNodeView>, Iterable<TextPaneSkinNodeView>, ElementListener {
    private ArrayList<TextPaneSkinNodeView> nodeViews = new ArrayList<>();
    private int skinX = 0;
    private int skinY = 0;

    public TextPaneSkinElementView(TextPaneSkin textPaneSkin, Element element) {
        super(textPaneSkin, element);
    }

    @Override
    protected void attach() {
        super.attach();

        Element element = (Element) getNode();
        element.getElementListeners().add(this);

        // Attach child node views
        for (Node node : element) {
            add(createNodeView(getTextPaneSkin(), node));
        }
    }

    @Override
    protected void detach() {
        Element element = (Element) getNode();
        element.getElementListeners().remove(this);

        // Detach child node views
        for (TextPaneSkinNodeView nodeView : this) {
            nodeView.detach();
        }

        super.detach();
    }

    @Override
    public void invalidateDownTree() {
        super.invalidateDownTree();
        for (TextPaneSkinNodeView child : this) {
            child.invalidateDownTree();
        }
    }

    @Override
    public int add(TextPaneSkinNodeView nodeView) {
        int index = getLength();
        insert(nodeView, index);

        return index;
    }

    @Override
    public void insert(TextPaneSkinNodeView nodeView, int index) {
        nodeView.setParent(this);
        nodeView.attach();

        nodeViews.insert(nodeView, index);
    }

    @Override
    public TextPaneSkinNodeView update(int index, TextPaneSkinNodeView nodeView) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int remove(TextPaneSkinNodeView nodeView) {
        int index = indexOf(nodeView);
        if (index != -1) {
            remove(index, 1);
        }

        return index;
    }

    @Override
    public Sequence<TextPaneSkinNodeView> remove(int index, int count) {
        Sequence<TextPaneSkinNodeView> removed = nodeViews.remove(index, count);

        for (int i = 0, n = removed.getLength(); i < n; i++) {
            TextPaneSkinNodeView nodeView = removed.get(i);
            nodeView.setParent(null);
            nodeView.detach();
        }

        return removed;
    }

    @Override
    public TextPaneSkinNodeView get(int index) {
        return nodeViews.get(index);
    }

    @Override
    public int indexOf(TextPaneSkinNodeView nodeView) {
        return nodeViews.indexOf(nodeView);
    }

    @Override
    public int getLength() {
        return nodeViews.getLength();
    }

    @Override
    public int getBaseline() {
        int baseline = -1;
        for (TextPaneSkinNodeView nodeView : nodeViews) {
            baseline = Math.max(baseline, nodeView.getBaseline());

        }
        return baseline;
    }

    @Override
    protected void setSkinLocation(int skinX, int skinY) {
        this.skinX = skinX;
        this.skinY = skinY;
    }

    @Override
    public void paint(Graphics2D graphics) {
        // Determine the paint bounds
        Bounds paintBounds = new Bounds(0, 0, getWidth(), getHeight());
        Rectangle clipBounds = graphics.getClipBounds();
        if (clipBounds != null) {
            paintBounds = paintBounds.intersect(clipBounds);
        }

        for (TextPaneSkinNodeView nodeView : nodeViews) {
            paintChild(graphics, paintBounds, nodeView);
        }
    }

    protected final void paintChild(Graphics2D graphics, Bounds paintBounds,
        TextPaneSkinNodeView nodeView) {
        Bounds nodeViewBounds = nodeView.getBounds();

        // Only paint node views that intersect the current clip rectangle
        if (nodeViewBounds.intersects(paintBounds)) {
            // Create a copy of the current graphics context and
            // translate to the node view's coordinate system
            Graphics2D nodeViewGraphics = (Graphics2D) graphics.create();

            Color styledBackgroundColor = getStyledBackgroundColor();
            if (styledBackgroundColor != null) {
                // don't paint over the selection background
                Area selection = getTextPaneSkin().getSelection();
                if (selection != null) {
                    Area fillArea = new Area(new Rectangle(nodeViewBounds.x, nodeViewBounds.y,
                        nodeViewBounds.width, nodeViewBounds.height));
                    selection = selection.createTransformedArea(AffineTransform.getTranslateInstance(
                        -skinX, -skinY));
                    fillArea.subtract(selection);
                    nodeViewGraphics.setColor(styledBackgroundColor);
                    nodeViewGraphics.fill(fillArea);
                } else {
                    nodeViewGraphics.setColor(styledBackgroundColor);
                    nodeViewGraphics.fillRect(nodeViewBounds.x, nodeViewBounds.y,
                        nodeViewBounds.width, nodeViewBounds.height);
                }
            }
            nodeViewGraphics.translate(nodeViewBounds.x, nodeViewBounds.y);

            // NOTE We don't clip here because views should generally
            // not overlap and clipping would impose an unnecessary
            // performance penalty

            // Paint the node view
            nodeView.paint(nodeViewGraphics);

            // Dispose of the node views's graphics
            nodeViewGraphics.dispose();
        }
    }

    private Color getStyledBackgroundColor() {
        Color backgroundColor = null;
        Node node = getNode();
        // run up the tree until we find a Element's style to apply
        while (node != null) {
            if (node instanceof Element) {
                backgroundColor = ((Element) node).getBackgroundColor();
                if (backgroundColor != null) {
                    break;
                }
            }
            node = node.getParent();
        }
        return backgroundColor;
    }

    @Override
    public Bounds getCharacterBounds(int offset) {
        Bounds characterBounds = null;

        for (int i = 0, n = nodeViews.getLength(); i < n; i++) {
            TextPaneSkinNodeView nodeView = nodeViews.get(i);
            int nodeViewOffset = nodeView.getOffset();
            int characterCount = nodeView.getCharacterCount();

            if (offset >= nodeViewOffset && offset < nodeViewOffset + characterCount) {
                characterBounds = nodeView.getCharacterBounds(offset - nodeViewOffset);

                if (characterBounds != null) {
                    characterBounds = characterBounds.translate(nodeView.getX(), nodeView.getY());
                }

                break;
            }
        }

        if (characterBounds != null) {
            characterBounds = characterBounds.intersect(0, 0, getWidth(), getHeight());
        }

        return characterBounds;
    }

    @Override
    public void nodeInserted(Element element, int index) {
        insert(createNodeView(getTextPaneSkin(), element.get(index)), index);
        invalidateUpTree();
    }

    @Override
    public void nodesRemoved(Element element, int index, Sequence<Node> nodes) {
        remove(index, nodes.getLength());
        invalidateUpTree();
    }

    @Override
    public void fontChanged(Element element, Font previousFont) {
        // because children may depend on parents for their style information,
        // we need to invalidate the whole tree
        // TODO, we don't need to invalidate the whole tree, just the sub-tree
        // from here down
        getTextPaneSkin().invalidateNodeViewTree();
    }

    @Override
    public void backgroundColorChanged(Element element, Color previousBackgroundColor) {
        repaint();
    }

    @Override
    public void foregroundColorChanged(Element element, Color previousForegroundColor) {
        // Because children may depend on parents for their style information,
        // we need to invalidate the whole tree.
        // TODO we don't need to invalidate the whole tree, just the sub-tree
        // from here down.
        getTextPaneSkin().invalidateNodeViewTree();
    }

    @Override
    public void underlineChanged(Element element) {
        // Because children may depend on parents for their style information,
        // we need to invalidate the whole tree.
        // TODO we don't need to invalidate the whole tree, just the sub-tree
        // from here down.
        getTextPaneSkin().invalidateNodeViewTree();
    }

    @Override
    public void strikethroughChanged(Element element) {
        // Because children may depend on parents for their style information,
        // we need to invalidate the whole tree.
        // TODO we don't need to invalidate the whole tree, just the sub-tree
        // from here down.
        getTextPaneSkin().invalidateNodeViewTree();
    }

    @Override
    public Iterator<TextPaneSkinNodeView> iterator() {
        return new ImmutableIterator<>(nodeViews.iterator());
    }
}
