/* ====================================================================
   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.poi.hslf.usermodel;

import java.awt.Dimension;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecordTypes;
import org.apache.poi.hslf.blip.DIB;
import org.apache.poi.hslf.blip.EMF;
import org.apache.poi.hslf.blip.JPEG;
import org.apache.poi.hslf.blip.PICT;
import org.apache.poi.hslf.blip.PNG;
import org.apache.poi.hslf.blip.WMF;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.Removal;
import org.apache.poi.util.Units;

/**
 * A class that represents image data contained in a slide show.
 */
public abstract class HSLFPictureData implements PictureData, GenericRecord {

    private static final Logger LOGGER = LogManager.getLogger(HSLFPictureData.class);

    /**
     * Size of the image checksum calculated using MD5 algorithm.
     */
    protected static final int CHECKSUM_SIZE = 16;

    /**
     * Size of the image preamble in bytes.
     * <p>
     * The preamble describes how the image should be decoded. All image types have the same preamble format. The
     * preamble has little endian encoding. Below is a diagram of the preamble contents.
     *
     * <pre>
     *  0               1               2               3
     *  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |           Signature           |          Picture Type         |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |                       Formatted Length                        |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * </pre>
     */
    static final int PREAMBLE_SIZE = 8;

    /**
     * Binary data of the picture, formatted as it will be stored in the {@link HSLFSlideShow}.
     * <p>
     * This does not include the {@link #PREAMBLE_SIZE preamble}.
     */
    private byte[] formattedData;

    /**
     * The instance type/signatures defines if one or two UID instances will be included
     */
    private int uidInstanceCount = 1;

    /**
     * The 1-based index within the pictures stream
     */
    private int index = -1;

    /**
     * {@link EscherRecordTypes#BSTORE_CONTAINER BStore} record tracking all pictures. Should be attached to the
     * slideshow that this picture is linked to.
     */
    final EscherContainerRecord bStore;

    /**
     * Record referencing this picture. Should be attached to the slideshow that this picture is linked to.
     */
    final EscherBSERecord bse;

    /**
     * @deprecated Use {@link HSLFSlideShow#addPicture(byte[], PictureType)} or one of it's overloads to create new
     *             {@link HSLFPictureData}. This API led to detached {@link HSLFPictureData} instances (See Bugzilla
     *             46122) and prevented adding additional functionality.
     */
    @Deprecated
    @Removal(version = "5.3")
    public HSLFPictureData() {
        this(new EscherContainerRecord(), new EscherBSERecord());
        LOGGER.atWarn().log("The no-arg constructor is deprecated. Some functionality such as updating pictures won't " +
                "work.");
    }

    /**
     * Creates a new instance.
     *
     * @param bStore {@link EscherRecordTypes#BSTORE_CONTAINER BStore} record tracking all pictures. Should be attached
     *               to the slideshow that this picture is linked to.
     * @param bse Record referencing this picture. Should be attached to the slideshow that this picture is linked to.
     */
    @Internal
    protected HSLFPictureData(EscherContainerRecord bStore, EscherBSERecord bse) {
        this.bStore = Objects.requireNonNull(bStore);
        this.bse = Objects.requireNonNull(bse);
    }

    /**
     * Blip signature.
     */
    protected abstract int getSignature();

    public abstract void setSignature(int signature);

    /**
     * The instance type/signatures defines if one or two UID instances will be included
     */
    protected int getUIDInstanceCount() {
        return uidInstanceCount;
    }

    /**
     * The instance type/signatures defines if one or two UID instances will be included
     *
     * @param uidInstanceCount the number of uid sequences
     */
    protected void setUIDInstanceCount(int uidInstanceCount) {
        this.uidInstanceCount = uidInstanceCount;
    }

    /**
     * Returns the formatted, binary data of this picture excluding the {@link #PREAMBLE_SIZE preamble} bytes.
     * <p>
     * Primarily intended for internal POI use. Use {@link #getData()} to retrieve the picture represented by this
     * object.
     *
     * @return Picture data formatted for the HSLF format.
     * @see #getData()
     * @see #formatImageForSlideshow(byte[])
     */
    public byte[] getRawData(){
        return formattedData;
    }

    /**
     * Sets the formatted data for this picture.
     * <p>
     * Primarily intended for internal POI use. Use {@link #setData(byte[])} to change the picture represented by this
     * object.
     *
     * @param data Picture data formatted for the HSLF format. Excludes the {@link #PREAMBLE_SIZE preamble}.
     * @see #setData(byte[])
     * @see #formatImageForSlideshow(byte[])
     * @deprecated Set image data using {@link #setData(byte[])}.
     */
    @Deprecated
    @Removal(version = "5.3")
    public void setRawData(byte[] data){
        formattedData = (data == null) ? null : data.clone();
    }

    /**
     * File offset in the 'Pictures' stream
     *
     * @return offset in the 'Pictures' stream
     */
    public int getOffset(){
        return bse.getOffset();
    }

    /**
     * Set offset of this picture in the 'Pictures' stream.
     * We need to set it when a new picture is created.
     *
     * @param offset in the 'Pictures' stream
     * @deprecated This function was only intended for POI internal use. If you have a use case you're concerned about,
     * please open an issue in the POI issue tracker.
     */
    @Deprecated
    @Removal(version = "5.3")
    public void setOffset(int offset){
        LOGGER.atWarn().log("HSLFPictureData#setOffset is deprecated.");
    }

    /**
     * Returns 16-byte checksum of this picture
     */
    public byte[] getUID(){
        return Arrays.copyOf(formattedData, CHECKSUM_SIZE);
    }

    @Override
    public byte[] getChecksum() {
        return getUID();
    }

    /**
     * Compute 16-byte checksum of this picture using MD5 algorithm.
     */
    public static byte[] getChecksum(byte[] data) {
        MessageDigest md5 = CryptoFunctions.getMessageDigest(HashAlgorithm.md5);
        md5.update(data);
        return md5.digest();
    }

    /**
     * Write this picture into <code>OutputStream</code>
     */
    public void write(OutputStream out) throws IOException {
        byte[] data;

        data = new byte[LittleEndianConsts.SHORT_SIZE];
        LittleEndian.putUShort(data, 0, getSignature());
        out.write(data);

        data = new byte[LittleEndianConsts.SHORT_SIZE];
        PictureType pt = getType();
        LittleEndian.putUShort(data, 0, pt.nativeId + EscherRecordTypes.BLIP_START.typeID);
        out.write(data);

        byte[] rd = getRawData();

        data = new byte[LittleEndianConsts.INT_SIZE];
        LittleEndian.putInt(data, 0, rd.length);
        out.write(data);

        out.write(rd);
    }

    /**
     * Create an instance of {@link HSLFPictureData} by type.
     *
     * @param type type of picture.
     * @return concrete instance of {@link HSLFPictureData}.
     * @deprecated Use {@link HSLFSlideShow#addPicture(byte[], PictureType)} or one of it's overloads to create new
     *             {@link HSLFPictureData}. This API led to detached {@link HSLFPictureData} instances (See Bugzilla
     *             46122) and prevented adding additional functionality.
     */
    @Deprecated
    @Removal(version = "5.3")
     public static HSLFPictureData create(PictureType type){
        LOGGER.atWarn().log("HSLFPictureData#create(PictureType) is deprecated. Some functionality such " +
                "as updating pictures won't work.");

        // This record code is a stub. It exists only for API compatibility.
        EscherContainerRecord record = new EscherContainerRecord();
        EscherBSERecord bse = new EscherBSERecord();
        return new HSLFSlideShowImpl.PictureFactory(record, type, new byte[0], 0, 0)
                .setRecord(bse)
                .build();
    }

    /**
     * Creates a new instance of the given image type using data already formatted for storage inside the slideshow.
     * <p>
     * This function is most handy when parsing an existing slideshow, as the picture data are already formatted.
     * @param type Image type.
     * @param recordContainer Record tracking all pictures. Should be attached to the slideshow that this picture is
     *                        linked to.
     * @param bse Record referencing this picture. Should be attached to the slideshow that this picture is linked to.
     * @param data Image data formatted for storage in the slideshow. This does not include the
     *        {@link #PREAMBLE_SIZE preamble}.
     * @param signature Image format-specific signature. See subclasses for signature details.
     * @return New instance.
     *
     * @see #createFromImageData(PictureType, EscherContainerRecord, EscherBSERecord, byte[])
     */
    static HSLFPictureData createFromSlideshowData(
            PictureType type,
            EscherContainerRecord recordContainer,
            EscherBSERecord bse,
            byte[] data,
            int signature
    ) {
        HSLFPictureData instance = newInstance(type, recordContainer, bse);
        instance.setSignature(signature);
        instance.formattedData = data;
        return instance;
    }

    /**
     * Creates a new instance of the given image type using data already formatted for storage inside the slideshow.
     * <p>
     * This function is most handy when adding new pictures to a slideshow, as the image data provided by users is not
     * yet formatted.
     *
     * @param type Image type.
     * @param recordContainer Record tracking all pictures. Should be attached to the slideshow that this picture is
     *                        linked to.
     * @param bse Record referencing this picture. Should be attached to the slideshow that this picture is linked to.
     * @param data Original image data. If these bytes were written to a disk, a common image viewer would be able to
     *             render the image.
     * @return New instance.
     *
     * @see #createFromSlideshowData(PictureType, EscherContainerRecord, EscherBSERecord, byte[], int)
     * @see #setData(byte[])
     */
    static HSLFPictureData createFromImageData(
            PictureType type,
            EscherContainerRecord recordContainer,
            EscherBSERecord bse,
            byte[] data
    ) {
        HSLFPictureData instance = newInstance(type, recordContainer, bse);
        instance.formattedData = instance.formatImageForSlideshow(data);
        return instance;
    }

    private static HSLFPictureData newInstance(
            PictureType type,
            EscherContainerRecord recordContainer,
            EscherBSERecord bse
    ) {
        switch (type) {
            case EMF:
                return new EMF(recordContainer, bse);
            case WMF:
                return new WMF(recordContainer, bse);
            case PICT:
                return new PICT(recordContainer, bse);
            case JPEG:
                return new JPEG(recordContainer, bse);
            case PNG:
                return new PNG(recordContainer, bse);
            case DIB:
                return new DIB(recordContainer, bse);
            default:
                throw new IllegalArgumentException("Unsupported picture type: " + type);
        }
    }

    /**
     * Return 24 byte header which preceeds the actual picture data.
     * <p>
     * The header consists of 2-byte signature, 2-byte type,
     * 4-byte image size and 16-byte checksum of the image data.
     * </p>
     *
     * @return the 24 byte header which preceeds the actual picture data.
     */
    public byte[] getHeader() {
        byte[] header = new byte[CHECKSUM_SIZE + PREAMBLE_SIZE];
        LittleEndian.putInt(header, 0, getSignature());
        LittleEndian.putInt(header, 4, getRawData().length);
        System.arraycopy(formattedData, 0, header, PREAMBLE_SIZE, CHECKSUM_SIZE);
        return header;
    }

    /**
     * Returns the 1-based index of this picture.
     * @return the 1-based index of this pictures within the pictures stream
     */
    public int getIndex() {
        return index;
    }

    /**
     * @param index sets the 1-based index of this pictures within the pictures stream
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * Formats the picture data for storage in the slideshow.
     * <p>
     * Images stored in {@link HSLFSlideShow}s are represented differently than when they are standalone files. The
     * exact formatting differs for each image type.
     *
     * @param data Original image data. If these bytes were written to a disk, a common image viewer would be able to
     *             render the image.
     * @return Formatted image representation.
     */
    protected abstract byte[] formatImageForSlideshow(byte[] data);

    /**
     * @return Size of this picture when stored in the image stream inside the {@link HSLFSlideShow}.
     */
    int getBseSize() {
        return formattedData.length + PREAMBLE_SIZE;
    }

    @Override
    public final void setData(byte[] data) throws IOException {
        /*
         * When working with slideshow pictures, we need to be aware of 2 container units. The first is a list of
         * HSLFPictureData that are the programmatic reference for working with the pictures. The second is the
         * Blip Store. For the purposes of this function, you can think of the Blip Store as containing a list of
         * pointers (with a small summary) to the picture in the slideshow.
         *
         * When updating a picture, we need to update the in-memory data structure (this instance), but we also need to
         * update the stored pointer. When modifying the pointer, we also need to modify all subsequent pointers, since
         * they might shift based on a change in the byte count of the underlying image.
         */
        int oldSize = getBseSize();
        formattedData = formatImageForSlideshow(data);
        int newSize = getBseSize();
        int changeInSize = newSize - oldSize;
        byte[] newUid = getUID();

        boolean foundBseForOldImage = false;

        // Get the BSE records & sort the list by offset, so we can proceed to shift offsets
        @SuppressWarnings("unchecked") // The BStore only contains BSE records
        List<EscherBSERecord> bseRecords = (List<EscherBSERecord>) (Object) bStore.getChildRecords();
        bseRecords.sort(Comparator.comparingInt(EscherBSERecord::getOffset));

        for (EscherBSERecord bse : bseRecords) {

            if (foundBseForOldImage) {

                // The BSE for this picture was modified in a previous iteration, and we are now adjusting
                //  subsequent offsets.
                bse.setOffset(bse.getOffset() + changeInSize);

            } else if (bse == this.bse) { // Reference equals is safe because these BSE belong to the same slideshow

                // This BSE matches the current image. Update the size and UID.
                foundBseForOldImage = true;

                bse.setUid(newUid);

                // Image byte count may have changed, so update the pointer.
                bse.setSize(newSize);
            }
        }
    }

    @Override
    public final String getContentType() {
        return getType().contentType;
    }

    @Override
    public Dimension getImageDimensionInPixels() {
        Dimension dim = getImageDimension();
        return new Dimension(
            Units.pointsToPixel(dim.getWidth()),
            Units.pointsToPixel(dim.getHeight())
        );
    }

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        final Map<String,Supplier<?>> m = new LinkedHashMap<>();
        m.put("type", this::getType);
        m.put("imageDimension", this::getImageDimension);
        m.put("signature", this::getSignature);
        m.put("uidInstanceCount", this::getUIDInstanceCount);
        m.put("offset", this::getOffset);
        m.put("uid", this::getUID);
        m.put("checksum", this::getChecksum);
        m.put("index", this::getIndex);
        m.put("rawData", this::getRawData);
        return Collections.unmodifiableMap(m);
    }
}
