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

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.WeakHashMap;

import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;

import org.apache.xmlgraphics.image.loader.ImageContext;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.util.io.SubInputStream;

import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.render.pdf.pdfbox.Cache.ValueMaker;

/**
 * Image preloader for PDF images.
 */
public class PreloaderPDF extends AbstractImagePreloader {

    /** PDF header text */
    private static final String PDF_HEADER = "%PDF-";

    /** static PDDocument cache for faster multi-page processing */
    private static final Cache.Type CACHE_TYPE = Cache.Type.valueOf(
            System.getProperty("fop.pdfbox.preloader-cache", Cache.Type.WEAK.name()).toUpperCase(Locale.ENGLISH));

    private static Map<Object, Cache<URI, PDDocument>> documentCacheMap
            = Collections.synchronizedMap(new WeakHashMap<Object, Cache<URI, PDDocument>>());
    //the cache here can cause problems because PDDocument that have been closed might still
    //be accessed. Example: java.io.IOException: The handle is invalid

    /** {@inheritDoc} */
    public ImageInfo preloadImage(String uri, Source src, ImageContext context)
                throws IOException, ImageException {
        if (!ImageUtil.hasImageInputStream(src)) {
            return null;
        }
        ImageInfo info = null;
        ImageInputStream in = ImageUtil.needImageInputStream(src);
        in.mark();
        try {
            byte[] header = getHeader(in, PDF_HEADER.length());
            String s = new String(header, "US-ASCII");

            boolean supported = PDF_HEADER.equals(s);
            if (supported) {
                info = loadPDF(uri, src, context);
            }
            return info;
        } finally {
            if (info == null) {
                in.reset(); //Error detected or not a PDF file
            }
        }
    }

    private static URI deriveDocumentURI(String uri) throws ImageException {
        try {
            URI originalURI = new URI(URISpecification.escapeURI(uri));
            URI tempURI = new URI(originalURI.getScheme(),
                    originalURI.getSchemeSpecificPart(), null);
            return tempURI;
        } catch (URISyntaxException e) {
            throw new ImageException("Problem processing URI", e);
        }
    }

    private ImageInfo loadPDF(String uri, Source src, ImageContext context) throws IOException,
            ImageException {
        int selectedPage = ImageUtil.needPageIndexFromURI(uri);

        URI docURI = deriveDocumentURI(src.getSystemId());

        PDDocument pddoc = getDocument(context, docURI, src);
        pddoc = Interceptors.getInstance().interceptOnLoad(pddoc, docURI);

        //Disable the warning about a missing close since we rely on the GC to decide when
        //the cached PDF shall be disposed off.
        pddoc.getDocument().setWarnMissingClose(false);

        int pageCount = pddoc.getNumberOfPages();
        if (selectedPage < 0 || selectedPage >= pageCount) {
            throw new ImageException("Selected page (index: " + selectedPage
                    + ") does not exist in the PDF file. The document has "
                    + pddoc.getNumberOfPages() + " pages.");
        }
        PDPage page = (PDPage)pddoc.getDocumentCatalog().getPages().get(selectedPage);
        PDRectangle mediaBox = page.getMediaBox();
        PDRectangle cropBox = page.getCropBox();
        PDRectangle viewBox = cropBox != null ? cropBox : mediaBox;
        int w = Math.round(viewBox.getWidth() * 1000);
        int h = Math.round(viewBox.getHeight() * 1000);

        //Handle the /Rotation entry on the page dict
        int rotation = PDFUtil.getNormalizedRotation(page);
        if (rotation == 90 || rotation == 270) {
            //Swap width and height
            int exch = w;
            w = h;
            h = exch;
        }

        ImageSize size = new ImageSize();
        size.setSizeInMillipoints(w, h);
        size.setResolution(context.getSourceResolution());
        size.calcPixelsFromSize();

        ImageInfo info = new ImageInfo(uri, ImagePDF.MIME_PDF);
        info.setSize(size);
        info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, new ImagePDF(info, pddoc));

        int lastPageIndex = pddoc.getNumberOfPages() - 1;
        if (selectedPage < lastPageIndex) {
            info.getCustomObjects().put(ImageInfo.HAS_MORE_IMAGES, Boolean.TRUE);
        }

        return info;
    }

//    private void notifyCouldNotDecrypt(Exception e)
//            throws ImageException {
//        throw new ImageException("Error decrypting PDF: "
//                + e.getMessage()
//                + "\nPlease use an OnLoadInterceptor to provide "
//                + "suitable decryption material (ex. a password).", e);
//    }

    private PDDocument getDocument(Object context, URI uri, Source src)
            throws IOException {
        try {
            return getDocumentCache(context).getValue(uri, createDocumentMaker(src, uri));
        } catch (IOException ioe) {
            throw ioe;
        } catch (Exception e) {
            // We cannot recover from this
            throw new RuntimeException(e);
        }
    }

    private Cache<URI, PDDocument> getDocumentCache(Object context) {
        Cache<URI, PDDocument> documentCache = documentCacheMap.get(context);

        if (documentCache == null) {
            documentCache = Cache.createCache(CACHE_TYPE);
            documentCacheMap.put(context, documentCache);
        }
        return documentCache;
    }

    private ValueMaker<PDDocument> createDocumentMaker(final Source src, final URI docURI) {
        return new DocumentMaker(src, docURI);
    }

    static class DocumentMaker implements ValueMaker<PDDocument> {
        private Source src;
        private URI docURI;

        public DocumentMaker(Source src, URI docURI) {
            this.src = src;
            this.docURI = docURI;
        }

            public PDDocument make() throws Exception {
                final InputStream in = ImageUtil.needInputStream(src);
                try {
                    PDDocument pddoc = PDDocument.load(new SubInputStream(in, Integer.MAX_VALUE));
                    return Interceptors.getInstance().interceptOnLoad(pddoc, docURI);
                } finally {
                    ImageUtil.closeQuietly(src);
                }
            }
        };
}
