/**
 * InlineReplacedBoxView.java
 * (c) Peter Bielik and Radek Burget, 2011-2012
 *
 * SwingBox is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * SwingBox 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 Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public License
 * along with SwingBox. If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package org.fit.cssbox.swingbox.view;

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.Map;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.LayeredHighlighter;
import javax.swing.text.Position;
import javax.swing.text.Position.Bias;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.View;

import org.fit.cssbox.layout.InlineReplacedBox;
import org.fit.cssbox.layout.ReplacedContent;
import org.fit.cssbox.layout.ReplacedImage;
import org.fit.cssbox.swingbox.util.Constants;

/**
 * @author Peter Bielik
 * @version 1.0
 * @since 1.0 - 15.3.2011
 */
public class InlineReplacedBoxView extends InlineBoxView
{
    // get some default system font..
    private static final Font DEFAULT_FONT = new Font(null, Font.PLAIN, 13);
    private Container container;
    private ReplacedContent content;
    private ReplacedImage repImage;
    private String alt = "";
    private String title = "";

    public InlineReplacedBoxView(Element elem)
    {
        super(elem);

        content = ((InlineReplacedBox) box).getContentObj();
        if (content instanceof ReplacedImage)
        {
            repImage = (ReplacedImage) content;
        }
        else
        {
            repImage = null;
        }

        loadElementAttributes();
    }

    private void loadElementAttributes()
    {
        alt = box.getElement().getAttribute("alt");
        title = box.getElement().getAttribute("title");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void paint(Graphics graphics, Shape allocation)
    {
        Graphics2D g = (Graphics2D) graphics;
        Rectangle alloc = toRect(allocation);

        if (isVisible()
                /*&& intersection(alloc, box.getAbsoluteBounds(), tmpRect)*/)
        {
            paintHighlights(g, alloc);
            box.getVisualContext().updateGraphics(g);
            box.drawBackground(g);

            if (content != null)
            {
                content.draw(g, box.getContentWidth(), box.getContentHeight());

                if (repImage != null && repImage.getImage() == null)
                {
                    if (!"".equals(alt))
                    {
                        // so we have replaced image, which has no image data...
                        // :)

                        g.setFont(DEFAULT_FONT);
                        g.setColor(Color.BLACK);
                        //tmpRect = box.getAbsoluteContentBounds();
                        // alternative picture representation (screen readers)
                        // TODO hint : java accessibility !!!
                        //g.drawString(alt, tmpRect.x + 2, tmpRect.y
                        //        + (int) (tmpRect.height * 0.7));
                    }
                    else
                    {
                        drawCross(g);
                    }
                }
            }
            else
            {
                drawCross(g);
            }

        }

    }

    private void drawCross(Graphics2D g)
    {
        /*tmpRect = box.getAbsoluteContentBounds();

        g.setColor(Color.BLACK);
        g.drawLine(tmpRect.x, tmpRect.y, tmpRect.x + tmpRect.width - 1,
                tmpRect.y + tmpRect.height - 1);
        g.drawLine(tmpRect.x + tmpRect.width - 1, tmpRect.y, tmpRect.x,
                tmpRect.y + tmpRect.height - 1);*/
    }

    @Override
    public String getToolTipText(float x, float y, Shape allocation)
    {
        Map<String, String> elementAttributes = anchor.getProperties();
        String val = "";
        String tmp;
        // image title
        if (title != null && !"".equals(title))
            val = val + "<b>" + title + "</b><br>";
        // anchor title
        tmp = elementAttributes.get(Constants.ELEMENT_A_ATTRIBUTE_TITLE);
        if (tmp != null && !"".equals(tmp))
            val = val + "<i>" + tmp + "</i><br>";
        // anchor href
        tmp = elementAttributes.get(Constants.ELEMENT_A_ATTRIBUTE_HREF);
        if (tmp != null && !"".equals(tmp)) val = val + tmp;

        return "".equals(val) ? null : "<html>" + val + "</html>";
    }

    @Override
    public boolean isVisible()
    {
        return box.isDisplayed() && box.isVisible();
    }

    @Override
    public void setParent(View parent)
    {
        super.setParent(parent);
        if (parent != null)
        {
            container = getContainer();
            if (repImage != null) repImage.setContainer(container);// getContainer());
        }
        else
        {
            repImage = null;
            content = null;
            container = null;
        }
    }

    @Override
    protected View getViewAtPoint(int x, int y, Rectangle alloc)
    {
        Rectangle rec = box.getAbsoluteBounds();
        if (rec.contains(x, y)) { return this; }

        return null;
    }

    @Override
    protected void setPropertiesFromAttributes(AttributeSet attr)
    {
        super.setPropertiesFromAttributes(attr);
        if (attr != null)
        {
            // setContent((ReplacedContent)
            // attr.getAttribute(Constants.ATTRIBUTE_REPLACED_CONTENT));
        }
    }

    protected SimpleAttributeSet createAttributes()
    {
        // called from getAttributes()
        SimpleAttributeSet res = super.createAttributes();
        res.addAttribute(Constants.ATTRIBUTE_REPLACED_CONTENT, content);

        return res;
    }

    @Override
    public int viewToModel(float x, float y, Shape a, Bias[] bias)
    {
        // Rectangle alloc = a instanceof Rectangle ? (Rectangle)a :
        // a.getBounds();
        // if (x < alloc.x + alloc.width) {
        // bias[0] = Position.Bias.Forward;
        // return getStartOffset(); // LTR
        // }
        // bias[0] = Position.Bias.Backward;
        // return getEndOffset(); //RTL

        Rectangle alloc = a instanceof Rectangle ? (Rectangle) a : a
                .getBounds();
        if (x < alloc.x + (alloc.width / 2))
        {
            bias[0] = Position.Bias.Forward;
            return getStartOffset();
        }
        bias[0] = Position.Bias.Backward;
        return getEndOffset();
    }

    @Override
    public Shape modelToView(int pos, Shape a, Bias b)
            throws BadLocationException
    {
        int p0 = getStartOffset();
        int p1 = getEndOffset();
        if ((pos >= p0) && (pos <= p1))
        {
            Rectangle r = a instanceof Rectangle ? (Rectangle) a : a
                    .getBounds();
            if (pos == p1)
            {
                r.x += r.width;
            }
            r.width = 0;
            return r;
        }
        // return null;
        // //return box.getAbsoluteBounds();
        throw new BadLocationException(pos + " not in range " + p0 + "," + p1,
                pos);
    }

    private void paintHighlights(Graphics g, Shape shape)
    {
        if (container instanceof JTextComponent)
        {
            JTextComponent tc = (JTextComponent) container;
            Highlighter h = tc.getHighlighter();
            if (h instanceof LayeredHighlighter)
            {
                ((LayeredHighlighter) h).paintLayeredHighlights(g,
                        getStartOffset(), getEndOffset(), shape, tc, this);
            }
        }
    }
}