/*
 * 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.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.io.IOUtils;
import org.apache.fontbox.cff.CFFCharset;
import org.apache.fontbox.cff.CFFFont;
import org.apache.fontbox.cff.CFFStandardString;
import org.apache.fontbox.cmap.CMap;

import org.apache.fontbox.ttf.CmapSubtable;
import org.apache.fontbox.ttf.GlyphData;
import org.apache.fontbox.ttf.TrueTypeFont;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSObject;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.font.PDCIDFont;
import org.apache.pdfbox.pdmodel.font.PDCIDFontType0;
import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.encoding.GlyphList;

import org.apache.fop.fonts.CIDFontType;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbeddingMode;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.pdf.PDFDictionary;
import org.apache.fop.util.CharUtilities;

public class FOPPDFMultiByteFont extends MultiByteFont implements FOPPDFFont {
    protected PDFDictionary ref;
    private Map<Integer, Integer> newWidth = new TreeMap<Integer, Integer>();
    private Map<String, Integer> charMapGlobal = new LinkedHashMap<String, Integer>();
    private MergeFonts mergeFonts;
    //private Map<String, GlyphData> glyphs = new HashMap<String, GlyphData>();
    private final Map<COSDictionary, FontContainer> fontMap = new HashMap<COSDictionary, FontContainer>();

    public FOPPDFMultiByteFont(COSDictionary fontData, String name) throws IOException {
        super(null, EmbeddingMode.SUBSET);
        //this stops fop modifying font later on
        setEmbeddingMode(EmbeddingMode.FULL);
        readFontBBox(fontData);
        setFontName(name);
        addFont(fontData);
        notifyMapOperation();
    }

    public String addFont(COSDictionary fontData) throws IOException {
        FontContainer font = getFont(fontData);
        setProperties(this, font.font);
        PDCIDFont mainFont = null;
        TrueTypeFont ttf = null;
        if (font.font instanceof PDType0Font) {
            PDCIDFont cidFont = ((PDType0Font) font.font).getDescendantFont();
            int dw = cidFont.getCOSObject().getInt(COSName.DW);
            setDefaultWidth(dw);
            mainFont = cidFont;
            if (cidFont instanceof PDCIDFontType0) {
                setCIDType(CIDFontType.CIDTYPE0);
                setFontType(FontType.CIDTYPE0);
            } else {
                ttf = ((PDCIDFontType2) cidFont).getTrueTypeFont();
            }
        } else {
            ttf = ((PDTrueTypeFont) font.font).getTrueTypeFont();
            setDefaultWidth(1000);
        }
        GlyphData[] glyphData = new GlyphData[0];
        if (ttf != null) {
            glyphData = ttf.getGlyph().getGlyphs();
        }
        Map<Integer, Integer> oldToNewGIMap = new HashMap<Integer, Integer>();
        if (charMapGlobal.isEmpty()) {
            oldToNewGIMap.put(0, 0); // .notdef glyph
        }
        CMap c = font.getToUnicodeCMap();
        Map<Integer, String> mapping = getMapping(font, c, glyphData.length);
        if (glyphData.length > 0) {
            differentGlyphData(glyphData, mapping);
        }
        Map<Integer, String> gidToGlyph = new TreeMap<Integer, String>(mapping);
        if (font.font instanceof PDTrueTypeFont) {
            CmapSubtable cmap = ttf.getCmap().getCmaps()[0];
            gidToGlyph.clear();
            for (int i = 1; i < glyphData.length; i++) {
                String mappedChar = mapping.get(cmap.getCharacterCode(i));
                gidToGlyph.put(i, mappedChar);
            }
        }
        readCharMap(font, gidToGlyph, glyphData, mainFont, oldToNewGIMap);
        InputStream ffr = readFontFile(font.font);
        if (mergeFonts == null) {
            if (ttf != null) {
                mergeFonts = new MergeTTFonts(null);
            } else {
                mergeFonts = new MergeCFFFonts();
            }
        }
        if (mergeFonts instanceof MergeTTFonts) {
            mergeMaxp(ttf, ((MergeTTFonts)mergeFonts).maxp);
            int sizeNoCompGlyphs = oldToNewGIMap.size();
            mergeFonts.readFont(ffr, null, null, oldToNewGIMap, true);
            if (oldToNewGIMap.size() > sizeNoCompGlyphs) {
                cidSet.mapChar(256 * 256, (char) 0);
            }
        } else {
            mergeFonts.readFont(ffr, getEmbedFontName(), null, null, true);
        }
        return getFontName();
    }

    private void readCharMap(FontContainer font, Map<Integer, String> gidToGlyph, GlyphData[] glyphData,
                             PDCIDFont mainFont, Map<Integer, Integer> oldToNewGIMap) throws IOException {
        int widthPos = font.getFirstChar() + 1;
        for (Map.Entry<Integer, String> i : gidToGlyph.entrySet()) {
            String mappedChar = i.getValue();
            int key = i.getKey();
            boolean skipWidth = (mappedChar == null) || mappedChar.length() == 0;
            if (skipWidth) {
                mappedChar = (char)charMapGlobal.size() + "tmp";
            } else if (mappedChar.length() > 1) {
                mappedChar = "" + (char)mappedChar.hashCode();
            }
            if (!charMapGlobal.containsKey(mappedChar)) {
                if (glyphData.length > 0
                        && glyphData[key] == null
                        && !CharUtilities.isAdjustableSpace(mappedChar.charAt(0))) {
                    continue;
                }
                boolean addToEnd = charMapGlobal.containsValue(key);
                if (addToEnd) {
                    addPrivateUseMapping(mappedChar.charAt(0), charMapGlobal.size() + 1);
                    charMapGlobal.put(mappedChar, charMapGlobal.size() + 1);
                } else {
                    addPrivateUseMapping(mappedChar.charAt(0), key);
                    charMapGlobal.put(mappedChar, key);
                }
                int glyph = 0;
                if (hasChar(mappedChar.charAt(0))) {
                    glyph = (int) mapChar(mappedChar.charAt(0));
                }
                oldToNewGIMap.put(key, glyph);
                if (!skipWidth) {
                    if (!(font.font instanceof PDTrueTypeFont)) {
                        widthPos = key;
                    }
                    float w = font.font.getWidth(widthPos);
                    if (w >= 0) {
                        if (mainFont instanceof PDCIDFontType0) {
                            newWidth.put(key, (int)w);
                        } else {
                            newWidth.put(glyph, (int)w);
                        }
                    }
                }
            }
            if (!skipWidth) {
                widthPos++;
            }
        }
    }

    private Map<Integer, String> getMapping(FontContainer font, CMap c, int len) throws IOException {
        Map<Integer, String> mapping = new HashMap<Integer, String>();
        if (font.font instanceof PDType0Font) {
            PDCIDFont cidFont = ((PDType0Font) font.font).getDescendantFont();
            if (cidFont instanceof PDCIDFontType0) {
                mapping = getStrings(((PDCIDFontType0) cidFont).getCFFFont());
            }
        }
        if (c != null) {
            int last = font.getLastChar();
            if (last == -1) {
                last = len;
            }
            for (int i = font.getFirstChar(); i <= last; i++) {
                String l = c.toUnicode(i);
                if (l != null) {
                    mapping.put(i, l);
                }
            }
        }
        return mapping;
    }

    private Map<Integer, String> getStrings(CFFFont ff) throws IOException {
        CFFCharset cs = ff.getCharset();
        Map<Integer, String> strings = new LinkedHashMap<Integer, String>();
        for (int gid = 0; gid < 256; gid++) {
            int sid = cs.getCIDForGID(gid);
            if (sid != 0) {
                strings.put(sid, GlyphList.getAdobeGlyphList().toUnicode(readString(sid)));
            }
        }
        return strings;
    }

    private String readString(int index) throws IOException {
        if (index >= 0 && index <= 390) {
            return CFFStandardString.getName(index);
        }
        // technically this maps to .notdef, but we need a unique glyph name
        return "SID" + index;
    }

        private boolean differentGlyphData(GlyphData[] data, Map<Integer, String> mapping) throws IOException {
            Map<String, Integer> tmpMap = new HashMap<String, Integer>();
            for (Map.Entry<Integer, String> entry : mapping.entrySet()) {
                if (!tmpMap.containsKey(entry.getValue())) {
                    tmpMap.put(entry.getValue(), entry.getKey());
                }
            }
            mapping.clear();
            for (Map.Entry<String, Integer> entry : tmpMap.entrySet()) {
                mapping.put(entry.getValue(), entry.getKey());
            }

            for (Map.Entry<Integer, String> n : mapping.entrySet()) {
                if (n.getKey() >= data.length) {
                    throw new IOException("Mapping not found in glyphData");
                }
//                if (data[n.getKey()] != null) {
//                    if (glyphs.containsKey(n.getValue()) && !glyphs.get(n.getValue()).equals(data[n.getKey()])) {
//                        return true;
//                    }
//                    glyphs.put(n.getValue(), data[n.getKey()]);
//                }
            }
            return false;
        }

    private InputStream readFontFile(PDFont font) throws IOException {
        PDFontDescriptor fd = font.getFontDescriptor();
        if (font instanceof PDType0Font) {
            PDCIDFont cidFont = ((PDType0Font) font).getDescendantFont();
            fd = cidFont.getFontDescriptor();
        }
        PDStream ff = fd.getFontFile3();
        if (ff == null) {
            ff = fd.getFontFile2();
            if (ff == null) {
                ff = fd.getFontFile();
            }
        }
        if (ff == null) {
            throw new IOException(font.getName() + " no fontfile");
        }
        InputStream is = ff.createInputStream();
        return new ByteArrayInputStream(IOUtils.toByteArray(is));
    }

    public Map<Integer, Integer> getWidthsMap() {
        return newWidth;
    }

    public PDFDictionary getRef() {
        return ref;
    }

    public void setRef(PDFDictionary d) {
        ref = d;
    }

    public int size() {
        if (getFontType() == FontType.CIDTYPE0) {
            return 1;
        }
        return 0;
    }

    private void readFontBBox(COSBase b) throws IOException {
        if (b instanceof COSDictionary) {
            COSDictionary dict = (COSDictionary)b;
            for (Map.Entry<COSName, COSBase> n : dict.entrySet()) {
                readFontBBox(n.getValue());
                if (n.getKey() == COSName.FONT_BBOX) {
                    COSArray w = (COSArray)n.getValue();
                    float[] bboxf = w.toFloatArray();
                    int[] bbox = new int[bboxf.length];
                    for (int i = 0; i < bbox.length; i++) {
                        bbox[i] = (int)bboxf[i];
                    }
                    setFontBBox(bbox);
                }
            }
        } else if (b instanceof COSObject) {
            COSObject o = (COSObject)b;
            readFontBBox(o.getObject());
        } else if (b instanceof COSArray) {
            COSArray o = (COSArray)b;
            for (int i = 0; i < o.size(); i++) {
                readFontBBox(o.get(i));
            }
        }
    }

    public boolean isEmbeddable() {
        return true;
    }

    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(mergeFonts.getMergedFontSubset());
    }

    protected FontContainer getFont(COSDictionary fontData) throws IOException {
        if (!fontMap.containsKey(fontData)) {
            if (fontMap.size() > 10) {
                fontMap.clear();
            }
            fontMap.put(fontData, new FontContainer(fontData));
        }
        return fontMap.get(fontData);
    }

    protected static void setProperties(CustomFont cFont, PDFont font) {
        if (font.getFontDescriptor() != null) {
            cFont.setCapHeight((int) font.getFontDescriptor().getCapHeight());
            cFont.setAscender((int)font.getFontDescriptor().getAscent());
            cFont.setDescender((int)font.getFontDescriptor().getDescent());
            cFont.setXHeight((int)font.getFontDescriptor().getXHeight());
            cFont.setStemV((int)font.getFontDescriptor().getStemV());
        }
    }

    protected static void mergeMaxp(TrueTypeFont ttf, MaximumProfileTable outMaxp) throws IOException {
        org.apache.fontbox.ttf.MaximumProfileTable mp = ttf.getMaximumProfile();
        outMaxp.setVersion(mp.getVersion());
        outMaxp.setNumGlyphs(outMaxp.getNumGlyphs() + mp.getNumGlyphs());
        outMaxp.setMaxPoints(outMaxp.getMaxPoints() + mp.getMaxPoints());
        outMaxp.setMaxContours(outMaxp.getMaxContours() + mp.getMaxContours());
        outMaxp.setMaxCompositePoints(outMaxp.getMaxCompositePoints() + mp.getMaxCompositePoints());
        outMaxp.setMaxCompositeContours(outMaxp.getMaxCompositeContours() + mp.getMaxCompositeContours());
        outMaxp.setMaxZones(outMaxp.getMaxZones() + mp.getMaxZones());
        outMaxp.setMaxTwilightPoints(outMaxp.getMaxTwilightPoints() + mp.getMaxTwilightPoints());
        outMaxp.setMaxStorage(outMaxp.getMaxStorage() + mp.getMaxStorage());
        outMaxp.setMaxFunctionDefs(outMaxp.getMaxFunctionDefs() + mp.getMaxFunctionDefs());
        outMaxp.setMaxInstructionDefs(outMaxp.getMaxInstructionDefs() + mp.getMaxInstructionDefs());
        outMaxp.setMaxStackElements(outMaxp.getMaxStackElements() + mp.getMaxStackElements());
        outMaxp.setMaxSizeOfInstructions(outMaxp.getMaxSizeOfInstructions() + mp.getMaxSizeOfInstructions());
        outMaxp.setMaxComponentElements(outMaxp.getMaxComponentElements() + mp.getMaxComponentElements());
        outMaxp.setMaxComponentDepth(outMaxp.getMaxComponentDepth() + mp.getMaxComponentDepth());
    }
}
