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

import java.io.IOException;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil;

import org.apache.fop.fonts.FontDescriptor;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.fonts.base14.Symbol;
import org.apache.fop.fonts.base14.ZapfDingbats;

/**
 * Class representing a /Resources object.
 *
 * /Resources object contain a list of references to the fonts, patterns,
 * shadings, etc.,  for the document.
 */
public class PDFResources extends PDFDictionary {

    /**
     * /Font objects keyed by their internal name
     */
    protected Map<String, PDFDictionary> fonts = new LinkedHashMap<String, PDFDictionary>();

    /**
     * Set of XObjects
     */
    protected Set<PDFXObject> xObjects = new LinkedHashSet<PDFXObject>();
    /** Map of color spaces (key: color space name) */
    protected Map<LazyName, PDFColorSpace> colorSpaces = new LinkedHashMap<LazyName, PDFColorSpace>();

    /** Map of ICC color spaces (key: ICC profile description) */
    protected Map<String, PDFICCBasedColorSpace> iccColorSpaces = new LinkedHashMap<String, PDFICCBasedColorSpace>();

    private PDFResources parent;
    private PDFDictionary fontsObj;
    private Map<String, PDFDictionary> fontsObjDict = new LinkedHashMap<String, PDFDictionary>();

    /** Named properties */
    protected Map<String, PDFReference> properties = new LinkedHashMap<String, PDFReference>();

    protected Set<PDFResourceContext> contexts = new LinkedHashSet<PDFResourceContext>();

    /**
     * create a /Resources object.
     */
    public PDFResources(PDFDocument doc) {
        /* generic creation of object */
        super();
        setObjectNumber(doc);
    }

    public void addContext(PDFResourceContext c) {
        contexts.add(c);
    }

    public void setParentResources(PDFResources p) {
        parent = p;
    }

    public PDFResources getParentResources() {
        return parent;
    }

    /**
     * add font object to resources list.
     *
     * @param font the PDFFont to add
     */
    public void addFont(PDFFont font) {
        addFont(font.getName(), font);
    }

    public void addFont(String name, PDFDictionary font) {
        if (fontsObj != null) {
            fontsObj.put(name, font);
            fontsObjDict.put(name, font);
        } else {
            fonts.put(name, font);
        }
    }

    public void createFontsAsObj() {
        fontsObj = new PDFDictionary();
        getDocument().registerTrailerObject(fontsObj);
        put("Font", fontsObj);
    }

    /**
     * Add the fonts in the font info to this PDF document's Font Resources.
     *
     * @param doc PDF document to add fonts to
     * @param fontInfo font info object to get font information from
     */
   public void addFonts(PDFDocument doc, FontInfo fontInfo) {
        Map<String, Typeface> usedFonts = fontInfo.getUsedFonts();
        for (Map.Entry<String, Typeface> e : usedFonts.entrySet()) {
            String f = e.getKey();
            Typeface font = e.getValue();

            //Check if the font actually had any mapping operations. If not, it is an indication
            //that it has never actually been used and therefore doesn't have to be embedded.
            if (font.hadMappingOperations()) {
                FontDescriptor desc = null;
                if (font instanceof FontDescriptor) {
                    desc = (FontDescriptor)font;
                }
                String encoding = font.getEncodingName();
                if (font instanceof Symbol || font instanceof ZapfDingbats) {
                    encoding = null; //Symbolic fonts shouldn't specify an encoding value in PDF
                }
                addFont(doc.getFactory().makeFont(
                    f, font.getEmbedFontName(), encoding, font, desc));
            }
        }
   }

    /**
     * Add an XObject to the resources.
     *
     * @param xObject the XObject to add
     */
    public void addXObject(PDFXObject xObject) {
        this.xObjects.add(xObject);
    }

    /**
     * Add a ColorSpace dictionary to the resources.
     * @param colorSpace the color space
     */
    public void addColorSpace(PDFColorSpace colorSpace) {
        this.colorSpaces.put(new LazyName(colorSpace), colorSpace);
        if (colorSpace instanceof PDFICCBasedColorSpace) {
            PDFICCBasedColorSpace icc = (PDFICCBasedColorSpace)colorSpace;
            String desc = ColorProfileUtil.getICCProfileDescription(
                    icc.getICCStream().getICCProfile());
            this.iccColorSpaces.put(desc, icc);
        }
    }

    static class LazyName {
        private PDFColorSpace colorSpace;
        public LazyName(PDFColorSpace colorSpace) {
            this.colorSpace = colorSpace;
        }
        public PDFName getName() {
            return new PDFName(colorSpace.getName());
        }
    }

    /**
     * Returns a ICCBased color space by profile name.
     * @param desc the name of the color space
     * @return the requested color space or null if it wasn't found
     */
    public PDFICCBasedColorSpace getICCColorSpaceByProfileName(String desc) {
        PDFICCBasedColorSpace cs = this.iccColorSpaces.get(desc);
        return cs;
    }

    /**
     * Returns a color space by name.
     * @param name the name of the color space
     * @return the requested color space or null if it wasn't found
     */
    public PDFColorSpace getColorSpace(PDFName name) {
        for (Map.Entry<LazyName, PDFColorSpace> x : colorSpaces.entrySet()) {
            if (x.getKey().getName().equals(name)) {
                return x.getValue();
            }
        }
        return null;
    }

    /**
     * Add a named property.
     *
     * @param name name of property
     * @param property reference to property value
     */
    public void addProperty(String name, PDFReference property) {
        this.properties.put(name, property);
    }

    /**
     * Get a named property.
     *
     * @param name name of property
     */
    public PDFReference getProperty(String name) {
        return this.properties.get(name);
    }

    @Override
    public int output(OutputStream stream) throws IOException {
        populateDictionary();
        return super.output(stream);
    }

    private void populateDictionary() {
        if (parent != null && parent.fontsObj != null) {
            put("Font", parent.fontsObj);
        }
        if (!this.fonts.isEmpty() || (parent != null && !parent.fonts.isEmpty())) {
            PDFDictionary dict = new PDFDictionary(this);
            /* construct PDF dictionary of font object references */
            for (Map.Entry<String, PDFDictionary> entry : fonts.entrySet()) {
                dict.put(entry.getKey(), entry.getValue());
            }
            if (parent != null) {
                for (Map.Entry<String, PDFDictionary> entry : parent.fonts.entrySet()) {
                    dict.put(entry.getKey(), entry.getValue());
                }
                for (Map.Entry<String, PDFDictionary> entry : parent.fontsObjDict.entrySet()) {
                    dict.put(entry.getKey(), entry.getValue());
                }
            }
            put("Font", dict);
        }

        Set<PDFPattern> patterns = new LinkedHashSet<PDFPattern>();
        Set<PDFShading> shadings = new LinkedHashSet<PDFShading>();
        Set<PDFGState> gstates = new LinkedHashSet<PDFGState>();
        for (PDFResourceContext c : contexts) {
            xObjects.addAll(c.getXObjects());
            patterns.addAll(c.getPatterns());
            shadings.addAll(c.getShadings());
            gstates.addAll(c.getGStates());
        }
        if (parent != null) {
            xObjects.addAll(parent.xObjects);
            for (PDFResourceContext c : parent.contexts) {
                patterns.addAll(c.getPatterns());
                shadings.addAll(c.getShadings());
                gstates.addAll(c.getGStates());
            }
        }

        if (!shadings.isEmpty()) {
            PDFDictionary dict = (PDFDictionary) get("Shading");
            if (dict == null) {
                dict = new PDFDictionary(this);
            }
            for (PDFShading shading : shadings) {
                dict.put(shading.getName(), shading);
            }
            put("Shading", dict);
        }

        if (!patterns.isEmpty()) {
            PDFDictionary dict = (PDFDictionary) get("Pattern");
            if (dict == null) {
                dict = new PDFDictionary(this);
            }
            for (PDFPattern pattern : patterns) {
                dict.put(pattern.getName(), pattern);
            }
            put("Pattern", dict);
        }

        PDFArray procset = new PDFArray(this);
        procset.add(new PDFName("PDF"));
        procset.add(new PDFName("ImageB"));
        procset.add(new PDFName("ImageC"));
        procset.add(new PDFName("Text"));
        put("ProcSet", procset);

        if (!xObjects.isEmpty()) {
            PDFDictionary dict = (PDFDictionary) get("XObject");
            if (dict == null) {
                dict = new PDFDictionary(this);
            }
            for (PDFXObject xObject : xObjects) {
                dict.put(xObject.getName().toString(), xObject);
            }
            put("XObject", dict);
        }

        if (!gstates.isEmpty()) {
            PDFDictionary dict = (PDFDictionary) get("ExtGState");
            if (dict == null) {
                dict = new PDFDictionary(this);
            }
            for (PDFGState gstate : gstates) {
                dict.put(gstate.getName(), gstate);
            }
            put("ExtGState", dict);
        }

        if (!this.colorSpaces.isEmpty() || (parent != null && !parent.colorSpaces.isEmpty())) {
            PDFDictionary dict = (PDFDictionary)this.get("ColorSpace");
            if (dict == null) {
                dict = new PDFDictionary(this);
            }
            if (parent != null) {
                for (PDFColorSpace colorSpace : parent.colorSpaces.values()) {
                    dict.put(colorSpace.getName(), colorSpace);
                }
            }
            for (PDFColorSpace colorSpace : colorSpaces.values()) {
                dict.put(colorSpace.getName(), colorSpace);
            }
            put("ColorSpace", dict);
        }

        if (!properties.isEmpty()) {
            PDFDictionary dict = new PDFDictionary(this);
            for (Map.Entry<String, PDFReference> stringPDFReferenceEntry : properties.entrySet()) {
                dict.put(stringPDFReferenceEntry.getKey(), stringPDFReferenceEntry.getValue());
            }
            put("Properties", dict);
        }
    }

    @Override
    public void getChildren(Set<PDFObject> children) {
        getChildren(children, false);
    }

    private void getChildren(Set<PDFObject> children, boolean isParent) {
        super.getChildren(children);
        for (PDFDictionary f : fonts.values()) {
            children.add(f);
            f.getChildren(children);
        }
        for (PDFResourceContext c : contexts) {
            for (PDFXObject x : c.getXObjects()) {
                children.add(x);
                x.getChildren(children);
            }
            for (PDFPattern x : c.getPatterns()) {
                children.add(x);
                x.getChildren(children);
            }
            for (PDFShading x : c.getShadings()) {
                children.add(x);
                x.getChildren(children);
            }
            for (PDFGState x : c.getGStates()) {
                children.add(x);
                x.getChildren(children);
            }
        }
        if (!isParent) {
            for (PDFColorSpace x : colorSpaces.values()) {
                children.add((PDFObject)x);
                ((PDFObject)x).getChildren(children);
            }
        }
        if (parent != null) {
            parent.getChildren(children, true);
        }
    }
}
