/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

/*
 * (C) Copyright IBM Corp. 1999-2003, All Rights Reserved
 *
 */

package sun.font;

import java.util.Map;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;

import java.awt.font.TextAttribute;

import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.GeneralPath;

import static sun.font.AttributeValues.*;
import static sun.font.EAttribute.*;

/**
 * This class handles underlining, strikethrough, and foreground and
 * background styles on text.  Clients simply acquire instances
 * of this class and hand them off to ExtendedTextLabels or GraphicComponents.
 */
public class Decoration {

    /**
     * This interface is implemented by clients that use Decoration.
     * Unfortunately, interface methods have to public;  ideally these
     * would be package-private.
     */
    public interface Label {
        CoreMetrics getCoreMetrics();
        Rectangle2D getLogicalBounds();

        void handleDraw(Graphics2D g2d, float x, float y);
        Rectangle2D handleGetCharVisualBounds(int index);
        Rectangle2D handleGetVisualBounds();
        Shape handleGetOutline(float x, float y);
    }

    private Decoration() {
    }

    /**
     * Return a Decoration which does nothing.
     */
    public static Decoration getPlainDecoration() {

        return PLAIN;
    }

    private static final int VALUES_MASK =
        AttributeValues.getMask(EFOREGROUND, EBACKGROUND, ESWAP_COLORS,
                                ESTRIKETHROUGH, EUNDERLINE, EINPUT_METHOD_HIGHLIGHT,
                                EINPUT_METHOD_UNDERLINE);

    public static Decoration getDecoration(AttributeValues values) {
        if (values == null || !values.anyDefined(VALUES_MASK)) {
            return PLAIN;
        }

        values = values.applyIMHighlight();

        return new DecorationImpl(values.getForeground(),
                                  values.getBackground(),
                                  values.getSwapColors(),
                                  values.getStrikethrough(),
                                  Underline.getUnderline(values.getUnderline()),
                                  Underline.getUnderline(values.getInputMethodUnderline()));
    }

    /**
     * Return a Decoration appropriate for the the given Map.
     * @param attributes the Map used to determine the Decoration
     */
    public static Decoration getDecoration(Map attributes) {
        if (attributes == null) {
            return PLAIN;
        }
        return getDecoration(AttributeValues.fromMap(attributes));
    }

    public void drawTextAndDecorations(Label label,
                                Graphics2D g2d,
                                float x,
                                float y) {

        label.handleDraw(g2d, x, y);
    }

    public Rectangle2D getVisualBounds(Label label) {

        return label.handleGetVisualBounds();
    }

    public Rectangle2D getCharVisualBounds(Label label, int index) {

        return label.handleGetCharVisualBounds(index);
    }

    Shape getOutline(Label label,
                     float x,
                     float y) {

        return label.handleGetOutline(x, y);
    }

    private static final Decoration PLAIN = new Decoration();

    private static final class DecorationImpl extends Decoration {

        private Paint fgPaint = null;
        private Paint bgPaint = null;
        private boolean swapColors = false;
        private boolean strikethrough = false;
        private Underline stdUnderline = null; // underline from TextAttribute.UNDERLINE_ON
        private Underline imUnderline = null; // input method underline

        DecorationImpl(Paint foreground,
                       Paint background,
                       boolean swapColors,
                       boolean strikethrough,
                       Underline stdUnderline,
                       Underline imUnderline) {

            fgPaint = (Paint) foreground;
            bgPaint = (Paint) background;

            this.swapColors = swapColors;
            this.strikethrough = strikethrough;

            this.stdUnderline = stdUnderline;
            this.imUnderline = imUnderline;
        }

        private static boolean areEqual(Object lhs, Object rhs) {

            if (lhs == null) {
                return rhs == null;
            }
            else {
                return lhs.equals(rhs);
            }
        }

        public boolean equals(Object rhs) {

            if (rhs == this) {
                return true;
            }
            if (rhs == null) {
                return false;
            }

            DecorationImpl other = null;
            try {
                other = (DecorationImpl) rhs;
            }
            catch(ClassCastException e) {
                return false;
            }

            if (!(swapColors == other.swapColors &&
                        strikethrough == other.strikethrough)) {
                return false;
            }

            if (!areEqual(stdUnderline, other.stdUnderline)) {
                return false;
            }
            if (!areEqual(fgPaint, other.fgPaint)) {
                return false;
            }
            if (!areEqual(bgPaint, other.bgPaint)) {
                return false;
            }
            return areEqual(imUnderline, other.imUnderline);
        }

        public int hashCode() {

            int hc = 1;
            if (strikethrough) {
                hc |= 2;
            }
            if (swapColors) {
                hc |= 4;
            }
            if (stdUnderline != null) {
                hc += stdUnderline.hashCode();
            }
            return hc;
        }

        /**
        * Return the bottom of the Rectangle which encloses pixels
        * drawn by underlines.
        */
        private float getUnderlineMaxY(CoreMetrics cm) {

            float maxY = 0;
            if (stdUnderline != null) {

                float ulBottom = cm.underlineOffset;
                ulBottom += stdUnderline.getLowerDrawLimit(cm.underlineThickness);
                maxY = Math.max(maxY, ulBottom);
            }

            if (imUnderline != null) {

                float ulBottom = cm.underlineOffset;
                ulBottom += imUnderline.getLowerDrawLimit(cm.underlineThickness);
                maxY = Math.max(maxY, ulBottom);
            }

            return maxY;
        }

        private void drawTextAndEmbellishments(Label label,
                                               Graphics2D g2d,
                                               float x,
                                               float y) {

            label.handleDraw(g2d, x, y);

            if (!strikethrough && stdUnderline == null && imUnderline == null) {
                return;
            }

            float x1 = x;
            float x2 = x1 + (float)label.getLogicalBounds().getWidth();

            CoreMetrics cm = label.getCoreMetrics();
            if (strikethrough) {
                Stroke savedStroke = g2d.getStroke();
                g2d.setStroke(new BasicStroke(cm.strikethroughThickness));
                float strikeY = y + cm.strikethroughOffset;
                g2d.draw(new Line2D.Float(x1, strikeY, x2, strikeY));
                g2d.setStroke(savedStroke);
            }

            float ulOffset = cm.underlineOffset;
            float ulThickness = cm.underlineThickness;

            if (stdUnderline != null) {
                stdUnderline.drawUnderline(g2d, ulThickness, x1, x2, y + ulOffset);
            }

            if (imUnderline != null) {
                imUnderline.drawUnderline(g2d, ulThickness, x1, x2, y + ulOffset);
            }
        }

        public void drawTextAndDecorations(Label label,
                                    Graphics2D g2d,
                                    float x,
                                    float y) {

            if (fgPaint == null && bgPaint == null && swapColors == false) {
                drawTextAndEmbellishments(label, g2d, x, y);
            }
            else {
                Paint savedPaint = g2d.getPaint();
                Paint foreground, background;

                if (swapColors) {
                    background = fgPaint==null? savedPaint : fgPaint;
                    if (bgPaint == null) {
                        if (background instanceof Color) {
                            Color bg = (Color)background;
                            // 30/59/11 is standard weights, tweaked a bit
                            int brightness = 33 * bg.getRed()
                                + 53 * bg.getGreen()
                                + 14 * bg.getBlue();
                            foreground = brightness > 18500 ? Color.BLACK : Color.WHITE;
                        } else {
                            foreground = Color.WHITE;
                        }
                    } else {
                        foreground = bgPaint;
                    }
                }
                else {
                    foreground = fgPaint==null? savedPaint : fgPaint;
                    background = bgPaint;
                }

                if (background != null) {

                    Rectangle2D bgArea = label.getLogicalBounds();
                    bgArea = new Rectangle2D.Float(x + (float)bgArea.getX(),
                                                y + (float)bgArea.getY(),
                                                (float)bgArea.getWidth(),
                                                (float)bgArea.getHeight());

                    g2d.setPaint(background);
                    g2d.fill(bgArea);
                }

                g2d.setPaint(foreground);
                drawTextAndEmbellishments(label, g2d, x, y);
                g2d.setPaint(savedPaint);
            }
        }

        public Rectangle2D getVisualBounds(Label label) {

            Rectangle2D visBounds = label.handleGetVisualBounds();

            if (swapColors || bgPaint != null
                        || stdUnderline != null || imUnderline != null) {

                float minX = 0;
                Rectangle2D lb = label.getLogicalBounds();

                float minY = 0, maxY = 0;

                if (swapColors || bgPaint != null) {

                    minY = (float)lb.getY();
                    maxY = minY + (float)lb.getHeight();
                }

                maxY = Math.max(maxY, getUnderlineMaxY(label.getCoreMetrics()));

                Rectangle2D ab = new Rectangle2D.Float(minX, minY, (float)lb.getWidth(), maxY-minY);
                visBounds.add(ab);
            }

            return visBounds;
        }

        Shape getOutline(Label label,
                         float x,
                         float y) {

            if (!strikethrough && stdUnderline == null && imUnderline == null) {
                return label.handleGetOutline(x, y);
            }

            CoreMetrics cm = label.getCoreMetrics();

            // NOTE:  The performace of the following code may
            // be very poor.
            float ulThickness = cm.underlineThickness;

            Rectangle2D lb = label.getLogicalBounds();
            float x1 = x;
            float x2 = x1 + (float)lb.getWidth();

            Area area = null;

            if (stdUnderline != null) {
                Shape ul = stdUnderline.getUnderlineShape(ulThickness, x1, x2, y);
                area = new Area(ul);
            }

            if (strikethrough) {
                Stroke stStroke = new BasicStroke(cm.strikethroughThickness);
                float shiftY = y + cm.strikethroughOffset;
                Line2D line = new Line2D.Float(x1, shiftY, x2, shiftY);
                Area slArea = new Area(stStroke.createStrokedShape(line));
                if(area == null) {
                    area = slArea;
                } else {
                    area.add(slArea);
                }
            }

            if (imUnderline != null) {
                Shape ul = imUnderline.getUnderlineShape(ulThickness, x1, x2, y);
                Area ulArea = new Area(ul);
                if (area == null) {
                    area = ulArea;
                }
                else {
                    area.add(ulArea);
                }
            }

            // area won't be null here, since at least one underline exists.
            area.add(new Area(label.handleGetOutline(x, y)));

            return new GeneralPath(area);
        }


        public String toString() {
            StringBuffer buf = new StringBuffer();
            buf.append(super.toString());
            buf.append("[");
            if (fgPaint != null) buf.append("fgPaint: " + fgPaint);
            if (bgPaint != null) buf.append(" bgPaint: " + bgPaint);
            if (swapColors) buf.append(" swapColors: true");
            if (strikethrough) buf.append(" strikethrough: true");
            if (stdUnderline != null) buf.append(" stdUnderline: " + stdUnderline);
            if (imUnderline != null) buf.append(" imUnderline: " + imUnderline);
            buf.append("]");
            return buf.toString();
        }
    }
}
