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

import java.awt.Dimension;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.xml.transform.Source;

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

import org.apache.xmlgraphics.io.TempResourceURIGenerator;
import org.apache.xmlgraphics.java2d.Dimension2DDouble;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.PSDictionary;
import org.apache.xmlgraphics.ps.PSDictionaryFormatException;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSPageDeviceDictionary;
import org.apache.xmlgraphics.ps.PSProcSets;
import org.apache.xmlgraphics.ps.PSResource;
import org.apache.xmlgraphics.ps.dsc.DSCException;
import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;

import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;
import org.apache.fop.render.ps.PSRendererConfig.PSRendererConfigParser;
import org.apache.fop.render.ps.extensions.PSCommentAfter;
import org.apache.fop.render.ps.extensions.PSCommentBefore;
import org.apache.fop.render.ps.extensions.PSPageTrailerCodeBefore;
import org.apache.fop.render.ps.extensions.PSSetPageDevice;
import org.apache.fop.render.ps.extensions.PSSetupCode;

/**
 * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation
 * that produces PostScript.
 */
public class PSDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {

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

    /**
     * Utility class which enables all sorts of features that are not directly connected to the
     * normal rendering process.
     */
    private PSRenderingUtil psUtil;

    /** The PostScript generator used to output the PostScript */
    PSGenerator gen;

    /** the temporary file in case of two-pass processing */
    private URI tempURI;
    private static final TempResourceURIGenerator TEMP_URI_GENERATOR
            = new TempResourceURIGenerator("ps-optimize");

    private int currentPageNumber = 0;
    private PageDefinition currentPageDefinition;

    /** Is used to determine the document's bounding box */
    private Rectangle2D documentBoundingBox;

    /** Used to temporarily store PSSetupCode instance until they can be written. */
    private List setupCodeList;

    /** This is a cache of PSResource instances of all fonts defined */
    private FontResourceCache fontResources;
    /** This is a map of PSResource instances of all forms (key: uri) */
    private Map formResources;

    /** encapsulation of dictionary used in setpagedevice instruction **/
    private PSPageDeviceDictionary pageDeviceDictionary;

    /** This is a collection holding all document header comments */
    private Collection[] comments = new Collection[4];
    private static final int COMMENT_DOCUMENT_HEADER = 0;
    private static final int COMMENT_DOCUMENT_TRAILER = 1;
    private static final int COMMENT_PAGE_TRAILER = 2;
    private static final int PAGE_TRAILER_CODE_BEFORE = 3;

    private PSEventProducer eventProducer;

    /**
     * Default constructor.
     */
    public PSDocumentHandler(IFContext context) {
        super(context);
        this.psUtil = new PSRenderingUtil(context.getUserAgent());
    }

    /** {@inheritDoc} */
    public boolean supportsPagesOutOfOrder() {
        return false;
    }

    /** {@inheritDoc} */
    public String getMimeType() {
        return MimeConstants.MIME_POSTSCRIPT;
    }

    PSGenerator getGenerator() {
        return gen;
    }

    /** {@inheritDoc} */
    public IFDocumentHandlerConfigurator getConfigurator() {
        return new PSRendererConfigurator(getUserAgent(), new PSRendererConfigParser());
    }

    PSRenderingUtil getPSUtil() {
        return this.psUtil;
    }

    /** {@inheritDoc} */
    public void startDocument() throws IFException {
        super.startDocument();
        this.fontResources = new FontResourceCache(getFontInfo());
        try {
            final OutputStream out;
            if (psUtil.isOptimizeResources()) {
                tempURI = TEMP_URI_GENERATOR.generate();
                out = new BufferedOutputStream(getUserAgent().getResourceResolver().getOutputStream(tempURI));
            } else {
                out = this.outputStream;
            }

            //Setup for PostScript generation
            this.gen = new PSGenerator(out) {
                /** Need to subclass PSGenerator to have better URI resolution */
                public Source resolveURI(String uri) {
                    return getUserAgent().resolveURI(uri);
                }
            };
            this.gen.setPSLevel(psUtil.getLanguageLevel());
            this.currentPageNumber = 0;
            this.documentBoundingBox = new Rectangle2D.Double();

            //Initial default page device dictionary settings
            this.pageDeviceDictionary = new PSPageDeviceDictionary();
            pageDeviceDictionary.setFlushOnRetrieval(!psUtil.isDSCComplianceEnabled());
            pageDeviceDictionary.put("/ImagingBBox", "null");
        } catch (IOException e) {
            throw new IFException("I/O error in startDocument()", e);
        }
    }

    private void writeHeader() throws IOException {
        //PostScript Header
        gen.writeln(DSCConstants.PS_ADOBE_30);
        gen.writeDSCComment(DSCConstants.CREATOR, new String[] {getUserAgent().getProducer()});
        gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()});
        gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(gen.getPSLevel()));
        gen.writeDSCComment(DSCConstants.PAGES, new Object[] {DSCConstants.ATEND});
        gen.writeDSCComment(DSCConstants.BBOX, DSCConstants.ATEND);
        gen.writeDSCComment(DSCConstants.HIRES_BBOX, DSCConstants.ATEND);
        gen.writeDSCComment(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES,
                new Object[] {DSCConstants.ATEND});
        writeExtensions(COMMENT_DOCUMENT_HEADER);
        gen.writeDSCComment(DSCConstants.END_COMMENTS);

        //Defaults
        gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS);
        gen.writeDSCComment(DSCConstants.END_DEFAULTS);

        //Prolog and Setup written right before the first page-sequence, see startPageSequence()
        //Do this only once, as soon as we have all the content for the Setup section!
        //Prolog
        gen.writeDSCComment(DSCConstants.BEGIN_PROLOG);
        PSProcSets.writeStdProcSet(gen);
        PSProcSets.writeEPSProcSet(gen);
        FOPProcSet.INSTANCE.writeTo(gen);
        gen.writeDSCComment(DSCConstants.END_PROLOG);

        //Setup
        gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
        PSRenderingUtil.writeSetupCodeList(gen, setupCodeList, "SetupCode");
        if (!psUtil.isOptimizeResources()) {
            this.fontResources.addAll(PSFontUtils.writeFontDict(gen, fontInfo, eventProducer));
        } else {
            gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass
        }
        gen.writeDSCComment(DSCConstants.END_SETUP);
    }

    /** {@inheritDoc} */
    public void endDocumentHeader() throws IFException {
        try {
            writeHeader();
        } catch (IOException ioe) {
            throw new IFException("I/O error writing the PostScript header", ioe);
        }
    }

    /** {@inheritDoc} */
    public void endDocument() throws IFException {
        try {
            //Write trailer
            gen.writeDSCComment(DSCConstants.TRAILER);
            writeExtensions(COMMENT_DOCUMENT_TRAILER);
            gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber));
            new DSCCommentBoundingBox(this.documentBoundingBox).generate(gen);
            new DSCCommentHiResBoundingBox(this.documentBoundingBox).generate(gen);
            gen.getResourceTracker().writeResources(false, gen);
            gen.writeDSCComment(DSCConstants.EOF);
            gen.flush();
            log.debug("Rendering to PostScript complete.");
            if (psUtil.isOptimizeResources()) {
                IOUtils.closeQuietly(gen.getOutputStream());
                rewritePostScriptFile();
            }
            if (pageDeviceDictionary != null) {
                pageDeviceDictionary.clear();
            }
        } catch (IOException ioe) {
            throw new IFException("I/O error in endDocument()", ioe);
        }
        super.endDocument();
    }

    /**
     * Used for two-pass production. This will rewrite the PostScript file from the temporary
     * file while adding all needed resources.
     * @throws IOException In case of an I/O error.
     */
    private void rewritePostScriptFile() throws IOException {
        log.debug("Processing PostScript resources...");
        long startTime = System.currentTimeMillis();
        ResourceTracker resTracker = gen.getResourceTracker();
        InputStream in = new BufferedInputStream(getUserAgent().getResourceResolver().getResource(tempURI));
        try {
            try {
                ResourceHandler handler = new ResourceHandler(getUserAgent(), eventProducer,
                        this.fontInfo, resTracker, this.formResources);
                handler.process(in, this.outputStream,
                        this.currentPageNumber, this.documentBoundingBox);
                this.outputStream.flush();
            } catch (DSCException e) {
                throw new RuntimeException(e.getMessage());
            }
        } finally {
            IOUtils.closeQuietly(in);
        }
        if (log.isDebugEnabled()) {
            long duration = System.currentTimeMillis() - startTime;
            log.debug("Resource Processing complete in " + duration + " ms.");
        }
    }

    /** {@inheritDoc} */
    public void startPageSequence(String id) throws IFException {
        //nop
    }

    /** {@inheritDoc} */
    public void endPageSequence() throws IFException {
        //nop
    }

    /** {@inheritDoc} */
    public void startPage(int index, String name, String pageMasterName, Dimension size)
                throws IFException {
        try {
            if (this.currentPageNumber == 0) {
                //writeHeader();
            }

            this.currentPageNumber++;

            gen.getResourceTracker().notifyStartNewPage();
            gen.getResourceTracker().notifyResourceUsageOnPage(PSProcSets.STD_PROCSET);
            gen.writeDSCComment(DSCConstants.PAGE, new Object[]
                    {name,
                     new Integer(this.currentPageNumber)});

            double pageWidth = size.width / 1000.0;
            double pageHeight = size.height / 1000.0;
            boolean rotate = false;
            List pageSizes = new java.util.ArrayList();
            if (this.psUtil.isAutoRotateLandscape() && (pageHeight < pageWidth)) {
                rotate = true;
                pageSizes.add(new Long(Math.round(pageHeight)));
                pageSizes.add(new Long(Math.round(pageWidth)));
            } else {
                pageSizes.add(new Long(Math.round(pageWidth)));
                pageSizes.add(new Long(Math.round(pageHeight)));
            }
            pageDeviceDictionary.put("/PageSize", pageSizes);
            this.currentPageDefinition = new PageDefinition(
                    new Dimension2DDouble(pageWidth, pageHeight), rotate);

            //TODO Handle extension attachments for the page!!!!!!!
            /*
            if (page.hasExtensionAttachments()) {
                for (Iterator iter = page.getExtensionAttachments().iterator();
                    iter.hasNext();) {
                    ExtensionAttachment attachment = (ExtensionAttachment) iter.next();
                    if (attachment instanceof PSSetPageDevice) {*/
                        /**
                         * Extract all PSSetPageDevice instances from the
                         * attachment list on the s-p-m and add all
                         * dictionary entries to our internal representation
                         * of the the page device dictionary.
                         *//*
                        PSSetPageDevice setPageDevice = (PSSetPageDevice)attachment;
                        String content = setPageDevice.getContent();
                        if (content != null) {
                            try {
                                pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
                            } catch (PSDictionaryFormatException e) {
                                PSEventProducer eventProducer = PSEventProducer.Provider.get(
                                        getUserAgent().getEventBroadcaster());
                                eventProducer.postscriptDictionaryParseError(this, content, e);
                            }
                        }
                    }
                }
            }*/

            final Integer zero = new Integer(0);
            Rectangle2D pageBoundingBox = new Rectangle2D.Double();
            if (rotate) {
                pageBoundingBox.setRect(0, 0, pageHeight, pageWidth);
                gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
                        zero, zero, new Long(Math.round(pageHeight)),
                        new Long(Math.round(pageWidth)) });
                gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
                        zero, zero, new Double(pageHeight),
                        new Double(pageWidth) });
                gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
            } else {
                pageBoundingBox.setRect(0, 0, pageWidth, pageHeight);
                gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
                        zero, zero, new Long(Math.round(pageWidth)),
                        new Long(Math.round(pageHeight)) });
                gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
                        zero, zero, new Double(pageWidth),
                        new Double(pageHeight) });
                if (psUtil.isAutoRotateLandscape()) {
                    gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION,
                            "Portrait");
                }
            }
            this.documentBoundingBox.add(pageBoundingBox);
            gen.writeDSCComment(DSCConstants.PAGE_RESOURCES,
                    new Object[] {DSCConstants.ATEND});

            gen.commentln("%FOPSimplePageMaster: " + pageMasterName);
        } catch (IOException ioe) {
            throw new IFException("I/O error in startPage()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void startPageHeader() throws IFException {
        super.startPageHeader();

        try {
            gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);
        } catch (IOException ioe) {
            throw new IFException("I/O error in startPageHeader()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void endPageHeader() throws IFException {
        try {
            // Write any unwritten changes to page device dictionary
            if (!pageDeviceDictionary.isEmpty()) {
                String content = pageDeviceDictionary.getContent();
                if (psUtil.isSafeSetPageDevice()) {
                    content += " SSPD";
                } else {
                    content += " setpagedevice";
                }
                PSRenderingUtil.writeEnclosedExtensionAttachment(gen, new PSSetPageDevice(content));
            }

            double pageHeight = this.currentPageDefinition.dimensions.getHeight();
            if (this.currentPageDefinition.rotate) {
                gen.writeln(gen.formatDouble(pageHeight) + " 0 translate");
                gen.writeln("90 rotate");
            }
            gen.concatMatrix(1, 0, 0, -1, 0, pageHeight);

            gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
        } catch (IOException ioe) {
            throw new IFException("I/O error in endPageHeader()", ioe);
        }

        super.endPageHeader();
    }

    private void writeExtensions(int which) throws IOException {
        Collection extensions = comments[which];
        if (extensions != null) {
            PSRenderingUtil.writeEnclosedExtensionAttachments(gen, extensions);
            extensions.clear();
        }
    }

    /** {@inheritDoc} */
    public IFPainter startPageContent() throws IFException {
        return new PSPainter(this);
    }

    /** {@inheritDoc} */
    public void endPageContent() throws IFException {
        try {
            gen.showPage();
        } catch (IOException ioe) {
            throw new IFException("I/O error in endPageContent()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void startPageTrailer() throws IFException {
        try {
            writeExtensions(PAGE_TRAILER_CODE_BEFORE);
            super.startPageTrailer();
            gen.writeDSCComment(DSCConstants.PAGE_TRAILER);
        } catch (IOException ioe) {
            throw new IFException("I/O error in startPageTrailer()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void endPageTrailer() throws IFException {
        try {
            writeExtensions(COMMENT_PAGE_TRAILER);
        } catch (IOException ioe) {
            throw new IFException("I/O error in endPageTrailer()", ioe);
        }
        super.endPageTrailer();
    }

    /** {@inheritDoc} */
    public void endPage() throws IFException {
        try {
            gen.getResourceTracker().writeResources(true, gen);
        } catch (IOException ioe) {
            throw new IFException("I/O error in endPage()", ioe);
        }

        this.currentPageDefinition = null;
    }

    private boolean inPage() {
        return this.currentPageDefinition != null;
    }

    /** {@inheritDoc} */
    public void handleExtensionObject(Object extension) throws IFException {
        try {
            if (extension instanceof PSSetupCode) {
                if (inPage()) {
                    PSRenderingUtil.writeEnclosedExtensionAttachment(gen, (PSSetupCode)extension);
                } else {
                    //A special collection for setup code as it's put in a different place
                    //than the "before comments".
                    if (setupCodeList == null) {
                        setupCodeList = new java.util.ArrayList();
                    }
                    if (!setupCodeList.contains(extension)) {
                        setupCodeList.add(extension);
                    }
                }
            } else if (extension instanceof PSSetPageDevice) {
                /**
                 * Extract all PSSetPageDevice instances from the
                 * attachment list on the s-p-m and add all dictionary
                 * entries to our internal representation of the the
                 * page device dictionary.
                 */
                PSSetPageDevice setPageDevice = (PSSetPageDevice)extension;
                String content = setPageDevice.getContent();
                if (content != null) {
                    try {
                        this.pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
                    } catch (PSDictionaryFormatException e) {
                        PSEventProducer eventProducer = PSEventProducer.Provider.get(
                                getUserAgent().getEventBroadcaster());
                        eventProducer.postscriptDictionaryParseError(this, content, e);
                    }
                }
            } else if (extension instanceof PSCommentBefore) {
                if (inPage()) {
                    PSRenderingUtil.writeEnclosedExtensionAttachment(
                            gen, (PSCommentBefore)extension);
                } else {
                    if (comments[COMMENT_DOCUMENT_HEADER] == null) {
                        comments[COMMENT_DOCUMENT_HEADER] = new java.util.ArrayList();
                    }
                    comments[COMMENT_DOCUMENT_HEADER].add(extension);
                }
            } else if (extension instanceof PSCommentAfter) {
                int targetCollection = (inPage() ? COMMENT_PAGE_TRAILER : COMMENT_DOCUMENT_TRAILER);
                if (comments[targetCollection] == null) {
                    comments[targetCollection] = new java.util.ArrayList();
                }
                comments[targetCollection].add(extension);
            } else if (extension instanceof PSPageTrailerCodeBefore) {
                if (comments[PAGE_TRAILER_CODE_BEFORE] == null) {
                    comments[PAGE_TRAILER_CODE_BEFORE] = new ArrayList();
                }
                comments[PAGE_TRAILER_CODE_BEFORE].add(extension);
            }
        } catch (IOException ioe) {
            throw new IFException("I/O error in handleExtensionObject()", ioe);
        }
    }

    /**
     * Returns the PSResource for the given font key.
     * @param key the font key ("F*")
     * @return the matching PSResource
     */
    protected PSFontResource getPSResourceForFontKey(String key) {
        return this.fontResources.getFontResourceForFontKey(key);
    }

    /**
     * Returns a PSResource instance representing a image as a PostScript form.
     * @param uri the image URI
     * @return a PSResource instance
     */
    protected PSResource getFormForImage(String uri) {
        if (uri == null || "".equals(uri)) {
            throw new IllegalArgumentException("uri must not be empty or null");
        }
        if (this.formResources == null) {
            this.formResources = new java.util.HashMap();
        }
        PSResource form = (PSResource)this.formResources.get(uri);
        if (form == null) {
            form = new PSImageFormResource(this.formResources.size() + 1, uri);
            this.formResources.put(uri, form);
        }
        return form;
    }

    private static final class PageDefinition {
        private Dimension2D dimensions;
        private boolean rotate;

        private PageDefinition(Dimension2D dimensions, boolean rotate) {
            this.dimensions = dimensions;
            this.rotate = rotate;
        }
    }

}
