/*
 * Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * 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. 1998-2003, All Rights Reserved
 *
 */

package sun.font;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.font.GraphicAttribute;
import java.awt.font.GlyphJustificationInfo;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.text.Bidi;
import java.util.Map;

public final class GraphicComponent implements TextLineComponent,
                                               Decoration.Label {

    public static final float GRAPHIC_LEADING = 2;

    private GraphicAttribute graphic;
    private int graphicCount;
    private int[] charsLtoV;  // possibly null
    private byte[] levels; // possibly null

    // evaluated in computeVisualBounds
    private Rectangle2D visualBounds = null;

    // used everywhere so we'll cache it
    private float graphicAdvance;

    private AffineTransform baseTx;

    private CoreMetrics cm;
    private Decoration decorator;


    /**
     * Create a new GraphicComponent.  start and limit are indices
     * into charLtoV and levels.  charsLtoV and levels may be adopted.
     */
    public GraphicComponent(GraphicAttribute graphic,
                            Decoration decorator,
                            int[] charsLtoV,
                            byte[] levels,
                            int start,
                            int limit,
                            AffineTransform baseTx) {

        if (limit <= start) {
            throw new IllegalArgumentException("0 or negative length in GraphicComponent");
        }
        this.graphic = graphic;
        this.graphicAdvance = graphic.getAdvance();
        this.decorator = decorator;
        this.cm = createCoreMetrics(graphic);
        this.baseTx = baseTx;

        initLocalOrdering(charsLtoV, levels, start, limit);
    }

    private GraphicComponent(GraphicComponent parent, int start, int limit, int dir) {

        this.graphic = parent.graphic;
        this.graphicAdvance = parent.graphicAdvance;
        this.decorator = parent.decorator;
        this.cm = parent.cm;
        this.baseTx = parent.baseTx;

        int[] charsLtoV = null;
        byte[] levels = null;

        if (dir == UNCHANGED) {
            charsLtoV = parent.charsLtoV;
            levels = parent.levels;
        }
        else if (dir == LEFT_TO_RIGHT || dir == RIGHT_TO_LEFT) {
            limit -= start;
            start = 0;
            if (dir == RIGHT_TO_LEFT) {
                charsLtoV = new int[limit];
                levels = new byte[limit];
                for (int i=0; i < limit; i++) {
                    charsLtoV[i] = limit-i-1;
                    levels[i] = (byte) 1;
                }
            }
        }
        else {
            throw new IllegalArgumentException("Invalid direction flag");
        }

        initLocalOrdering(charsLtoV, levels, start, limit);
    }

    /**
     * Initialize graphicCount, also charsLtoV and levels arrays.
     */
    private void initLocalOrdering(int[] charsLtoV,
                                   byte[] levels,
                                   int start,
                                   int limit) {

        this.graphicCount = limit - start; // todo: should be codepoints?

        if (charsLtoV == null || charsLtoV.length == graphicCount) {
            this.charsLtoV = charsLtoV;
        }
        else {
            this.charsLtoV = BidiUtils.createNormalizedMap(charsLtoV, levels, start, limit);
        }

        if (levels == null || levels.length == graphicCount) {
            this.levels = levels;
        }
        else {
            this.levels = new byte[graphicCount];
            System.arraycopy(levels, start, this.levels, 0, graphicCount);
        }
    }

    public boolean isSimple() {
        return false;
    }

    public Rectangle getPixelBounds(FontRenderContext frc, float x, float y) {
        throw new InternalError("do not call if isSimple returns false");
    }

    public Rectangle2D handleGetVisualBounds() {

        Rectangle2D bounds = graphic.getBounds();

        float width = (float) bounds.getWidth() +
                                 graphicAdvance * (graphicCount-1);

        return new Rectangle2D.Float((float) bounds.getX(),
                                     (float) bounds.getY(),
                                     width,
                                     (float) bounds.getHeight());
    }

    public CoreMetrics getCoreMetrics() {
        return cm;
    }

    public static CoreMetrics createCoreMetrics(GraphicAttribute graphic) {
        return new CoreMetrics(graphic.getAscent(),
                               graphic.getDescent(),
                               GRAPHIC_LEADING,
                               graphic.getAscent() + graphic.getDescent() + GRAPHIC_LEADING,
                               graphic.getAlignment(),
                               new float[] { 0, -graphic.getAscent() / 2, -graphic.getAscent() },
                               -graphic.getAscent() / 2,
                               graphic.getAscent() / 12,
                               graphic.getDescent() / 3,
                               graphic.getAscent() / 12,
                               0, // ss offset
                               0); // italic angle -- need api for this
    }

    public float getItalicAngle() {

        return 0;
    }

    public Rectangle2D getVisualBounds() {

        if (visualBounds == null) {
            visualBounds = decorator.getVisualBounds(this);
        }
        Rectangle2D.Float bounds = new Rectangle2D.Float();
        bounds.setRect(visualBounds);
        return bounds;
    }

    public Shape handleGetOutline(float x, float y) {
        double[] matrix = { 1, 0, 0, 1, x, y };

        if (graphicCount == 1) {
            AffineTransform tx = new AffineTransform(matrix);
            return graphic.getOutline(tx);
        }

        GeneralPath gp = new GeneralPath();
        for (int i = 0; i < graphicCount; ++i) {
            AffineTransform tx = new AffineTransform(matrix);
            gp.append(graphic.getOutline(tx), false);
            matrix[4] += graphicAdvance;
        }

        return gp;
    }

    public AffineTransform getBaselineTransform() {
        return baseTx;
    }

    public Shape getOutline(float x, float y) {

        return decorator.getOutline(this, x, y);
    }

    public void handleDraw(Graphics2D g2d, float x, float y) {

        for (int i=0; i < graphicCount; i++) {

            graphic.draw(g2d, x, y);
            x += graphicAdvance;
        }
    }

    public void draw(Graphics2D g2d, float x, float y) {

        decorator.drawTextAndDecorations(this, g2d, x, y);
    }

    public Rectangle2D getCharVisualBounds(int index) {

        return decorator.getCharVisualBounds(this, index);
    }

    public int getNumCharacters() {

        return graphicCount;
    }

    public float getCharX(int index) {

        int visIndex = charsLtoV==null? index : charsLtoV[index];
        return graphicAdvance * visIndex;
    }

    public float getCharY(int index) {

        return 0;
    }

    public float getCharAdvance(int index) {

        return graphicAdvance;
    }

    public boolean caretAtOffsetIsValid(int index) {

        return true;
    }

    public Rectangle2D handleGetCharVisualBounds(int index) {

        Rectangle2D bounds = graphic.getBounds();
        // don't modify their rectangle, just in case they don't copy

        Rectangle2D.Float charBounds = new Rectangle2D.Float();
        charBounds.setRect(bounds);
        charBounds.x += graphicAdvance * index;

        return charBounds;
    }

    // measures characters in context, in logical order
    public int getLineBreakIndex(int start, float width) {

        int index = (int) (width / graphicAdvance);
        if (index > graphicCount - start) {
            index = graphicCount - start;
        }
        return index;
    }

    // measures characters in context, in logical order
    public float getAdvanceBetween(int start, int limit) {

        return graphicAdvance * (limit - start);
    }

    public Rectangle2D getLogicalBounds() {

        float left = 0;
        float top = -cm.ascent;
        float width = graphicAdvance * graphicCount;
        float height = cm.descent - top;

        return new Rectangle2D.Float(left, top, width, height);
    }

    public float getAdvance() {
        return graphicAdvance * graphicCount;
    }

    public Rectangle2D getItalicBounds() {
        return getLogicalBounds();
    }

    public TextLineComponent getSubset(int start, int limit, int dir) {

        if (start < 0 || limit > graphicCount || start >= limit) {
            throw new IllegalArgumentException("Invalid range.  start="
                                               +start+"; limit="+limit);
        }

        if (start == 0 && limit == graphicCount && dir == UNCHANGED) {
            return this;
        }

        return new GraphicComponent(this, start, limit, dir);
    }

    public String toString() {

        return "[graphic=" + graphic + ":count=" + getNumCharacters() + "]";
    }

  /**
   * Return the number of justification records this uses.
   */
  public int getNumJustificationInfos() {
    return 0;
  }

  /**
   * Return GlyphJustificationInfo objects for the characters between
   * charStart and charLimit, starting at offset infoStart.  Infos
   * will be in visual order.  All positions between infoStart and
   * getNumJustificationInfos will be set.  If a position corresponds
   * to a character outside the provided range, it is set to null.
   */
  public void getJustificationInfos(GlyphJustificationInfo[] infos, int infoStart, int charStart, int charLimit) {
  }

  /**
   * Apply deltas to the data in this component, starting at offset
   * deltaStart, and return the new component.  There are two floats
   * for each justification info, for a total of 2 * getNumJustificationInfos.
   * The first delta is the left adjustment, the second is the right
   * adjustment.
   * <p>
   * If flags[0] is true on entry, rejustification is allowed.  If
   * the new component requires rejustification (ligatures were
   * formed or split), flags[0] will be set on exit.
   */
  public TextLineComponent applyJustificationDeltas(float[] deltas, int deltaStart, boolean[] flags) {
    return this;
  }
}
