/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.svg;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.batik.bridge.FontFamilyResolver;
import org.apache.batik.bridge.GlyphLayout;
import org.apache.batik.bridge.SVGGVTFont;
import org.apache.batik.bridge.StrokingTextPainter;
import org.apache.batik.bridge.TextLayoutFactory;
import org.apache.batik.bridge.TextNode;
import org.apache.batik.bridge.TextSpanLayout;
import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.text.TextPaintInfo;

import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
import org.apache.fop.svg.font.FOPGVTFont;
import org.apache.fop.svg.font.FOPGVTGlyphVector;
import org.apache.fop.svg.text.BidiAttributedCharacterIterator;
import org.apache.fop.svg.text.ComplexGlyphLayout;
import org.apache.fop.util.CharUtilities;

/**
 * Abstract base class for text painters that use specialized text commands native to an output
 * format to render text.
 */
public abstract class NativeTextPainter extends StrokingTextPainter {

    /** the logger for this class */
    protected static final Log log = LogFactory.getLog(NativeTextPainter.class);
    private static final boolean DEBUG = false;

    /** the font collection */
    protected final FontInfo fontInfo;

    protected final FontFamilyResolver fontFamilyResolver;

    protected Font font;

    protected TextPaintInfo tpi;

    /**
     * Creates a new instance.
     * @param fontInfo the font collection
     */
    public NativeTextPainter(FontInfo fontInfo) {
        this.fontInfo = fontInfo;
        this.fontFamilyResolver = new FOPFontFamilyResolverImpl(fontInfo);
    }

    /**
     * Indicates whether the given {@link Graphics2D} instance if compatible with this text painter
     * implementation.
     * @param g2d the instance to check
     * @return true if the instance is compatible.
     */
    protected abstract boolean isSupported(Graphics2D g2d);

    /**
     * Paints a single text run.
     * @param textRun the text run
     * @param g2d the target Graphics2D instance
     * @throws IOException if an I/O error occurs while rendering the text
     */
    protected final void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException {
        logTextRun(textRun);
        AttributedCharacterIterator runaci = textRun.getACI();
        runaci.first();
        tpi = (TextPaintInfo) runaci.getAttribute(PAINT_INFO);
        if (tpi == null || !tpi.visible) {
            return;
        }
        if (tpi.composite != null) {
            g2d.setComposite(tpi.composite);
        }
        TextSpanLayout layout = textRun.getLayout();
        GVTGlyphVector gv = layout.getGlyphVector();
        if (!(gv.getFont() instanceof FOPGVTFont)) {
            assert gv.getFont() == null || gv.getFont() instanceof SVGGVTFont;
            //Draw using Java2D when no native fonts are available
            textRun.getLayout().draw(g2d);
            return;
        } else {
            GeneralPath debugShapes = new GeneralPath();
            preparePainting(g2d);
            saveGraphicsState();
            setInitialTransform(g2d.getTransform());
            clip(g2d.getClip());
            beginTextObject();
            writeGlyphs((FOPGVTGlyphVector) gv, debugShapes);
            endTextObject();
            restoreGraphicsState();
            if (DEBUG) {
                g2d.setStroke(new BasicStroke(0));
                g2d.setColor(Color.LIGHT_GRAY);
                g2d.draw(debugShapes);
            }
        }
    }

    protected void writeGlyphs(FOPGVTGlyphVector gv, GeneralPath debugShapes) throws IOException {
        AffineTransform localTransform = new AffineTransform();
        Point2D prevPos = null;
        AffineTransform prevGlyphTransform = null;
        font = ((FOPGVTFont) gv.getFont()).getFont();
        for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
            if (!gv.isGlyphVisible(index)) {
                continue;
            }
            Point2D glyphPos = gv.getGlyphPosition(index);

            AffineTransform glyphTransform = gv.getGlyphTransform(index);
            if (log.isTraceEnabled()) {
                log.trace("pos " + glyphPos + ", transform " + glyphTransform);
            }
            if (DEBUG) {
                Shape sh = gv.getGlyphLogicalBounds(index);
                if (sh == null) {
                    sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2);
                }
                debugShapes.append(sh, false);
            }

            //Exact position of the glyph
            localTransform.setToIdentity();
            localTransform.translate(glyphPos.getX(), glyphPos.getY());
            if (glyphTransform != null) {
                localTransform.concatenate(glyphTransform);
            }
            localTransform.scale(1, -1);

            positionGlyph(prevPos, glyphPos, glyphTransform != null || prevGlyphTransform != null);
            char glyph = (char) gv.getGlyphCode(index);
            //Update last position
            prevPos = glyphPos;
            prevGlyphTransform = glyphTransform;

            writeGlyph(glyph, localTransform);
        }
    }

    @Override
    protected void paintTextRuns(@SuppressWarnings("rawtypes") List textRuns, Graphics2D g2d) {
        if (log.isTraceEnabled()) {
            log.trace("paintTextRuns: count = " + textRuns.size());
        }
        if (!isSupported(g2d)) {
            super.paintTextRuns(textRuns, g2d);
            return;
        }
        for (Object textRun1 : textRuns) {
            TextRun textRun = (TextRun) textRun1;
            try {
                paintTextRun(textRun, g2d);
            } catch (IOException ioe) {
                //No other possibility than to use a RuntimeException
                throw new RuntimeException(ioe);
            }
        }
    }

    /**
     * Collects all characters from an {@link AttributedCharacterIterator}.
     * @param runaci the character iterator
     * @return the characters
     */
    protected CharSequence collectCharacters(AttributedCharacterIterator runaci) {
        StringBuffer chars = new StringBuffer();
        for (runaci.first(); runaci.getIndex() < runaci.getEndIndex();) {
            chars.append(runaci.current());
            runaci.next();
        }
        return chars;
    }

    // Use FOP's bidi algorithm implementation and sub-divide each chunk into runs
    // that respect bidi level boundaries. N.B. batik does not sub-divide chunks at
    // bidi level boundaries because it performs eager reordering. In FOP, we need
    // to perform lazy reordering after character to glyph mapping occurs since
    // that mapping process requires logical (not visual) ordered input.
    @Override
    public List computeTextRuns(TextNode node, AttributedCharacterIterator nodeACI,
        AttributedCharacterIterator [] chunkACIs) {
        nodeACI.first();
        int defaultBidiLevel = (((Integer) nodeACI.getAttribute(WRITING_MODE)).intValue() == WRITING_MODE_RTL) ? 1 : 0;
        for (int i = 0, n = chunkACIs.length; i < n; ++i) {
            chunkACIs[i] = new BidiAttributedCharacterIterator(chunkACIs[i], defaultBidiLevel);
        }
        return super.computeTextRuns(node, nodeACI, chunkACIs, null);
    }

    // We want to sub-divide text chunks into distinct runs at bidi level boundaries.
    @Override
    protected Set getTextRunBoundaryAttributes() {
        Set textRunBoundaryAttributes = super.getTextRunBoundaryAttributes();
        if (!textRunBoundaryAttributes.contains(BIDI_LEVEL)) {
            textRunBoundaryAttributes.add(BIDI_LEVEL);
        }
        return textRunBoundaryAttributes;
    }

    // Perform reordering of runs.
    @Override
    protected List reorderTextRuns(TextChunk chunk, List runs) {
        // 1. determine min/max bidi levels for runs
        int mn = -1;
        int mx = -1;
        for (TextRun r : (List<TextRun>) runs) {
            int level = r.getBidiLevel();
            if (level >= 0) {
                if ((mn < 0) || (level < mn)) {
                    mn = level;
                }
                if ((mx < 0) || (level > mx)) {
                    mx = level;
                }
            }
        }

        // 2. reorder from maximum level to minimum odd level
        if (mx > 0) {
            for (int l1 = mx, l2 = ((mn & 1) == 0) ? (mn + 1) : mn; l1 >= l2; l1--) {
                runs = reorderRuns(runs, l1);
            }
        }

        // 3. reverse glyphs (and perform mirroring) in runs as needed
        boolean mirror = true;
        reverseGlyphs(runs, mirror);

        return runs;
    }

    private List reorderRuns(List runs, int level) {
        assert level >= 0;
        List runsNew = new java.util.ArrayList();
        for (int i = 0, n = runs.size(); i < n; i++) {
            TextRun tri = (TextRun) runs.get(i);
            if (tri.getBidiLevel() < level) {
                runsNew.add(tri);
            } else {
                int s = i;
                int e = s;
                while (e < n) {
                    TextRun tre = (TextRun) runs.get(e);
                    if (tre.getBidiLevel() < level) {
                        break;
                    } else {
                        e++;
                    }
                }
                if (s < e) {
                    runsNew.addAll(reverseRuns(runs, s, e));
                }
                i = e - 1;
            }
        }
        if (!runsNew.equals(runs)) {
            runs = runsNew;
        }
        return runs;
    }

    private List reverseRuns(List runs, int s, int e) {
        int n = e - s;
        List runsNew = new java.util.ArrayList(n);
        if (n > 0) {
            for (int i = 0; i < n; i++) {
                int k = (n - i - 1);
                TextRun tr = (TextRun) runs.get(s + k);
                tr.reverse();
                runsNew.add(tr);
            }
        }
        return runsNew;
    }

    private void reverseGlyphs(List runs, boolean mirror) {
        for (TextRun r : (List<TextRun>) runs) {
            r.maybeReverseGlyphs(mirror);
        }
    }

    protected abstract void preparePainting(Graphics2D g2d);

    protected abstract void saveGraphicsState() throws IOException;

    protected abstract void restoreGraphicsState() throws IOException;

    protected abstract void setInitialTransform(AffineTransform transform) throws IOException;

    protected abstract void clip(Shape clip) throws IOException;

    protected abstract void beginTextObject() throws IOException;

    protected abstract void endTextObject() throws IOException;

    protected abstract void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition);

    protected abstract void writeGlyph(char glyph, AffineTransform transform) throws IOException;


    protected final void logTextRun(TextRun textRun) {
        AttributedCharacterIterator runaci = textRun.getACI();
        TextSpanLayout layout = textRun.getLayout();
        runaci.first();
        if (log.isTraceEnabled()) {
            int charCount = runaci.getEndIndex() - runaci.getBeginIndex();
            log.trace("================================================");
            log.trace("New text run:");
            log.trace("char count: " + charCount);
            log.trace("range: "
                    + runaci.getBeginIndex() + " - " + runaci.getEndIndex());
            log.trace("glyph count: " + layout.getGlyphCount()); //=getNumGlyphs()
        }
    }

    /**
     * @param ch a character
     * @param layout a text span layout
     * @param index an index
     * @param visibleChar visible character flag
     */
    protected final void logCharacter(char ch, TextSpanLayout layout, int index,
            boolean visibleChar) {
        if (log.isTraceEnabled()) {
            log.trace("glyph " + index
                    + " -> " + layout.getGlyphIndex(index) + " => " + ch);
            if (CharUtilities.isAnySpace(ch) && ch != 32) {
                log.trace("Space found: " + Integer.toHexString(ch));
            } else if (ch == CharUtilities.ZERO_WIDTH_JOINER) {
                log.trace("ZWJ found: " + Integer.toHexString(ch));
            } else if (ch == CharUtilities.SOFT_HYPHEN) {
                log.trace("Soft hyphen found: " + Integer.toHexString(ch));
            }
            if (!visibleChar) {
                log.trace("Invisible glyph found: " + Integer.toHexString(ch));
            }
        }
    }

    @Override
    protected FontFamilyResolver getFontFamilyResolver() {
        return this.fontFamilyResolver;
    }

    private static final TextLayoutFactory COMPLEX_SCRIPT_TEXT_LAYOUT_FACTORY =
        new TextLayoutFactory() {
            public TextSpanLayout createTextLayout(AttributedCharacterIterator aci,
                int [] charMap, Point2D offset, FontRenderContext frc) {
                if (ComplexGlyphLayout.mayRequireComplexLayout(aci)) {
                    return new ComplexGlyphLayout(aci, charMap, offset, frc);
                } else {
                    return new GlyphLayout(aci, charMap, offset, frc);
                }
            }
        };

    @Override
    protected TextLayoutFactory getTextLayoutFactory() {
        return COMPLEX_SCRIPT_TEXT_LAYOUT_FACTORY;
    }

}
