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

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.afp.AFPResourceLevel.ResourceType;
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.modca.AbstractNamedAFPObject;
import org.apache.fop.afp.modca.AbstractPageObject;
import org.apache.fop.afp.modca.ActiveEnvironmentGroup;
import org.apache.fop.afp.modca.IncludeObject;
import org.apache.fop.afp.modca.IncludedResourceObject;
import org.apache.fop.afp.modca.ObjectContainer;
import org.apache.fop.afp.modca.PageSegment;
import org.apache.fop.afp.modca.Registry;
import org.apache.fop.afp.modca.ResourceGroup;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.modca.triplets.EncodingTriplet;
import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet;
import org.apache.fop.afp.util.AFPResourceAccessor;
import org.apache.fop.afp.util.AFPResourceUtil;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.fonts.FontType;
import org.apache.fop.render.afp.AFPFontConfig;

/**
 * Manages the creation and storage of document resources
 */
public class AFPResourceManager {

    /** logging instance */
    private static Log log = LogFactory.getLog(AFPResourceManager.class);

    /** The AFP datastream (document tree) */
    private DataStream dataStream;

    /** Resource creation factory */
    private final Factory factory;

    private final AFPStreamer streamer;

    private final AFPDataObjectFactory dataObjectFactory;

    /** Maintain a reference count of instream objects for referencing purposes */
    private int instreamObjectCount;

    /** Mapping of resourceInfo to AbstractCachedObject */
    private final Map<AFPResourceInfo, List<AbstractCachedObject>> includeObjectCache =
            new HashMap<AFPResourceInfo, List<AbstractCachedObject>>();

    private AFPResourceLevelDefaults resourceLevelDefaults = new AFPResourceLevelDefaults();

    protected boolean includeCached = true;

    /**
     * Main constructor
     *
     * @param resourceResolver  the associated {@link InternalResourceResolver} instance
     */
    public AFPResourceManager(InternalResourceResolver resourceResolver) {
        this.factory = new Factory();
        this.streamer = new AFPStreamer(factory, resourceResolver);
        this.dataObjectFactory = new AFPDataObjectFactory(factory);
    }

    /**
     * Sets the outputstream
     *
     * @param paintingState the AFP painting state
     * @param outputStream the outputstream
     * @return a new AFP DataStream
     * @throws IOException thrown if an I/O exception of some sort has occurred
     */
    public DataStream createDataStream(AFPPaintingState paintingState, OutputStream outputStream)
    throws IOException {
        this.dataStream = streamer.createDataStream(paintingState);
        streamer.setOutputStream(outputStream);
        return this.dataStream;
    }

    /**
     * Returns the AFP DataStream
     *
     * @return the AFP DataStream
     */
    public DataStream getDataStream() {
        return this.dataStream;
    }

    /**
     * Tells the streamer to write
     *
     * @throws IOException thrown if an I/O exception of some sort has occurred.
     */
    public void writeToStream() throws IOException {
        streamer.close();
    }

    /**
     * Sets the default resource group URI.
     *
     * @param uri the default resource group URI
     */

    public void setDefaultResourceGroupUri(URI uri) {
        streamer.setDefaultResourceGroupUri(uri);
    }

    /**
     * Tries to create an include of a data object that has been previously added to the
     * AFP data stream. If no such object was available, the method returns false which serves
     * as a signal that the object has to be created.
     * @param dataObjectInfo the data object info
     * @return true if the inclusion succeeded, false if the object was not available
     * @throws IOException thrown if an I/O exception of some sort has occurred.
     */
    public boolean tryIncludeObject(AFPDataObjectInfo dataObjectInfo) throws IOException {
        AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
        updateResourceInfoUri(resourceInfo);
        return includeCachedObject(resourceInfo, dataObjectInfo.getObjectAreaInfo());
    }

    /**
     * Creates a new data object in the AFP datastream
     *
     * @param dataObjectInfo the data object info
     *
     * @throws IOException thrown if an I/O exception of some sort has occurred.
     */
    public void createObject(AFPDataObjectInfo dataObjectInfo) throws IOException {
        if (tryIncludeObject(dataObjectInfo)) {
            //Object has already been produced and is available by inclusion, so return early.
            return;
        }

        AbstractNamedAFPObject namedObj = null;
        AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();

        boolean useInclude = true;
        Registry.ObjectType objectType = null;

        // new resource so create
        if (dataObjectInfo instanceof AFPImageObjectInfo) {
            AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo;
            namedObj = dataObjectFactory.createImage(imageObjectInfo);
        } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
            AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo)dataObjectInfo;
            namedObj = dataObjectFactory.createGraphic(graphicsObjectInfo);
        } else {
            // natively embedded data object
            namedObj = dataObjectFactory.createObjectContainer(dataObjectInfo);
            objectType = dataObjectInfo.getObjectType();
            useInclude = objectType != null && objectType.isIncludable();
        }

        AFPResourceLevel resourceLevel = resourceInfo.getLevel();
        ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);

        useInclude &= resourceGroup != null;
        if (useInclude) {
            final boolean usePageSegment = dataObjectInfo.isCreatePageSegment();

            // if it is to reside within a resource group at print-file or external level
            if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) {
                if (usePageSegment) {
                    String pageSegmentName = "S10" + namedObj.getName().substring(3);
                    namedObj.setName(pageSegmentName);
                    PageSegment seg = new PageSegment(pageSegmentName);
                    seg.addObject(namedObj);
                    namedObj = seg;
                }

                // wrap newly created data object in a resource object
                namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType);
            }

            // add data object into its resource group destination
            resourceGroup.addObject(namedObj);
            includeObject(namedObj, dataObjectInfo);
        } else {
            // not to be included so inline data object directly into the current page
            dataStream.getCurrentPage().addObject(namedObj);
        }
    }

    private abstract class AbstractCachedObject {
        protected String objectName;
        protected AFPDataObjectInfo dataObjectInfo;

        public AbstractCachedObject(String objectName, AFPDataObjectInfo dataObjectInfo) {
            this.objectName = objectName;
            this.dataObjectInfo = dataObjectInfo;


        }
        protected abstract void includeObject();
    }

    private class CachedPageSegment extends AbstractCachedObject {

        public CachedPageSegment(String objectName, AFPDataObjectInfo dataObjectInfo) {
           super(objectName, dataObjectInfo);
        }

        protected void includeObject() {
            includePageSegment(dataObjectInfo, objectName);
        }

    }

    private class CachedObject extends AbstractCachedObject {

        public CachedObject(String objectName, AFPDataObjectInfo dataObjectInfo) {
           super(objectName, dataObjectInfo);
        }

        protected void includeObject() {
            AFPResourceManager.this.includeObject(dataObjectInfo, objectName);
        }

    }


    private void includeObject(AbstractNamedAFPObject namedObj, AFPDataObjectInfo dataObjectInfo) {

        // create the include object
        String objectName = namedObj.getName();

        AbstractCachedObject cachedObject;

        if (dataObjectInfo.isCreatePageSegment()) {
            cachedObject = new CachedPageSegment(objectName, dataObjectInfo);
        } else {
            cachedObject = new CachedObject(objectName, dataObjectInfo);
        }

        cachedObject.includeObject();

        addToCache(dataObjectInfo.getResourceInfo(), cachedObject);

        //The data field of dataObjectInfo is not further required
        // therefore we are safe to null the reference, saving memory
        dataObjectInfo.setData(null);

    }

    private void addToCache(AFPResourceInfo resourceInfo, AbstractCachedObject cachedObject) {
        List<AbstractCachedObject> objs = includeObjectCache.get(resourceInfo);
        if (objs == null) {
            objs = new ArrayList<AbstractCachedObject>();
            includeObjectCache.put(resourceInfo, objs);
        }
        objs.add(cachedObject);
    }

    /**
     * Returns {@code true} if the passed {@link AFPResourceInfo} instance is already cached.
     *
     * @param resourceInfo  the resource info to check
     * @return  {@code true} if the object is cached
     */
    public boolean isObjectCached(AFPResourceInfo resourceInfo) {
        return includeObjectCache.containsKey(resourceInfo);
    }

    /**
     *
     * @param resourceInfo  the resource info to check
     * @param areaInfo  the area info to check
     * @return  {@code true} if ...
     */
    public boolean includeCachedObject(AFPResourceInfo resourceInfo, AFPObjectAreaInfo areaInfo) {
        List<AbstractCachedObject> cachedObjectList = includeObjectCache.get(resourceInfo);
        if (cachedObjectList != null && includeCached) {
            for (AbstractCachedObject cachedObject : cachedObjectList) {
                if (areaInfo != null && cachedObjectList.size() == 1) {
                    cachedObject.dataObjectInfo.setObjectAreaInfo(areaInfo);
                }
                cachedObject.includeObject();
            }
            return true;
        } else {
            return false;
        }
    }


    private void updateResourceInfoUri(AFPResourceInfo resourceInfo) {
        String uri = resourceInfo.getUri();
        if (uri == null) {
            uri = "/";
        }
        // if this is an instream data object adjust the uri to ensure that its unique
        if (uri.endsWith("/")) {
            uri += "#" + (++instreamObjectCount);
            resourceInfo.setUri(uri);
        }
    }

    private void includeObject(AFPDataObjectInfo dataObjectInfo,
            String objectName) {
        IncludeObject includeObject = dataObjectFactory.createInclude(objectName, dataObjectInfo);
        dataStream.getCurrentPage().addObject(includeObject);
    }

    /**
     * Handles font embedding. If a font is embeddable and has not already been embedded it will be.
     * @param afpFont the AFP font to be checked for embedding
     * @param charSet the associated character set
     * @throws IOException if there's a problem while embedding the external resources
     */
    public void embedFont(AFPFont afpFont, CharacterSet charSet)
            throws IOException {
        if (afpFont.isEmbeddable()) {
            //Embed fonts (char sets and code pages)
            if (charSet.getResourceAccessor() != null) {
                AFPResourceAccessor accessor = charSet.getResourceAccessor();
                if (afpFont.getFontType() == FontType.TRUETYPE) {

                    createIncludedResource(afpFont.getFontName(),
                            ((AFPFontConfig.AFPTrueTypeFont) afpFont).getUri(), accessor,
                            ResourceObject.TYPE_OBJECT_CONTAINER, true,
                            ((AFPFontConfig.AFPTrueTypeFont) afpFont).getTTC());
                } else {
                    createIncludedResource(
                            charSet.getName(), accessor,
                            ResourceObject.TYPE_FONT_CHARACTER_SET);
                    createIncludedResource(
                            charSet.getCodePage(), accessor,
                            ResourceObject.TYPE_CODE_PAGE);
                }
            }
        }
    }

    private void includePageSegment(AFPDataObjectInfo dataObjectInfo,
            String pageSegmentName) {
        int x = dataObjectInfo.getObjectAreaInfo().getX();
        int y = dataObjectInfo.getObjectAreaInfo().getY();
        AbstractPageObject currentPage = dataStream.getCurrentPage();
        boolean createHardPageSegments = true;
        currentPage.createIncludePageSegment(pageSegmentName, x, y, createHardPageSegments);
    }

    /**
     * Creates an included resource object by loading the contained object from a file.
     * @param resourceName the name of the resource
     * @param accessor resource accessor to access the resource with
     * @param resourceObjectType the resource object type ({@link ResourceObject}.*)
     * @throws IOException if an I/O error occurs while loading the resource
     */
    public void createIncludedResource(String resourceName, AFPResourceAccessor accessor,
                byte resourceObjectType) throws IOException {
        URI uri;
        try {
            uri = new URI(resourceName.trim());
        } catch (URISyntaxException e) {
            throw new IOException("Could not create URI from resource name: " + resourceName
                    + " (" + e.getMessage() + ")");
        }

        createIncludedResource(resourceName, uri, accessor, resourceObjectType, false, null);
    }

    /**
     * Creates an included resource object by loading the contained object from a file.
     * @param resourceName the name of the resource
     * @param uri the URI for the resource
     * @param accessor resource accessor to access the resource with
     * @param resourceObjectType the resource object type ({@link ResourceObject}.*)
     * @throws IOException if an I/O error occurs while loading the resource
     */
    public void createIncludedResource(String resourceName, URI uri, AFPResourceAccessor accessor,
                                       byte resourceObjectType, boolean truetype, String ttc) throws IOException {
        AFPResourceLevel resourceLevel = new AFPResourceLevel(ResourceType.PRINT_FILE);

        AFPResourceInfo resourceInfo = new AFPResourceInfo();
        resourceInfo.setLevel(resourceLevel);
        resourceInfo.setName(resourceName);
        resourceInfo.setUri(uri.toASCIIString());

        List<AbstractCachedObject> cachedObject = includeObjectCache.get(resourceInfo);
        if (cachedObject == null) {
            if (log.isDebugEnabled()) {
                log.debug("Adding included resource: " + resourceName);
            }

            ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);

            if (truetype) {
                ResourceObject res = factory.createResource();
                res.setType(ResourceObject.TYPE_OBJECT_CONTAINER);

                ActiveEnvironmentGroup.setupTruetypeMDR(res, false);

                ObjectContainer oc = factory.createObjectContainer();
                InputStream is = accessor.createInputStream(uri);

                if (ttc != null) {
                    oc.setData(extractTTC(ttc, is));
                } else {
                    oc.setData(IOUtils.toByteArray(is));
                }

                ActiveEnvironmentGroup.setupTruetypeMDR(oc, true);

                res.addTriplet(new EncodingTriplet(1200));

                res.setFullyQualifiedName(FullyQualifiedNameTriplet.TYPE_REPLACE_FIRST_GID_NAME,
                        FullyQualifiedNameTriplet.FORMAT_CHARSTR, resourceName, true);

                res.setDataObject(oc);
                resourceGroup.addObject(res);
            } else {
                ResourceObject resourceObject = factory.createResource(resourceName);
                IncludedResourceObject resourceContent = new IncludedResourceObject(
                        resourceName, accessor, uri);
                resourceObject.setDataObject(resourceContent);
                resourceObject.setType(resourceObjectType);
                resourceGroup.addObject(resourceObject);
            }

            //TODO what is the data object?
            CachedObject newcachedObject = new CachedObject(resourceName, null);

            // record mapping of resource info to data object resource name
            addToCache(resourceInfo, newcachedObject);
        } else {
            //skip, already created
        }
    }

    private byte[] extractTTC(String ttc, InputStream is) throws IOException {
//        TrueTypeCollection trueTypeCollection = new TrueTypeCollection(is);
//        for (TrueTypeFont ttf : trueTypeCollection.getFonts()) {
//            String name = ttf.getNaming().getFontFamily();
//            if (name.equals(ttc)) {
//                ByteArrayOutputStream bos = new ByteArrayOutputStream();
//                TTFSubsetter s = new TTFSubsetter(ttf, null);
//                for (int i = 0; i < 256 * 256; i++) {
//                    s.addCharCode(i);
//                }
//                s.writeToStream(bos);
//                return bos.toByteArray();
//            }
//        }
        throw new IOException(ttc + " not supported");
    }

    /**
     * Creates an included resource extracting the named resource from an external source.
     * @param resourceName the name of the resource
     * @param uri the URI for the resource
     * @param accessor resource accessor to access the resource with
     * @throws IOException if an I/O error occurs while loading the resource
     */
    public void createIncludedResourceFromExternal(final String resourceName,
            final URI uri, final AFPResourceAccessor accessor) throws IOException {

        AFPResourceLevel resourceLevel = new AFPResourceLevel(ResourceType.PRINT_FILE);

        AFPResourceInfo resourceInfo = new AFPResourceInfo();
        resourceInfo.setLevel(resourceLevel);
        resourceInfo.setName(resourceName);
        resourceInfo.setUri(uri.toASCIIString());

        List<AbstractCachedObject> resource = includeObjectCache.get(resourceInfo);
        if (resource == null) {
            ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);

            //resourceObject delegates write commands to copyNamedResource()
            //The included resource may already be wrapped in a resource object
            AbstractNamedAFPObject resourceObject = new AbstractNamedAFPObject(null) {

                @Override
                protected void writeContent(OutputStream os) throws IOException {
                    InputStream inputStream = null;
                    try {
                        inputStream = accessor.createInputStream(uri);
                        BufferedInputStream bin = new BufferedInputStream(inputStream);
                        AFPResourceUtil.copyNamedResource(resourceName, bin, os);
                    } finally {
                        IOUtils.closeQuietly(inputStream);
                    }
                }

                //bypass super.writeStart
                @Override
                protected void writeStart(OutputStream os) throws IOException { }
                //bypass super.writeEnd
                @Override
                protected void writeEnd(OutputStream os) throws IOException { }
            };
            resourceGroup.addObject(resourceObject);
            CachedObject newresource = new CachedObject(resourceName, null);
            addToCache(resourceInfo, newresource);
        }
    }


    /**
     * Sets resource level defaults. The existing defaults over merged with the ones passed in
     * as parameter.
     * @param defaults the new defaults
     */
    public void setResourceLevelDefaults(AFPResourceLevelDefaults defaults) {
        this.resourceLevelDefaults.mergeFrom(defaults);
    }

    /**
     * Returns the resource level defaults in use with this resource manager.
     * @return the resource level defaults
     */
    public AFPResourceLevelDefaults getResourceLevelDefaults() {
        return this.resourceLevelDefaults;
    }

}
