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

// Java
import java.util.Collections;
import java.util.Set;

import org.apache.fop.fonts.CodePointMapping;
import org.apache.fop.fonts.SingleByteEncoding;

/**
 * Class representing an /Encoding object.
 *
 * A small object expressing the base encoding name and
 * the differences from the base encoding.
 *
 * The three base encodings are given by their name.
 *
 * Encodings are specified in section 5.5.5 of the PDF 1.4 spec.
 */
public class PDFEncoding extends PDFDictionary {

    /** the name for the standard encoding scheme */
    public static final String STANDARD_ENCODING = "StandardEncoding";
    /** the name for the Mac Roman encoding scheme */
    public static final String MAC_ROMAN_ENCODING = "MacRomanEncoding";
    /** the name for the Mac Export encoding scheme */
    public static final String MAC_EXPERT_ENCODING = "MacExpertEncoding";
    /** the name for the WinAnsi encoding scheme */
    public static final String WIN_ANSI_ENCODING = "WinAnsiEncoding";
    /** the name for the PDF document encoding scheme */
    public static final String PDF_DOC_ENCODING = "PDFDocEncoding";

    /** the set of predefined encodings that can be assumed present in a PDF viewer */
    private static final Set PREDEFINED_ENCODINGS;

    static {
        Set encodings = new java.util.HashSet();
        encodings.add(STANDARD_ENCODING);
        encodings.add(MAC_ROMAN_ENCODING);
        encodings.add(MAC_EXPERT_ENCODING);
        encodings.add(WIN_ANSI_ENCODING);
        encodings.add(PDF_DOC_ENCODING);
        PREDEFINED_ENCODINGS = Collections.unmodifiableSet(encodings);
    }

    /**
     * Create a new /Encoding object.
     *
     * @param basename the name of the character encoding schema
     */
    public PDFEncoding(String basename) {
        super();

        put("Type", new PDFName("Encoding"));
        if (basename != null) {
            put("BaseEncoding", new PDFName(basename));
        }
    }

    /**
     * Creates a PDFEncoding instance from a CodePointMapping instance.
     * @param encoding the code point mapping (encoding)
     * @param fontName ...
     * @return the PDF Encoding dictionary (or a String with the predefined encoding)
     */
    static Object createPDFEncoding(SingleByteEncoding encoding, String fontName) {
        //If encoding type is null, return null which causes /Encoding to be omitted.
        if (encoding == null) {
            return null;
        }
        String encodingName = null;
        SingleByteEncoding baseEncoding;
        if (fontName.indexOf("Symbol") >= 0) {
            baseEncoding = CodePointMapping.getMapping(CodePointMapping.SYMBOL_ENCODING);
            encodingName = baseEncoding.getName();
        } else {
            baseEncoding = CodePointMapping.getMapping(CodePointMapping.STANDARD_ENCODING);
        }
        PDFEncoding pdfEncoding = new PDFEncoding(encodingName);
        PDFEncoding.DifferencesBuilder builder = pdfEncoding.createDifferencesBuilder();
        PDFArray differences = builder.buildDifferencesArray(baseEncoding, encoding);
        // TODO This method should not be returning an Object with two different outcomes
        // resulting in subsequent `if (X instanceof Y)` statements.
        if (differences.length() > 0) {
            pdfEncoding.setDifferences(differences);
            return pdfEncoding;
        } else {
            return encodingName;
        }
    }

    /**
     * Indicates whether a given encoding is one of the predefined encodings.
     * @param name the encoding name (ex. "StandardEncoding")
     * @return true if it is a predefined encoding
     */
    public static boolean isPredefinedEncoding(String name) {
        return PREDEFINED_ENCODINGS.contains(name);
    }

    /**
     * Indicates whether the given encoding type is that of standard encoding
     * @param name The encoding name
     * @return Returns true if it is of type standard encoding
     */
    static boolean hasStandardEncoding(String encodingName) {
        return encodingName.equals(STANDARD_ENCODING);
    }

    /**
     * Creates and returns a new DifferencesBuilder instance for constructing the Differences
     * array.
     * @return the DifferencesBuilder
     */
    public DifferencesBuilder createDifferencesBuilder() {
        return new DifferencesBuilder();
    }

    /**
     * Sets the Differences value.
     * @param differences the differences.
     */
    public void setDifferences(PDFArray differences) {
        put("Differences", differences);
    }

    /**
     * Builder class for constructing the Differences array.
     */
    public class DifferencesBuilder {

        private int currentCode = -1;

        /**
         * Creates an array containing the differences between two single-byte.
         * font encodings.
         * @param encodingA The first single-byte encoding
         * @param encodingB The second single-byte encoding
         * @return The PDFArray of differences between encodings
         */
        public PDFArray buildDifferencesArray(SingleByteEncoding encodingA,
                SingleByteEncoding encodingB) {
            PDFArray differences = new PDFArray();
            int start = -1;
            String[] baseNames = encodingA.getCharNameMap();
            String[] charNameMap = encodingB.getCharNameMap();
            for (int i = 0, ci = charNameMap.length; i < ci; i++) {
                String basec = baseNames[i];
                String c = charNameMap[i];
                if (!basec.equals(c)) {
                    if (start != i) {
                        addDifference(i, differences);
                        start = i;
                    }
                    addName(c, differences);
                    start++;
                }
            }
            return differences;
        }

        /**
         * Start a new difference.
         * @param code the starting code index inside the encoding
         * @return this builder instance
         */
        private void addDifference(int code, PDFArray differences) {
            this.currentCode = code;
            differences.add(Integer.valueOf(code));
        }

        /**
         * Adds a character name to the current difference.
         * @param name the character name
         * @return this builder instance
         */
        private void addName(String name, PDFArray differences) {
            if (this.currentCode < 0) {
                throw new IllegalStateException("addDifference(int) must be called first");
            }
            differences.add(new PDFName(name));
        }
    }

    /*
     * example (p. 214)
     * 25 0 obj
     * <<
     * /Type /Encoding
     * /Differences [39 /quotesingle 96 /grave 128
     * /Adieresis /Aring /Ccedilla /Eacute /Ntilde
     * /Odieresis /Udieresis /aacute /agrave]
     * >>
     * endobj
     */
}
