/*
 * 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.Date;
import java.util.UUID;

import javax.xml.transform.TransformerConfigurationException;

import org.xml.sax.SAXException;

import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.xmlgraphics.xmp.XMPSerializer;
import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter;
import org.apache.xmlgraphics.xmp.schemas.DublinCoreSchema;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
import org.apache.xmlgraphics.xmp.schemas.pdf.AdobePDFAdapter;
import org.apache.xmlgraphics.xmp.schemas.pdf.AdobePDFSchema;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFAAdapter;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFAXMPSchema;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFUAAdapter;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFUAXMPSchema;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFVTAdapter;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFVTXMPSchema;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFXAdapter;
import org.apache.xmlgraphics.xmp.schemas.pdf.PDFXXMPSchema;
import org.apache.xmlgraphics.xmp.schemas.pdf.XAPMMAdapter;
import org.apache.xmlgraphics.xmp.schemas.pdf.XAPMMXMPSchema;

/**
 * Special PDFStream for Metadata.
 * @since PDF 1.4
 */
public class PDFMetadata extends PDFStream {

    private Metadata xmpMetadata;
    private boolean readOnly = true;

    /**
     * @param xmp xmp metadata
     * @param readOnly true if read only
     * @see org.apache.fop.pdf.PDFObject#PDFObject()
     */
    public PDFMetadata(Metadata xmp, boolean readOnly) {
        super();
        if (xmp == null) {
            throw new NullPointerException(
                    "The parameter for the XMP Document must not be null");
        }
        this.xmpMetadata = xmp;
        this.readOnly = readOnly;
    }

    /** {@inheritDoc} */
    protected String getDefaultFilterName() {
        return PDFFilterList.METADATA_FILTER;
    }

    /**
     * @return the XMP metadata
     */
    public Metadata getMetadata() {
        return this.xmpMetadata;
    }

    /**
     * overload the base object method so we don't have to copy
     * byte arrays around so much
     * {@inheritDoc}
     */
    public int output(java.io.OutputStream stream)
                throws java.io.IOException {
        int length = super.output(stream);
        this.xmpMetadata = null; //Release DOM when it's not used anymore
        return length;
    }

    /** {@inheritDoc} */
    protected void outputRawStreamData(OutputStream out) throws IOException {
        try {
            XMPSerializer.writeXMPPacket(xmpMetadata, out, this.readOnly);
        } catch (TransformerConfigurationException tce) {
            throw new IOException("Error setting up Transformer for XMP stream serialization: "
                    + tce.getMessage());
        } catch (SAXException saxe) {
            throw new IOException("Error while serializing XMP stream: "
                    + saxe.getMessage());
        }
    }

    /** {@inheritDoc} */
    protected void populateStreamDict(Object lengthEntry) {
        final String filterEntry = getFilterList().buildFilterDictEntries();
        if (getDocumentSafely().getProfile().getPDFAMode().isPart1()
                && filterEntry != null && filterEntry.length() > 0) {
            throw new PDFConformanceException(
                    "The Filter key is prohibited when PDF/A-1 is active");
        }
        put("Type", new PDFName("Metadata"));
        put("Subtype", new PDFName("XML"));
        super.populateStreamDict(lengthEntry);
    }

    /**
     * Creates an XMP document based on the settings on the PDF Document.
     * @param pdfDoc the PDF Document
     * @return the requested XMP metadata
     */
    public static Metadata createXMPFromPDFDocument(PDFDocument pdfDoc) {
        Metadata meta = new Metadata();

        PDFInfo info = pdfDoc.getInfo();
        PDFRoot root = pdfDoc.getRoot();

        //Set creation date if not available, yet
        if (info.getCreationDate() == null) {
            Date d = new Date();
            info.setCreationDate(d);
        }

        //Important: Acrobat 7's preflight check for PDF/A-1b wants the creation date in the Info
        //object and in the XMP metadata to have the same timezone or else it shows a validation
        //error even if the times are essentially equal.

        //Dublin Core
        DublinCoreAdapter dc = DublinCoreSchema.getAdapter(meta);
        //PDF/A identification
        PDFAMode pdfaMode = pdfDoc.getProfile().getPDFAMode();
        dc.setCompact(pdfaMode.getPart() != 3);
        if (info.getAuthor() != null) {
            dc.addCreator(info.getAuthor());
        }
        if (info.getTitle() != null) {
            dc.setTitle(info.getTitle());
        }
        if (info.getSubject() != null) {
            //Subject maps to dc:description["x-default"] as per ISO-19005-1:2005/Cor.1:2007
            dc.setDescription(null, info.getSubject());
        }
        if (root.getLanguage() != null) {
            //Note: No check is performed to make sure the value is valid RFC 3066!
            dc.addLanguage(root.getLanguage());
        }
        dc.addDate(info.getCreationDate());

        //Somewhat redundant but some PDF/A checkers issue a warning without this.
        dc.setFormat("application/pdf");

        PDFUAMode pdfuaMode = pdfDoc.getProfile().getPDFUAMode();
        if (pdfuaMode.isEnabled()) {
            PDFUAAdapter pdfua = PDFUAXMPSchema.getAdapter(meta);
            pdfua.setPart(pdfuaMode.getPart());
        }

        if (pdfaMode.isEnabled()) {
            PDFAAdapter pdfa = PDFAXMPSchema.getAdapter(meta);
            pdfa.setPart(pdfaMode.getPart());
            pdfa.setConformance(String.valueOf(pdfaMode.getConformanceLevel()));
        }
        AdobePDFAdapter adobePDF = AdobePDFSchema.getAdapter(meta);
        PDFXMode pdfxMode = pdfDoc.getProfile().getPDFXMode();
        if (pdfxMode != PDFXMode.DISABLED) {
            PDFXAdapter pdfx = PDFXXMPSchema.getAdapter(meta);
            pdfx.setVersion(pdfxMode.getName());

            XAPMMAdapter xapmm = XAPMMXMPSchema.getAdapter(meta);
            xapmm.setVersion("1");
            xapmm.setDocumentID("uuid:" + UUID.randomUUID().toString());
            xapmm.setInstanceID("uuid:" + UUID.randomUUID().toString());
            xapmm.setRenditionClass("default");
            adobePDF.setTrapped("False");
        }
        PDFProfile profile = pdfDoc.getProfile();
        PDFVTMode pdfvtMode = profile.getPDFVTMode();
        if (pdfvtMode != PDFVTMode.DISABLED) {
            PDFVTAdapter pdfvt = PDFVTXMPSchema.getAdapter(meta);
            pdfvt.setVersion("PDF/VT-1");
            if (info.getModDate() != null) {
                pdfvt.setModifyDate(info.getModDate());
            } else if (profile.isModDateRequired()) {
                //if modify date is needed but none is in the Info object, use creation date
                pdfvt.setModifyDate(info.getCreationDate());
            }
        }

        //XMP Basic Schema
        XMPBasicAdapter xmpBasic = XMPBasicSchema.getAdapter(meta);
        xmpBasic.setCreateDate(info.getCreationDate());
        if (info.getModDate() != null) {
            xmpBasic.setModifyDate(info.getModDate());
        } else if (profile.isModDateRequired()) {
            //if modify date is needed but none is in the Info object, use creation date
            xmpBasic.setModifyDate(info.getCreationDate());
        }
        if (info.getCreator() != null) {
            xmpBasic.setCreatorTool(info.getCreator());
        }


        if (info.getKeywords() != null) {
            adobePDF.setKeywords(info.getKeywords());
        }
        if (info.getProducer() != null) {
            adobePDF.setProducer(info.getProducer());
        }
        adobePDF.setPDFVersion(pdfDoc.getPDFVersionString());


        return meta;
    }

    /**
     * Updates the values in the Info object from the XMP metadata according to the rules defined
     * in PDF/A-1 (ISO 19005-1:2005)
     * @param meta the metadata
     * @param info the Info object
     */
    public static void updateInfoFromMetadata(Metadata meta, PDFInfo info) {
        DublinCoreAdapter dc = DublinCoreSchema.getAdapter(meta);
        info.setTitle(dc.getTitle());
        String[] creators = dc.getCreators();
        if (creators != null && creators.length > 0) {
            info.setAuthor(creators[0]);
        } else {
            info.setAuthor(null);
        }

        //dc:description["x-default"] maps to Subject as per ISO-19005-1:2005/Cor.1:2007
        info.setSubject(dc.getDescription());

        AdobePDFAdapter pdf = AdobePDFSchema.getAdapter(meta);
        info.setKeywords(pdf.getKeywords());
        info.setProducer(pdf.getProducer());

        XMPBasicAdapter xmpBasic = XMPBasicSchema.getAdapter(meta);
        info.setCreator(xmpBasic.getCreatorTool());
        Date d;
        d = xmpBasic.getCreateDate();
        xmpBasic.setCreateDate(d); //To make Adobe Acrobat happy (bug filed with Adobe)
        //Adobe Acrobat doesn't like it when the xmp:CreateDate has a different timezone
        //than Info/CreationDate
        info.setCreationDate(d);
        d = xmpBasic.getModifyDate();
        if (d != null) { //ModifyDate is only required for PDF/X
            xmpBasic.setModifyDate(d);
            info.setModDate(d);
        }
    }
}
