/*
 * 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.
 */
package org.apache.tika.parser.image;

import static java.nio.charset.StandardCharsets.US_ASCII;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

import org.apache.tika.config.Field;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.EndianUtils;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Photoshop;
import org.apache.tika.metadata.TIFF;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AbstractParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.xmp.JempboxExtractor;
import org.apache.tika.sax.XHTMLContentHandler;

/**
 * Parser for the Adobe Photoshop PSD File Format.
 * <p/>
 * Documentation on the file format is available from
 * http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm
 * <p>
 * An MIT-licensed python parser with test files is:
 * https://github.com/psd-tools/psd-tools
 */
public class PSDParser extends AbstractParser {

    /**
     * Serial version UID
     */
    private static final long serialVersionUID = 883387734607994914L;

    private static final Set<MediaType> SUPPORTED_TYPES = Collections.unmodifiableSet(
            new HashSet<>(Collections.singletonList(MediaType.image("vnd.adobe.photoshop"))));

    private static final int MAX_DATA_LENGTH_BYTES = 10_000_000;
    private static final int MAX_BLOCKS = 10000;

    private int maxDataLengthBytes = MAX_DATA_LENGTH_BYTES;

    public Set<MediaType> getSupportedTypes(ParseContext context) {
        return SUPPORTED_TYPES;
    }

    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
                      ParseContext context) throws IOException, SAXException, TikaException {
        // Check for the magic header signature
        byte[] signature = new byte[4];
        IOUtils.readFully(stream, signature);
        if (signature[0] == (byte) '8' && signature[1] == (byte) 'B' &&
                signature[2] == (byte) 'P' && signature[3] == (byte) 'S') {
            // Good, signature found
        } else {
            throw new TikaException("PSD/PSB magic signature invalid");
        }

        // Check the version
        int version = EndianUtils.readUShortBE(stream);
        if (version == 1 || version == 2) {
            // Good, we support these two
        } else {
            throw new TikaException("Invalid PSD/PSB version " + version);
        }

        // Skip the reserved block
        IOUtils.readFully(stream, new byte[6]);

        // Number of channels in the image
        int numChannels = EndianUtils.readUShortBE(stream);
        // TODO Identify a suitable metadata key for this

        // Width and Height
        int height = EndianUtils.readIntBE(stream);
        int width = EndianUtils.readIntBE(stream);
        metadata.set(TIFF.IMAGE_LENGTH, height);
        metadata.set(TIFF.IMAGE_WIDTH, width);

        // Depth (bits per channel)
        int depth = EndianUtils.readUShortBE(stream);
        metadata.set(TIFF.BITS_PER_SAMPLE, Integer.toString(depth));

        // Colour mode, eg Bitmap or RGB
        int colorMode = EndianUtils.readUShortBE(stream);
        if (colorMode < Photoshop._COLOR_MODE_CHOICES_INDEXED.length) {
            metadata.set(Photoshop.COLOR_MODE, Photoshop._COLOR_MODE_CHOICES_INDEXED[colorMode]);
        }

        // Next is the Color Mode section
        // We don't care about this bit
        long colorModeSectionSize = EndianUtils.readIntBE(stream);
        IOUtils.skipFully(stream, colorModeSectionSize);

        // Next is the Image Resources section
        // Check for certain interesting keys here
        long imageResourcesSectionSize = EndianUtils.readIntBE(stream);
        long read = 0;
        //if something is corrupt about this number, prevent an
        //infinite loop by only reading 10000 blocks
        int blocks = 0;
        while (read < imageResourcesSectionSize && blocks < MAX_BLOCKS) {
            ResourceBlock rb = new ResourceBlock(stream, maxDataLengthBytes);
            if (rb.totalLength <= 0) {
                //break;
            }
            read += rb.totalLength;

            // Is it one we can do something useful with?
            if (rb.id == ResourceBlock.ID_CAPTION) {
                metadata.add(TikaCoreProperties.DESCRIPTION, rb.getDataAsString());
            } else if (rb.id == ResourceBlock.ID_EXIF_1) {
                // TODO Parse the EXIF info via ImageMetadataExtractor
            } else if (rb.id == ResourceBlock.ID_EXIF_3) {
                // TODO Parse the EXIF info via ImageMetadataExtractor
            } else if (rb.id == ResourceBlock.ID_XMP) {
                //if there are multiple xmps in a file, this will
                //overwrite the data from the earlier xmp
                JempboxExtractor ex = new JempboxExtractor(metadata);
                ex.parse(new ByteArrayInputStream(rb.data));
            }
            blocks++;
        }

        // Next is the Layer and Mask Info
        // Finally we have Image Data
        // We can't do anything with these parts

        // We don't have any helpful text, sorry...
        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
        xhtml.startDocument();
        xhtml.endDocument();
    }

    @Field
    public void setMaxDataLengthBytes(int maxDataLengthBytes) {
        this.maxDataLengthBytes = maxDataLengthBytes;
    }

    private static class ResourceBlock {
        private static final long SIGNATURE = 0x3842494d; // 8BIM
        private static final int ID_CAPTION = 0x03F0;
        private static final int ID_EXIF_1 = 0x0422;
        private static final int ID_EXIF_3 = 0x0423;
        private static final int ID_XMP = 0x0424;
        //TODO
        private static final int ID_URL = 0x040B;
        private static final int ID_AUTO_SAVE_FILE_PATH = 0x043E;
        private static final int ID_THUMBNAIL_RESOURCE = 0x040C;
        static int counter = 0;
        private final int maxDataLengthBytes;
        private int id;
        private String name;
        private byte[] data;
        private int totalLength;

        private ResourceBlock(InputStream stream, int maxDataLengthBytes)
                throws IOException, TikaException {
            this.maxDataLengthBytes = maxDataLengthBytes;
            counter++;
            // Verify the signature
            long sig = EndianUtils.readIntBE(stream);
            if (sig != SIGNATURE) {
                throw new TikaException(
                        "Invalid Image Resource Block Signature Found, got " + sig + " 0x" +
                                Long.toHexString(sig) + " but the spec defines " + SIGNATURE);
            }

            // Read the block
            id = EndianUtils.readUShortBE(stream);

            StringBuffer nameB = new StringBuffer();
            int nameLen = 0;
            while (true) {
                int v = stream.read();
                if (v < 0) {
                    throw new EOFException();
                }
                nameLen++;

                if (v == 0) {
                    // The name length is padded to be even
                    if (nameLen % 2 == 1) {
                        stream.read();
                        nameLen++;
                    }
                    break;
                } else {
                    nameB.append((char) v);
                }
                name = nameB.toString();
            }

            int dataLen = EndianUtils.readIntBE(stream);
            if (dataLen < 0) {
                throw new TikaException("data length must be >= 0: " + dataLen);
            }
            if (dataLen % 2 == 1) {
                // Data Length is even padded
                dataLen = dataLen + 1;
            }
            //protect against overflow
            if (Integer.MAX_VALUE - dataLen < nameLen + 10) {
                throw new TikaException("data length is too long:" + dataLen);
            }
            totalLength = 4 + 2 + nameLen + 4 + dataLen;
            // Do we have use for the data segment?
            if (captureData(id)) {
                if (dataLen > maxDataLengthBytes) {
                    throw new TikaException(
                            "data length must be < " + maxDataLengthBytes + ": " + dataLen);
                }
                data = new byte[dataLen];
                IOUtils.readFully(stream, data);
            } else {
                data = new byte[0];
                IOUtils.skipFully(stream, dataLen);
            }
        }

        /**
         * To save memory, only capture the data
         * section of resource blocks we process
         */
        private static boolean captureData(int id) {
            switch (id) {
                case ID_CAPTION:
                case ID_EXIF_1:
                case ID_EXIF_3:
                case ID_XMP:
                    return true;
            }
            return false;
        }

        private String getDataAsString() {
            // Will be null padded
            return new String(data, 0, data.length - 1, US_ASCII);
        }
    }
}
