/*
 * 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.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.fontbox.cff.CFFCIDFont;
import org.apache.fontbox.cff.CFFCharset;
import org.apache.fontbox.cff.CFFEncoding;
import org.apache.fontbox.cff.CFFFont;
import org.apache.fontbox.cff.CFFISOAdobeCharset;
import org.apache.fontbox.cff.CFFParser;
import org.apache.fontbox.cff.CFFStandardEncoding;
import org.apache.fontbox.cff.CFFStandardString;
import org.apache.fontbox.cff.CFFType1Font;

import org.apache.fop.fonts.cff.CFFDataReader;
import org.apache.fop.fonts.truetype.FontFileReader;

public class MergeCFFFonts extends OTFSubSetFile implements MergeFonts {
    protected List<Map<Integer, Integer>> subsetGlyphsList = new ArrayList<Map<Integer, Integer>>();
    private boolean fallbackIndex;
    private int charsetOffset;
    private int fontFileSize;
    private Set<String> used = new HashSet<String>();
    private List<String> strings = new ArrayList<String>();
    private List<Integer> chars = new ArrayList<Integer>();
    private List<String> added = new ArrayList<String>();
    private Map<Integer, Integer> range = new LinkedHashMap<Integer, Integer>();
    private int noOfFonts;
    private CFFEncoding encoding = null;

    public MergeCFFFonts() throws IOException {
        gidToSID = new LinkedHashMap<Integer, Integer>();
        subsetCharStringsIndex = new ArrayList<byte[]>();
    }

    public void readFont(InputStream is, String name, FontContainer fontContainer,
                         Map<Integer, Integer> subsetGlyphs, boolean cid) throws IOException {
        this.embeddedName = name;
        FontFileReader fontFile = new FontFileReader(is);
        CFFParser p = new CFFParser();
        CFFFont ff = p.parse(fontFile.getAllBytes()).get(0);

        if (used.containsAll(getStrings(ff).keySet())) {
            return;
        }
        fontFileSize += fontFile.getFileSize();
        this.fontFile = fontFile;
        used.addAll(getStrings(ff).keySet());
        if (fileFont == null) {
            fileFont = ff;
        }
        Map<Integer, Integer> sg = new LinkedHashMap<Integer, Integer>();
        for (int i = 0; i < ff.getNumCharStrings() + 1; i++) {
            sg.put(i, i);
        }
        subsetGlyphsList.add(sg);
        cffReader = new CFFDataReader(fontFile);

        for (int sid : getSids(ff.getCharset())) {
            if (sid >= NUM_STANDARD_STRINGS) {
                int index = sid - NUM_STANDARD_STRINGS;
                if (index <= cffReader.getStringIndex().getNumObjects()) {
                    String data = new String(cffReader.getStringIndex().getValue(index), "US-ASCII");
                    if (!strings.contains(data)) {
                        strings.add(data);
                    }
                }
            }
        }

        if (ff instanceof CFFType1Font) {
            encoding = ((CFFType1Font)ff).getEncoding();
            if (!(encoding instanceof CFFStandardEncoding)) {
                for (int c : encoding.getCodeToNameMap().keySet()) {
                    if (!chars.contains(c) && c != 0) {
                        chars.add(c);
                    }
                }
            }
        }
        setupMapping(ff.getCharset(), sg);

        for (Map.Entry<String, byte[]> s : getStrings(ff).entrySet()) {
            if (!added.contains(s.getKey())) {
                subsetCharStringsIndex.add(s.getValue());
                added.add(s.getKey());
            }
        }

        CFFCharset cSet = ff.getCharset();
        String cClass = cSet.getClass().getName();
        if (cClass.equals("org.apache.fontbox.cff.CFFParser$Format1Charset")
                || cClass.equals("org.apache.fontbox.cff.CFFParser$Format0Charset")) {
            for (int sid : getSids(cSet)) {
                range.put(sid, 0);
            }
        }
        noOfFonts++;
    }

    private void setupMapping(CFFCharset charset, Map<Integer, Integer> sg) {
        int subsetGlyphIndex = 0;
        for (int sid : getSids(charset)) {
            if (sg.containsKey(subsetGlyphIndex)) {
                int gid = sg.get(subsetGlyphIndex);

                //Check whether the SID falls into the standard string set
                if (sid < NUM_STANDARD_STRINGS) {
                    gidToSID.put(sg.get(gid), sid);
                } else {
                    int index = sid - NUM_STANDARD_STRINGS;
                    if (index <= cffReader.getStringIndex().getNumObjects()) {
                        gidToSID.put(sg.get(gid), stringIndexData.size() + NUM_STANDARD_STRINGS - 1);
                    } else {
                        gidToSID.put(sg.get(gid), index);
                    }
                }
                subsetGlyphIndex++;
            }
        }
    }

    public static List<Integer> getSids(CFFCharset cSet) {
        List<Integer> sids = new ArrayList<Integer>();
        try {
            for (int gid = 0; gid < 1024; gid++) {
                int sid = cSet.getCIDForGID(gid);
                if (sid != 0) {
                    sids.add(sid);
                }
            }
        } catch (IllegalStateException e) {
            try {
                final Method getSIDForGID = CFFCharset.class.getDeclaredMethod("getSIDForGID", int.class);
                AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        getSIDForGID.setAccessible(true);
                        return null;
                    }
                });
                for (int gid = 0; gid < 1024; gid++) {
                    int sid = (Integer)getSIDForGID.invoke(cSet, gid);
                    if (sid != 0) {
                        sids.add(sid);
                    }
                }
            } catch (NoSuchMethodException e1) {
                throw new RuntimeException(e1);
            } catch (InvocationTargetException e1) {
                throw new RuntimeException(e1);
            } catch (IllegalAccessException e1) {
                throw new RuntimeException(e1);
            }
        }
        return sids;
    }

    public static Map<String, byte[]> getStrings(CFFFont ff) throws IOException {
        CFFCharset cs = ff.getCharset();
        List<byte[]> csbytes = ff.getCharStringBytes();
        Map<String, byte[]> strings = new LinkedHashMap<String, byte[]>();
        int i = 0;
        try {
            for (int gid = 0; gid < 256; gid++) {
                String name = cs.getNameForGID(gid);
                if (name != null && i < csbytes.size()) {
                    strings.put(name, csbytes.get(i));
                    i++;
                }
            }
        } catch (IllegalStateException e) {
            strings.put(".notdef", csbytes.get(0));
            for (int sid : getSids(ff.getCharset())) {
                if (i < csbytes.size()) {
                    i++;
                    strings.put(readString(sid), csbytes.get(i));
                }
            }
        }
        return strings;
    }

    private static 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;
    }

    public byte[] getMergedFontSubset() throws IOException {
        output = new byte[fontFileSize * 2];
        if (noOfFonts == 1) {
            writeBytes(fontFile.getAllBytes());
            return super.getFontSubset();
        }
        createCFF();
        return super.getFontSubset();
    }

    protected void createCFF() throws IOException {
        //Header
        writeBytes(cffReader.getHeader());

        //Name Index
        writeIndex(Arrays.asList(fileFont.getName().getBytes("UTF-8")));

        //Keep offset of the topDICT so it can be updated once all data has been written
        int topDictOffset = currentPos;
        //Top DICT Index and Data
        byte[] topDictIndex = cffReader.getTopDictIndex().getByteData();
        int offSize = topDictIndex[2];
        writeBytes(topDictIndex, 0, 3 + (offSize * 2));
        int topDictDataOffset = currentPos;
        writeTopDICT();
        createCharStringData();

        //String index
        writeStringIndex();

        Map<String, CFFDataReader.DICTEntry> topDICT = cffReader.getTopDictEntries();
        final CFFDataReader.DICTEntry charString = topDICT.get("CharStrings");
        final CFFDataReader.DICTEntry encodingEntry = topDICT.get("Encoding");

        int encodingOffset;
        if (encodingEntry != null && charString.getOffset() > encodingEntry.getOffset()) {
            charsetOffset = currentPos;
            if (!fallbackIndex) {
                charsetOffset += 2;
            }
            writeCharsetTable(cffReader.getFDSelect() != null, !fallbackIndex);
            encodingOffset = currentPos;
            writeEncoding();
        } else {
            writeCard16(0);
            encodingOffset = currentPos;
            writeEncoding();
            charsetOffset = currentPos;
            writeCharsetTable(cffReader.getFDSelect() != null, false);
        }

        int fdSelectOffset = currentPos;
        if (cffReader.getFDSelect() != null) {
            writeByte(0);
            for (int i = 0; i < subsetCharStringsIndex.size(); i++) {
                writeByte(0);
            }
        }

        //Keep offset to modify later with the local subroutine index offset
        int privateDictOffset = currentPos;
        writePrivateDict();

        //Char Strings Index
        int charStringOffset = currentPos;
        writeIndex(subsetCharStringsIndex);

        //Local subroutine index
        int localIndexOffset = currentPos;
        if (!subsetLocalIndexSubr.isEmpty()) {
            writeIndex(subsetLocalIndexSubr);
        }

        if (cffReader.getFDSelect() != null) {
            int fdArrayOffset = currentPos;
            writeCard16(1);
            writeByte(1); //Offset size
            writeByte(1); //First offset
            int count = 1;
            for (CFFDataReader.FontDict fdFont : cffReader.getFDFonts()) {
                count += fdFont.getByteData().length;
                writeByte(count);
            }
            int fdByteData = currentPos;
            for (CFFDataReader.FontDict fdFont : cffReader.getFDFonts()) {
                writeBytes(fdFont.getByteData());
            }
            List<Integer> privateDictOffsets = new ArrayList<Integer>();
            for (CFFDataReader.FontDict curFDFont : cffReader.getFDFonts()) {
                privateDictOffsets.add(currentPos);
                writeBytes(curFDFont.getPrivateDictData());
                writeIndex(new ArrayList<byte[]>());
            }
            currentPos = fdByteData;
            int i = 0;
            for (CFFDataReader.FontDict fdFont : cffReader.getFDFonts()) {
                byte[] fdFontByteData = fdFont.getByteData();
                Map<String, CFFDataReader.DICTEntry> fdFontDict = cffReader.parseDictData(fdFontByteData);
                //Update the Private dict reference
                CFFDataReader.DICTEntry fdPrivate = fdFontDict.get("Private");
                updateOffset(fdFontByteData,
                        fdPrivate.getOffset() + fdPrivate.getOperandLengths().get(0),
                        fdPrivate.getOperandLengths().get(1),
                        privateDictOffsets.get(i));
                writeBytes(fdFontByteData);
                i++;
            }

            updateCIDOffsets(topDictDataOffset, fdArrayOffset, fdSelectOffset, charsetOffset, charStringOffset,
                    encodingOffset);
        } else {
            //Update the offsets
            updateOffsets(topDictOffset, charsetOffset, charStringOffset, privateDictOffset, localIndexOffset,
                    encodingOffset);
        }
    }

    protected void writeEncoding() throws IOException {
        if (!chars.isEmpty()) {
            writeCard16(chars.size());
            for (int i : chars) {
                writeByte(i);
            }
        }
    }

    protected void writeStringIndex() throws IOException {
        int stringIndexSize = stringIndexData.size();
        for (String s : strings) {
            stringIndexData.add(s.getBytes("US-ASCII"));
        }

        //Write the String Index
        if (!stringIndexData.isEmpty()) {
            if (!strings.isEmpty() && !new String(stringIndexData.get(0), "UTF-8").equals(strings.get(0))) {
                //Keep strings in order as they are referenced from the TopDICT
                for (int i = 0; i < stringIndexSize; i++) {
                    stringIndexData.add(stringIndexData.remove(0));
                }
            } else {
                String notice = (String)fileFont.getTopDict().get("Notice");
                if (notice != null && !(fileFont instanceof CFFCIDFont)) {
                    stringIndexData.add(notice.getBytes("ISO-8859-1"));
                }
            }
            stringIndexData.add(embeddedName.getBytes("UTF-8"));
            writeIndex(stringIndexData);
        } else {
            String notice = (String)fileFont.getTopDict().get("Notice");
            if (notice != null) {
                writeIndex(Arrays.<byte[]>asList(notice.getBytes("ISO-8859-1"), embeddedName.getBytes("UTF-8")));
            } else {
                List<byte[]> sindex = new ArrayList<byte[]>();
                sindex.add(cffReader.getStringIndex().getData());
                if (sindex.size() > 1) {
                    fallbackIndex = true;
                    writeIndex(sindex);
                } else if (sindex.size() == 1) {
                    writeIndex(Arrays.asList(embeddedName.getBytes("UTF-8")));
                } else {
                    writeCard16(0);
                }
            }
        }
    }

    protected void createCharStringData() throws IOException {
        //Create the two lists which are to store the local and global subroutines
        subsetLocalIndexSubr = new ArrayList<byte[]>();

        localUniques = new ArrayList<Integer>();
        globalUniques = new ArrayList<Integer>();

        //Store the size of each subset index and clear the unique arrays
        localUniques.clear();
        globalUniques.clear();
    }

    protected void writeCharsetTable(boolean cidFont, boolean afterstringindex) throws IOException {
        if (range.isEmpty()) {
            writeByte(0);
            for (Map.Entry<Integer, Integer> gid : gidToSID.entrySet()) {
                if (cidFont && gid.getKey() == 0) {
                    continue;
                }
                writeCard16(cidFont ? gid.getKey() : gid.getValue());
            }
        } else {
            writeFormat1CS(range, afterstringindex);
        }
    }

    private void writeFormat1CS(Map<Integer, Integer> range, boolean afterstringindex) {
        if (!afterstringindex) {
            charsetOffset += 2;
        }
        writeByte(0);
        writeCard16(1);
        updateStandardRange(range);
        for (Map.Entry<Integer, Integer> i : range.entrySet()) {
            writeCard16(i.getKey());
            writeByte(i.getValue());
        }
        writeByte(1);
    }

    private void updateStandardRange(Map<Integer, Integer> range) {
        if (range.containsKey(NUM_STANDARD_STRINGS) && range.containsKey(NUM_STANDARD_STRINGS + 1)) {
            boolean mixedCS = false;
            for (int i : range.keySet()) {
                if (i < NUM_STANDARD_STRINGS && i > 1) {
                    mixedCS = true;
                    break;
                }
            }
            if (!mixedCS) {
                if (range.containsKey(1)) {
                    range.clear();
                    range.put(1, 0);
                }
                int last = -1;
                boolean simpleRange = false;
                for (int i : range.keySet()) {
                    simpleRange = last + 1 == i;
                    last = i;
                }
                if (simpleRange) {
                    for (int i = NUM_STANDARD_STRINGS; i < NUM_STANDARD_STRINGS + subsetCharStringsIndex.size(); i++) {
                        range.put(i, 0);
                    }
                } else {
                    range.put(NUM_STANDARD_STRINGS, subsetCharStringsIndex.size());
                }
            }
        } else if (cffReader.getFDSelect() instanceof CFFDataReader.Format3FDSelect) {
            int last = -1;
            int count = 1;
            Set<Integer> r = new TreeSet<Integer>(range.keySet());
            for (int i : r) {
                if (last + count == i) {
                    range.remove(i);
                    range.put(last, count);
                    count++;
                } else {
                    last = i;
                    count = 1;
                }
            }
        }
    }

    @Override
    protected void updateFixedOffsets(Map<String, CFFDataReader.DICTEntry> topDICT, int dataTopDictOffset,
                                      int charsetOffset, int charStringOffset, int encodingOffset) {
        //Charset offset in the top dict
        final CFFDataReader.DICTEntry charset = topDICT.get("charset");
        if (charset != null) {
            int oldCharsetOffset = dataTopDictOffset + charset.getOffset();
            int oldCharset = Integer.parseInt(String.format("%02x", output[oldCharsetOffset] & 0xff), 16);
            if (oldCharset >= 32 && oldCharset <= 246) {
                charsetOffset += 139;
            }
            updateOffset(output, oldCharsetOffset, charset.getOperandLength(), charsetOffset);
        }

        //Char string index offset in the private dict
        final CFFDataReader.DICTEntry charString = topDICT.get("CharStrings");
        int oldCharStringOffset = dataTopDictOffset + charString.getOffset();
        int oldString = Integer.parseInt(String.format("%02x", output[oldCharStringOffset] & 0xff), 16);
        if (oldString >= 32 && oldString <= 246) {
            charStringOffset += 139;
        }
        if (!(fileFont.getCharset() instanceof CFFISOAdobeCharset)) {
            updateOffset(output, oldCharStringOffset, charString.getOperandLength(), charStringOffset);
        }

        final CFFDataReader.DICTEntry encodingEntry = topDICT.get("Encoding");
        if (encodingEntry != null && encodingEntry.getOperands().get(0).intValue() != 0
                && encodingEntry.getOperands().get(0).intValue() != 1) {
            int oldEncodingOffset = dataTopDictOffset + encodingEntry.getOffset();
            int oldEnc = Integer.parseInt(String.format("%02x", output[oldEncodingOffset] & 0xff), 16);
            if (oldEnc >= 32 && oldEnc <= 246) {
                encodingOffset += 139;
            } else {
                encodingOffset--;
            }
            updateOffset(output, oldEncodingOffset, encodingEntry.getOperandLength(), encodingOffset);
        }
    }

    protected void writeCIDCount(CFFDataReader.DICTEntry dictEntry) throws IOException {
        writeBytes(dictEntry.getByteData());
    }
}
