/*
 * 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.
 */
package org.apache.fop.render.pdf.pdfbox;

import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

import org.apache.fontbox.ttf.MaximumProfileTable;

import org.apache.fop.fonts.truetype.FontFileReader;
import org.apache.fop.fonts.truetype.GlyfTable;
import org.apache.fop.fonts.truetype.OFDirTabEntry;
import org.apache.fop.fonts.truetype.OFMtxEntry;
import org.apache.fop.fonts.truetype.OFTableName;
import org.apache.fop.fonts.truetype.TTFSubSetFile;

public class MergeTTFonts extends TTFSubSetFile {
    private Map<Integer, Glyph> added = new TreeMap<Integer, Glyph>();
    private int origIndexesLen;
    private int size;
    protected MaximumProfileTable maxp = new MaximumProfileTable();
    private Integer nhmtxDiff = null;

    static class Glyph {
        final byte[] data;
        final OFMtxEntry mtx;
        Glyph(byte[] d, OFMtxEntry m) {
            data = d;
            mtx = m;
        }
    }

    /**
     * Create the glyf table and fill in loca table
     * @param glyphs map of glyphs
     * @param in fontfile
     * @throws IOException on error
     */
    private void readGlyf(Map<Integer, Integer> glyphs, FontFileReader in) throws IOException {
        OFDirTabEntry entry = dirTabs.get(OFTableName.GLYF);
        if (entry != null) {
            int[] origIndexes = buildSubsetIndexToOrigIndexMap(glyphs);
            for (int i = 0; i < origIndexes.length; i++) {
                int nextOffset = 0;
                int origGlyphIndex = origIndexes[i];
                if (origGlyphIndex >= (mtxTab.length - 1)) {
                    nextOffset = (int)lastLoca;
                } else {
                    nextOffset = (int)mtxTab[origGlyphIndex + 1].getOffset();
                }
                int glyphOffset = (int)mtxTab[origGlyphIndex].getOffset();
                int glyphLength = nextOffset - glyphOffset;
                if (glyphLength < 0) {
                    continue;
                }
                byte[] glyphData = in.getBytes(
                        (int)entry.getOffset() + glyphOffset,
                        glyphLength);

                Glyph g = new Glyph(glyphData, mtxTab[origGlyphIndex]);
                if (!cid && (origIndexesLen == 0 || (glyphLength > 0 && i > 0))) {
                    added.put(i, g);
                } else if (cid) {
                    added.put(i + origIndexesLen, g);
                }
            }
            if (!cid) {
                origIndexesLen = origIndexes.length;
            } else {
                origIndexesLen += origIndexes.length;
            }
        } else {
            throw new IOException("Can't find glyf table");
        }
    }

    private void createGlyf() throws IOException {
        OFDirTabEntry entry = dirTabs.get(OFTableName.GLYF);
        int size = 0;
        int startPos = 0;
        int endOffset = 0;    // Store this as the last loca

        if (entry != null) {
            pad4();
            startPos = currentPos;
            /* Loca table must be in order by glyph index, so build
             * an array first and then write the glyph info and
             * location offset.
             */
            glyphOffsets = new int[origIndexesLen];
            for (Map.Entry<Integer, Glyph> gly : added.entrySet()) {
                byte[] glyphData = gly.getValue().data;
                int glyphLength = glyphData.length;
                int i = gly.getKey();
                int endOffset1 = endOffset;
                // Copy glyph
                writeBytes(glyphData);
                // Update loca table
                if (cid || locaFormat == 1) {
                    writeULong(locaOffset + i * 4, currentPos - startPos);
                }
                if ((currentPos - startPos + glyphLength) > endOffset1) {
                    endOffset1 = currentPos - startPos + glyphLength;
                }

                // Store the glyph boundary positions relative to the start of the font
                glyphOffsets[i] = currentPos;
                currentPos += glyphLength;
                realSize += glyphLength;

                endOffset = endOffset1;
            }

            size = currentPos - startPos;

            currentPos += 12;
            realSize += 12;
            updateCheckSum(startPos, size + 12, OFTableName.GLYF);

            // Update loca checksum and last loca index
            if (cid || locaFormat == 1) {
                writeULong(locaOffset + added.size() * 4, endOffset);
            }
            int locaSize = added.size() * 4 + 4;
            int checksum = getCheckSum(output, locaOffset, locaSize);
            writeULong(offsets.get(OFTableName.LOCA), checksum);
            int padSize = (locaOffset + locaSize) % 4;
            newDirTabs.put(OFTableName.LOCA,
                    new OFDirTabEntry(locaOffset, locaSize + padSize));

            if (!cid && locaFormat == 0) {
                int i = 0;
                int offset = 0;
                for (Glyph e : added.values()) {
                    writeUShort(locaOffset + i * 2, offset / 2);
                    offset += e.data.length;
                    i++;
                }
                writeUShort(locaOffset + i * 2, offset / 2);
            }
        } else {
            throw new IOException("Can't find glyf table");
        }
    }

    /**
     * Create the hmtx table by copying metrics from original
     * font to subset font. The glyphs Map contains an
     * Integer key and Integer value that maps the original
     * metric (key) to the subset metric (value)
     * @throws IOException on error
     */
    protected void createHmtx() throws IOException {
        OFTableName hmtx = OFTableName.HMTX;
        OFDirTabEntry entry = dirTabs.get(hmtx);
        if (entry != null) {
            pad4();
            // int offset = (int)entry.offset;

            int longHorMetricSize = added.size() * 2;
            int leftSideBearingSize = added.size() * 2;
            int hmtxSize = longHorMetricSize + leftSideBearingSize;

            for (Map.Entry<Integer, Glyph> e : added.entrySet()) {
                Integer subsetIndex = e.getKey();
                OFMtxEntry mtx = e.getValue().mtx;
                writeUShort(currentPos + subsetIndex * 4,
                        mtx.getWx());
                writeUShort(currentPos + subsetIndex * 4 + 2,
                        mtx.getLsb());
            }

            updateCheckSum(currentPos, hmtxSize, hmtx);
            currentPos += hmtxSize;
            realSize += hmtxSize;
        } else {
            throw new IOException("Can't find hmtx table");
        }
    }

    /**
     * Returns a subset of the original font.
     *
     * @param fontFile font file
     * @param subsetGlyphs Map of glyphs (glyphs has old index as (Integer) key and
     * new index as (Integer) value)
     * @param cid is cid
     * @throws IOException in case of an I/O problem
     */
    public void readFont(FontFileReader fontFile, Map<Integer, Integer> subsetGlyphs, boolean cid) throws IOException {
        this.cid = cid;
        if (subsetGlyphs.isEmpty()) {
            return;
        }
        this.fontFile = fontFile;
        size += fontFile.getAllBytes().length;

        readDirTabs();
        readFontHeader();
        getNumGlyphs();
        readHorizontalHeader();
        readHorizontalMetrics();
        readIndexToLocation();
        int sgsize = subsetGlyphs.size();
        if (!cid && subsetGlyphs.size() <= 1) {
            for (int i = 0; i < mtxTab.length; i++) {
                subsetGlyphs.put(i, i);
            }
        }
        scanGlyphs(fontFile, subsetGlyphs);
        readGlyf(subsetGlyphs, fontFile);
        if (nhmtxDiff == null) {
            nhmtxDiff = sgsize - nhmtx;
            if (nhmtxDiff < 0) {
                nhmtxDiff = 0;
            }
        }
    }

    protected void scanGlyphs(FontFileReader in, Map<Integer, Integer> subsetGlyphs) throws IOException {
        OFDirTabEntry glyfTableInfo = dirTabs.get(OFTableName.GLYF);
        if (glyfTableInfo == null) {
            throw new IOException("Glyf table could not be found");
        }
        new MergeGlyfTable(in, mtxTab, glyfTableInfo, subsetGlyphs);
    }

    static class MergeGlyfTable extends GlyfTable {
        public MergeGlyfTable(FontFileReader in, OFMtxEntry[] metrics, OFDirTabEntry dirTableEntry,
                              Map<Integer, Integer> glyphs) throws IOException {
            super(in, metrics, dirTableEntry, glyphs);
            populateGlyphsWithComposites();
        }

        @Override
        protected void addAllComposedGlyphsToSubset() {
            int newIndex = -1;
            for (int v : subset.values()) {
                if (v > newIndex) {
                    newIndex = v;
                }
            }
            for (int composedGlyph : composedGlyphs) {
                subset.put(composedGlyph, ++newIndex);
            }
        }
    }

    public void writeFont(PDFBoxAdapter.Cmap cmap) throws IOException {
        output = new byte[size * 2];
        createDirectory();     // Create the TrueType header and directory
        int sgsize = added.size();
        if (!cid) {
            writeCMAP(cmap);
//            copyTable(fontFile, OFTableName.CMAP);
        }
        createHmtx();           // Create hmtx table
        if (cid || locaFormat == 1) {
            createLoca(sgsize);    // create empty loca table
        } else {
            createLoca(numberOfGlyphs / 2);    // create empty loca table
        }
        createHead(fontFile);
        createOS2(fontFile);                          // copy the OS/2 table
        if (!cid) {
            createHhea(fontFile, sgsize - nhmtxDiff);    // Create the hhea table
        } else {
            createHhea(fontFile, sgsize);    // Create the hhea table
        }
        if (maxp.getVersion() == 0) {
            createMaxp(fontFile, sgsize);    // copy the maxp table
        } else {
            writeMaxp();
        }
        boolean optionalTableFound;
        optionalTableFound = createCvt(fontFile);    // copy the cvt table
        if (!optionalTableFound) {
            // cvt is optional (used in TrueType fonts only)
            log.debug("TrueType: ctv table not present. Skipped.");
        }
        optionalTableFound = createFpgm(fontFile);    // copy fpgm table
        if (!optionalTableFound) {
            // fpgm is optional (used in TrueType fonts only)
            log.debug("TrueType: fpgm table not present. Skipped.");
        }
        createPost(fontFile);                         // copy the post table
        optionalTableFound = createPrep(fontFile);    // copy prep table
        if (!optionalTableFound) {
            // prep is optional (used in TrueType fonts only)
            log.debug("TrueType: prep table not present. Skipped.");
        }
        createName(fontFile);                         // copy the name table
        createGlyf(); //create glyf table and update loca table
        pad4();
        createCheckSumAdjustment();
    }

    private void writeMaxp() {
        int checksum = currentPos;
        pad4();
        int startPos = currentPos;
        writeUShort((int) maxp.getVersion()); //version
        writeUShort(0);
        writeUShort(added.size()); //numGlyphs
        writeUShort(maxp.getMaxPoints()); //maxPoints
        writeUShort(maxp.getMaxContours()); //maxContours
        writeUShort(maxp.getMaxCompositePoints()); //maxCompositePoints
        writeUShort(maxp.getMaxCompositeContours()); //maxCompositeContours
        writeUShort(maxp.getMaxZones()); //maxZones
        writeUShort(maxp.getMaxTwilightPoints()); //maxTwilightPoints
        writeUShort(maxp.getMaxStorage()); //maxStorage
        writeUShort(maxp.getMaxFunctionDefs()); //maxFunctionDefs
        writeUShort(maxp.getMaxInstructionDefs()); //maxInstructionDefs
        writeUShort(maxp.getMaxStackElements()); //maxStackElements
        writeUShort(maxp.getMaxSizeOfInstructions()); //maxSizeOfInstructions
        writeUShort(maxp.getMaxComponentElements()); //maxComponentElements
        writeUShort(maxp.getMaxComponentDepth()); //maxComponentDepth
        updateCheckSum(checksum, currentPos - startPos, OFTableName.MAXP);
        realSize += currentPos - startPos;
    }

    private void writeCMAP(PDFBoxAdapter.Cmap cmap) {
        int checksum = currentPos;
        pad4();
        int cmapPos = currentPos;
        writeUShort(0); //version
        writeUShort(1); //number of tables

        Map<Integer, Integer> glyphIdToCharacterCode = cmap.glyphIdToCharacterCode;
        writeUShort(cmap.platformId); //platformid
        writeUShort(cmap.platformEncodingId); //platformEncodingId
        writeULong(currentPos, currentPos - cmapPos + 12); //subTableOffset
        currentPos += 12;

        writeUShort(12); //subtableFormat
        writeUShort(0);
        writeULong(currentPos, (glyphIdToCharacterCode.size() * 12) + 16);
        currentPos += 4;
        writeULong(currentPos, 0);
        currentPos += 4;
        writeULong(currentPos, glyphIdToCharacterCode.size());
        currentPos += 4;

        for (Map.Entry<Integer, Integer> g : glyphIdToCharacterCode.entrySet()) {
            writeULong(currentPos, g.getKey());
            currentPos += 4;
            writeULong(currentPos, g.getKey());
            currentPos += 4;
            writeULong(currentPos, g.getValue());
            currentPos += 4;
        }

//            writeUShort(6); //subtableFormat
//            int firstCode = -1;
//            int lastCode = -1;
//            List<Integer> codes = new ArrayList<Integer>();
//            for (Map.Entry<Integer, Integer> g : glyphIdToCharacterCode.entrySet()) {
//                if (firstCode < 0) {
//                    firstCode = g.getKey();
//                }
//                while (lastCode > 0 && lastCode + 1 < g.getKey()) {
//                    codes.add(0);
//                    lastCode++;
//                }
//                codes.add(g.getValue());
//
//                lastCode = g.getKey();
//            }
//
//            writeUShort((codes.size() * 2) + 6); //length
//            writeUShort(0); //version
//
//            writeUShort(firstCode); //firstCode
//            writeUShort(codes.size()); //entryCount
//
//            for (int i : codes) {
//                writeUShort(i);
//            }

        updateCheckSum(checksum, currentPos - cmapPos, OFTableName.CMAP);
        realSize += currentPos - cmapPos;
    }

    /**
     * Get index from starting at lowest glyph position
     * @param glyphs map
     * @return index map
     */
    protected int[] buildSubsetIndexToOrigIndexMap(Map<Integer, Integer> glyphs) {
        int[] origIndexes = new int[glyphs.size()];
        int minIndex = Integer.MAX_VALUE;
        for (int glyph : glyphs.values()) {
            if (minIndex > glyph) {
                minIndex = glyph;
            }
        }
        for (Map.Entry<Integer, Integer> glyph : glyphs.entrySet()) {
            int origIndex = glyph.getKey();
            int subsetIndex = glyph.getValue() - minIndex;
            origIndexes[subsetIndex] = origIndex;
        }
        return origIndexes;
    }
}
