/*
 * 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 = 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);
                }
            }
        };
}
