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

import java.util.ArrayList;
import java.util.List;

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

import org.apache.fop.complexscripts.fonts.GlyphPositioningTable;
import org.apache.fop.complexscripts.fonts.GlyphTable;
import org.apache.fop.complexscripts.util.CharScript;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.util.CharUtilities;

import static org.apache.fop.fonts.type1.AdobeStandardEncoding.i;

/**
 * Stores the mapping of a text fragment to glyphs, along with various information.
 */
public class GlyphMapping {

    private static final Log LOG = LogFactory.getLog(GlyphMapping.class);
    /** Inclusive. */
    public final int startIndex;
    /** Exclusive. */
    public final int endIndex;
    private int wordCharLength;
    public final int wordSpaceCount;
    public int letterSpaceCount;
    public MinOptMax areaIPD;
    public final boolean isHyphenated;
    public final boolean isSpace;
    public boolean breakOppAfter;
    public final Font font;
    public final int level;
    public final int[][] gposAdjustments;
    public String mapping;
    public List associations;

    public GlyphMapping(int startIndex, int endIndex, int wordSpaceCount, int letterSpaceCount,
            MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter,
            Font font, int level, int[][] gposAdjustments) {
        this(startIndex, endIndex, wordSpaceCount, letterSpaceCount, areaIPD, isHyphenated,
                isSpace, breakOppAfter, font, level, gposAdjustments, null, null);
    }

    public GlyphMapping(int startIndex, int endIndex, int wordSpaceCount, int letterSpaceCount,
            MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter,
            Font font, int level, int[][] gposAdjustments, String mapping, List associations) {
        assert startIndex <= endIndex;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
        this.wordCharLength = -1;
        this.wordSpaceCount = wordSpaceCount;
        this.letterSpaceCount = letterSpaceCount;
        this.areaIPD = areaIPD;
        this.isHyphenated = isHyphenated;
        this.isSpace = isSpace;
        this.breakOppAfter = breakOppAfter;
        this.font = font;
        this.level = level;
        this.gposAdjustments = gposAdjustments;
        this.mapping = mapping;
        this.associations = associations;
    }

    public static GlyphMapping doGlyphMapping(TextFragment text, int startIndex, int endIndex,
            Font font, MinOptMax letterSpaceIPD, MinOptMax[] letterSpaceAdjustArray,
            char precedingChar, char breakOpportunityChar, final boolean endsWithHyphen, int level,
            boolean dontOptimizeForIdentityMapping, boolean retainAssociations, boolean retainControls) {
        GlyphMapping mapping;
        if (font.performsSubstitution() || font.performsPositioning()) {
            mapping = processWordMapping(text, startIndex, endIndex, font,
                    breakOpportunityChar, endsWithHyphen, level,
                    dontOptimizeForIdentityMapping, retainAssociations, retainControls);
        } else {
            mapping = processWordNoMapping(text, startIndex, endIndex, font,
                    letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen, level);
        }
        return mapping;
    }

    private static GlyphMapping processWordMapping(TextFragment text, int startIndex,
            int endIndex, final Font font, final char breakOpportunityChar,
            final boolean endsWithHyphen, int level,
            boolean dontOptimizeForIdentityMapping, boolean retainAssociations, boolean retainControls) {
        int nLS = 0; // # of letter spaces
        String script = text.getScript();
        String language = text.getLanguage();

        if (LOG.isDebugEnabled()) {
            LOG.debug("PW: [" + startIndex + "," + endIndex + "]: {"
                    + " +M"
                    + ", level = " + level
                    + " }");
        }

        // 1. extract unmapped character sequence.
        CharSequence ics = text.subSequence(startIndex, endIndex);

        // 2. if script is not specified (by FO property) or it is specified as 'auto',
        // then compute dominant script.
        if ((script == null) || "auto".equals(script)) {
            script = CharScript.scriptTagFromCode(CharScript.dominantScript(ics));
        }
        if ((language == null) || "none".equals(language)) {
            language = "dflt";
        }

        // 3. perform mapping of chars to glyphs ... to glyphs ... to chars, retaining
        // associations if requested.
        List associations = retainAssociations ? new ArrayList() : null;

        // This is a workaround to read the ligature from the font even if the script
        // does not match the one defined for the table.
        // More info here: https://issues.apache.org/jira/browse/FOP-2638
        // zyyy == SCRIPT_UNDEFINED
        if ("zyyy".equals(script) || "auto".equals(script)) {
            script = "*";
        }

        CharSequence mcs = font.performSubstitution(ics, script, language, associations, retainControls);

        // 4. compute glyph position adjustments on (substituted) characters.
        int[][] gpa = null;
        if (font.performsPositioning()) {
            // handle GPOS adjustments
            gpa = font.performPositioning(mcs, script, language);
        }
        if (useKerningAdjustments(font, script, language)) {
            // handle standard (non-GPOS) kerning adjustments
            gpa = getKerningAdjustments(mcs, font, gpa);
        }

        // 5. reorder combining marks so that they precede (within the mapped char sequence) the
        // base to which they are applied; N.B. position adjustments (gpa) are reordered in place.
        mcs = font.reorderCombiningMarks(mcs, gpa, script, language, associations);

        // 6. compute word ipd based on final position adjustments.
        MinOptMax ipd = MinOptMax.ZERO;
        for (int i = 0, n = mcs.length(); i < n; i++) {
            int c = mcs.charAt(i);

            if (CharUtilities.containsSurrogatePairAt(mcs, i)) {
                c = Character.toCodePoint((char) c, mcs.charAt(++i));
            }

            int w = font.getCharWidth(c);
            if (w < 0) {
                w = 0;
            }
            if (gpa != null) {
                w += gpa[i][GlyphPositioningTable.Value.IDX_X_ADVANCE];
            }
            ipd = ipd.plus(w);
        }

        // [TBD] - handle letter spacing

        return new GlyphMapping(startIndex, endIndex, 0, nLS, ipd, endsWithHyphen, false,
                breakOpportunityChar != 0, font, level, gpa,
                !dontOptimizeForIdentityMapping && CharUtilities.isSameSequence(mcs, ics) ? null : mcs.toString(),
                associations);
    }

    private static boolean useKerningAdjustments(final Font font, String script, String language) {
        return font.hasKerning() && !font.hasFeature(GlyphTable.GLYPH_TABLE_TYPE_POSITIONING, script, language, "kern");
    }

    /**
     * Given a mapped character sequence MCS, obtain glyph position adjustments from the
     * font's kerning data.
     *
     * @param mcs mapped character sequence
     * @param font applicable font
     * @return glyph position adjustments (or null if no kerning)
     */
    private static int[][] getKerningAdjustments(CharSequence mcs, final Font font, int[][] gpa) {
        int numCodepoints = Character.codePointCount(mcs, 0, mcs.length());
        // extract kerning array
        int[] kernings = new int[numCodepoints]; // kerning array

        int prevCp = -1;
        int i = 0;
        for (int cp : CharUtilities.codepointsIter(mcs)) {
            if (prevCp >= 0) {
                kernings[i] = font.getKernValue(prevCp, cp);
            }
            prevCp = cp;
            i++;
        }
        // was there a non-zero kerning?
        boolean hasKerning = false;
        for (int kerningValue : kernings) {
            if (kerningValue != 0) {
                hasKerning = true;
                break;
            }
        }
        // if non-zero kerning, then create and return glyph position adjustment array
        if (hasKerning) {
            if (gpa == null) {
                gpa = new int[numCodepoints][4];
            }
            for (i = 0; i < numCodepoints; i++) {
                if (i > 0) {
                    gpa [i - 1][GlyphPositioningTable.Value.IDX_X_ADVANCE] += kernings[i];
                }
            }
            return gpa;
        } else {
            return null;
        }
    }

    private static GlyphMapping processWordNoMapping(TextFragment text, int startIndex, int endIndex,
            final Font font, MinOptMax letterSpaceIPD, MinOptMax[] letterSpaceAdjustArray,
            char precedingChar, final char breakOpportunityChar, final boolean endsWithHyphen, int level) {
        boolean kerning = font.hasKerning();
        MinOptMax wordIPD = MinOptMax.ZERO;

        if (LOG.isDebugEnabled()) {
            LOG.debug("PW: [" + startIndex + "," + endIndex + "]: {"
                    + " -M"
                    + ", level = " + level
                    + " }");
        }

        CharSequence ics = text.subSequence(startIndex, endIndex);
        int offset = 0;
        for (int currentChar : CharUtilities.codepointsIter(ics)) {

            // character width
            int charWidth = font.getCharWidth(currentChar);
            wordIPD = wordIPD.plus(charWidth);

            // kerning
            if (kerning) {
                int kern = 0;
                if (offset > 0) {
                    int previousChar = Character.codePointAt(ics, offset - 1);
                    kern = font.getKernValue(previousChar, currentChar);
                } else if (precedingChar != 0) {
                    kern = font.getKernValue(precedingChar, currentChar);
                }
                if (kern != 0) {
                    addToLetterAdjust(letterSpaceAdjustArray, startIndex + offset, kern);
                    wordIPD = wordIPD.plus(kern);
                }
            }
            offset++;
        }
        if (kerning
                && (breakOpportunityChar != 0)
                && !isSpace(breakOpportunityChar)
                && endIndex > 0
                && endsWithHyphen) {
            int endChar = text.charAt(endIndex - 1);

            if (Character.isLowSurrogate((char) endChar)) {
                char highSurrogate = text.charAt(endIndex - 2);
                endChar = Character.toCodePoint(highSurrogate, (char) endChar);
            }

            int kern = font.getKernValue(endChar, (int) breakOpportunityChar);
            if (kern != 0) {
                addToLetterAdjust(letterSpaceAdjustArray, endIndex, kern);
                // TODO: add kern to wordIPD?
            }
        }
        // shy+chars at start of word: wordLength == 0 && breakOpportunity
        // shy only characters in word: wordLength == 0 && !breakOpportunity
        int wordLength = endIndex - startIndex;
        int letterSpaces = 0;
        if (wordLength != 0) {
            letterSpaces = wordLength - 1;
            // if there is a break opportunity and the next one (break character)
            // is not a space, it could be used as a line end;
            // add one more letter space, in case other text follows
            if ((breakOpportunityChar != 0) && !isSpace(breakOpportunityChar)) {
                letterSpaces++;
            }
        }
        assert letterSpaces >= 0;
        wordIPD = wordIPD.plus(letterSpaceIPD.mult(letterSpaces));

        // create and return the AreaInfo object
        return new GlyphMapping(startIndex, endIndex, 0, letterSpaces, wordIPD, endsWithHyphen, false,
                (breakOpportunityChar != 0) && !isSpace(breakOpportunityChar), font, level, null);
    }

    private static void addToLetterAdjust(MinOptMax[] letterSpaceAdjustArray, int index, int width) {
        if (letterSpaceAdjustArray[index] == null) {
            letterSpaceAdjustArray[index] = MinOptMax.getInstance(width);
        } else {
            letterSpaceAdjustArray[index] = letterSpaceAdjustArray[index].plus(width);
        }
    }

    /**
     * Indicates whether a character is a space in terms of this layout manager.
     *
     * @param ch the character
     * @return true if it's a space
     */
    public static boolean isSpace(final char ch) {
        return ch == CharUtilities.SPACE
                || CharUtilities.isNonBreakableSpace(ch)
                || CharUtilities.isFixedWidthSpace(ch);
    }

    /**
     * Obtain number of 'characters' contained in word. If word is mapped, then this
     * number may be less than or greater than the original length (breakIndex -
     * startIndex). We compute and memoize thius length upon first invocation of this
     * method.
     */
    public int getWordLength() {
        if (wordCharLength == -1) {
            if (mapping != null) {
                wordCharLength = mapping.length();
            } else {
                assert endIndex >= startIndex;
                wordCharLength = endIndex - startIndex;
            }
        }
        return wordCharLength;
    }

    public void addToAreaIPD(MinOptMax idp) {
        areaIPD = areaIPD.plus(idp);
    }

    public String toString() {
        return super.toString() + "{"
                + "interval = [" + startIndex + "," + endIndex + "]"
                + ", isSpace = " + isSpace
                + ", level = " + level
                + ", areaIPD = " + areaIPD
                + ", letterSpaceCount = " + letterSpaceCount
                + ", wordSpaceCount = " + wordSpaceCount
                + ", isHyphenated = " + isHyphenated
                + ", font = " + font
                + "}";
    }

}
