/*
 * 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)) {
        //    return null;
        //}
        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 (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());
    }
}
