/* ====================================================================
   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.ddf;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Supplier;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;

import static org.apache.logging.log4j.util.Unbox.box;

public final class EscherMetafileBlip extends EscherBlipRecord {
    private static final Logger LOGGER = LogManager.getLogger(EscherMetafileBlip.class);
    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 100_000_000;

    public static final short RECORD_ID_EMF = EscherRecordTypes.BLIP_EMF.typeID;
    public static final short RECORD_ID_WMF = EscherRecordTypes.BLIP_WMF.typeID;
    public static final short RECORD_ID_PICT = EscherRecordTypes.BLIP_PICT.typeID;

    private static final int HEADER_SIZE = 8;

    private final byte[] field_1_UID = new byte[16];
    /**
     * The primary UID is only saved to disk if (blip_instance ^ blip_signature == 1)
     */
    private final byte[] field_2_UID = new byte[16];
    private int field_2_cb;
    private int field_3_rcBounds_x1;
    private int field_3_rcBounds_y1;
    private int field_3_rcBounds_x2;
    private int field_3_rcBounds_y2;
    private int field_4_ptSize_w;
    private int field_4_ptSize_h;
    private int field_5_cbSave;
    private byte field_6_fCompression;
    private byte field_7_fFilter;

    private byte[] raw_pictureData;
    private byte[] remainingData;

    public EscherMetafileBlip() {}

    public EscherMetafileBlip(EscherMetafileBlip other) {
        super(other);
        System.arraycopy(other.field_1_UID, 0, field_1_UID, 0, field_1_UID.length);
        System.arraycopy(other.field_2_UID, 0, field_2_UID, 0, field_2_UID.length);
        field_2_cb = other.field_2_cb;
        field_3_rcBounds_x1 = other.field_3_rcBounds_x1;
        field_3_rcBounds_y1 = other.field_3_rcBounds_y1;
        field_3_rcBounds_x2 = other.field_3_rcBounds_x2;
        field_3_rcBounds_y2 = other.field_3_rcBounds_y2;
        field_4_ptSize_h = other.field_4_ptSize_h;
        field_4_ptSize_w = other.field_4_ptSize_w;
        field_5_cbSave = other.field_5_cbSave;
        field_6_fCompression = other.field_6_fCompression;
        field_7_fFilter = other.field_7_fFilter;
        raw_pictureData = (other.raw_pictureData == null) ? null : other.raw_pictureData.clone();
        remainingData = (other.remainingData == null) ? null : other.remainingData.clone();
    }

    @Override
    public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
        int bytesAfterHeader = readHeader( data, offset );
        int pos = offset + HEADER_SIZE;
        System.arraycopy( data, pos, field_1_UID, 0, 16 ); pos += 16;

        if((getOptions() ^ getSignature()) == 0x10){
            System.arraycopy( data, pos, field_2_UID, 0, 16 ); pos += 16;
        }

        field_2_cb = LittleEndian.getInt( data, pos ); pos += 4;
        field_3_rcBounds_x1 = LittleEndian.getInt( data, pos ); pos += 4;
        field_3_rcBounds_y1 = LittleEndian.getInt( data, pos ); pos += 4;
        field_3_rcBounds_x2 = LittleEndian.getInt( data, pos ); pos += 4;
        field_3_rcBounds_y2 = LittleEndian.getInt( data, pos ); pos += 4;
        field_4_ptSize_w = LittleEndian.getInt( data, pos ); pos += 4;
        field_4_ptSize_h = LittleEndian.getInt( data, pos ); pos += 4;
        field_5_cbSave = LittleEndian.getInt( data, pos ); pos += 4;
        field_6_fCompression = data[pos]; pos++;
        field_7_fFilter = data[pos]; pos++;

        raw_pictureData = IOUtils.safelyClone(data, pos, field_5_cbSave, MAX_RECORD_LENGTH);
        pos += field_5_cbSave;

        // 0 means DEFLATE compression
        // 0xFE means no compression
        if (field_6_fCompression == 0) {
            super.setPictureData(inflatePictureData(raw_pictureData));
        } else {
            super.setPictureData(raw_pictureData);
        }

        int remaining = bytesAfterHeader - pos + offset + HEADER_SIZE;
        if(remaining > 0) {
            remainingData = IOUtils.safelyClone(data, pos, remaining, MAX_RECORD_LENGTH);
        }
        return bytesAfterHeader + HEADER_SIZE;
    }

    @Override
    public int serialize(int offset, byte[] data, EscherSerializationListener listener) {
        listener.beforeRecordSerialize(offset, getRecordId(), this);

        int pos = offset;
        LittleEndian.putShort( data, pos, getOptions() ); pos += 2;
        LittleEndian.putShort( data, pos, getRecordId() ); pos += 2;
        LittleEndian.putInt( data, pos, getRecordSize() - HEADER_SIZE ); pos += 4;

        System.arraycopy( field_1_UID, 0, data, pos, field_1_UID.length ); pos += field_1_UID.length;
        if ((getOptions() ^ getSignature()) == 0x10) {
            System.arraycopy( field_2_UID, 0, data, pos, field_2_UID.length ); pos += field_2_UID.length;
        }
        LittleEndian.putInt( data, pos, field_2_cb ); pos += 4;
        LittleEndian.putInt( data, pos, field_3_rcBounds_x1 ); pos += 4;
        LittleEndian.putInt( data, pos, field_3_rcBounds_y1 ); pos += 4;
        LittleEndian.putInt( data, pos, field_3_rcBounds_x2 ); pos += 4;
        LittleEndian.putInt( data, pos, field_3_rcBounds_y2 ); pos += 4;
        LittleEndian.putInt( data, pos, field_4_ptSize_w ); pos += 4;
        LittleEndian.putInt( data, pos, field_4_ptSize_h ); pos += 4;
        LittleEndian.putInt( data, pos, field_5_cbSave ); pos += 4;
        data[pos] = field_6_fCompression; pos++;
        data[pos] = field_7_fFilter; pos++;

        System.arraycopy( raw_pictureData, 0, data, pos, raw_pictureData.length ); pos += raw_pictureData.length;
        if(remainingData != null) {
            System.arraycopy( remainingData, 0, data, pos, remainingData.length ); pos += remainingData.length;
        }

        listener.afterRecordSerialize(offset + getRecordSize(), getRecordId(), getRecordSize(), this);
        return getRecordSize();
    }

    /**
     * Decompresses the provided data, returning the inflated result.
     *
     * @param data the deflated picture data.
     * @return the inflated picture data.
     */
    private static byte[] inflatePictureData(byte[] data) {
        try {
            InflaterInputStream in = new InflaterInputStream(
                new ByteArrayInputStream( data ) );
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buf = new byte[4096];
            int readBytes;
            while ((readBytes = in.read(buf)) > 0) {
                out.write(buf, 0, readBytes);
            }
            return out.toByteArray();
        } catch (IOException e) {
            LOGGER.atWarn().withThrowable(e).log("Possibly corrupt compression or non-compressed data");
            return data;
        }
    }

    @Override
    public int getRecordSize() {
        int size = 8 + 50 + raw_pictureData.length;
        if(remainingData != null) {
            size += remainingData.length;
        }
        if((getOptions() ^ getSignature()) == 0x10){
            size += field_2_UID.length;
        }
        return size;
    }

    /**
     * Gets the first MD4, that specifies the unique identifier of the
     * uncompressed blip data
     *
     * @return the first MD4
     */
    public byte[] getUID() {
        return field_1_UID;
    }

    /**
     * Sets the first MD4, that specifies the unique identifier of the
     * uncompressed blip data
     *
     * @param uid the first MD4
     */
    public void setUID(byte[] uid) {
        if (uid == null || uid.length != 16) {
            throw new IllegalArgumentException("uid must be byte[16]");
        }
        System.arraycopy(uid, 0, field_1_UID, 0, field_1_UID.length);
    }

    /**
     * Gets the second MD4, that specifies the unique identifier of the
     * uncompressed blip data
     *
     * @return the second MD4
     */
    public byte[] getPrimaryUID() {
        return field_2_UID;
    }

    /**
     * Sets the second MD4, that specifies the unique identifier of the
     * uncompressed blip data
     *
     * @param primaryUID the second MD4
     */
    public void setPrimaryUID(byte[] primaryUID) {
        if (primaryUID == null || primaryUID.length != 16) {
            throw new IllegalArgumentException("primaryUID must be byte[16]");
        }
        System.arraycopy(primaryUID, 0, field_2_UID, 0, field_2_UID.length);
    }

    /**
     * Gets the uncompressed size (in bytes)
     *
     * @return the uncompressed size
     */
    public int getUncompressedSize() {
        return field_2_cb;
    }

    /**
     * Sets the uncompressed size (in bytes)
     *
     * @param uncompressedSize the uncompressed size
     */
    public void setUncompressedSize(int uncompressedSize) {
        field_2_cb = uncompressedSize;
    }

    /**
     * Get the clipping region of the metafile
     *
     * @return the clipping region
     */
    public Rectangle getBounds() {
        return new Rectangle(field_3_rcBounds_x1,
                             field_3_rcBounds_y1,
                             field_3_rcBounds_x2 - field_3_rcBounds_x1,
                             field_3_rcBounds_y2 - field_3_rcBounds_y1);
    }

    /**
     * Sets the clipping region
     *
     * @param bounds the clipping region
     */
    public void setBounds(Rectangle bounds) {
        field_3_rcBounds_x1 = bounds.x;
        field_3_rcBounds_y1 = bounds.y;
        field_3_rcBounds_x2 = bounds.x + bounds.width;
        field_3_rcBounds_y2 = bounds.y + bounds.height;
    }

    /**
     * Gets the dimensions of the metafile
     *
     * @return the dimensions of the metafile
     */
    public Dimension getSizeEMU() {
        return new Dimension(field_4_ptSize_w, field_4_ptSize_h);
    }

    /**
     * Gets the dimensions of the metafile
     *
     * @param sizeEMU the dimensions of the metafile
     */
    public void setSizeEMU(Dimension sizeEMU) {
        field_4_ptSize_w = sizeEMU.width;
        field_4_ptSize_h = sizeEMU.height;
    }

    /**
     * Gets the compressed size of the metafile (in bytes)
     *
     * @return the compressed size
     */
    public int getCompressedSize() {
        return field_5_cbSave;
    }

    /**
     * Sets the compressed size of the metafile (in bytes)
     *
     * @param compressedSize the compressed size
     */
    public void setCompressedSize(int compressedSize) {
        field_5_cbSave = compressedSize;
    }

    /**
     * Gets the compression of the metafile
     *
     * @return true, if the metafile is compressed
     */
    public boolean isCompressed() {
        return (field_6_fCompression == 0);
    }

    /**
     * Sets the compression of the metafile
     *
     * @param compressed the compression state, true if it's compressed
     */
    public void setCompressed(boolean compressed) {
        field_6_fCompression = compressed ? 0 : (byte)0xFE;
    }

    /**
     * Gets the filter byte - this is usually 0xFE
     *
     * @return the filter byte
     */
    public byte getFilter() {
        return field_7_fFilter;
    }

    /**
     * Sets the filter byte - this is usually 0xFE
     *
     * @param filter the filter byte
     */
    public void setFilter(byte filter) {
        field_7_fFilter = filter;
    }



    /**
     * Returns any remaining bytes
     *
     * @return any remaining bytes
     */
    public byte[] getRemainingData() {
        return remainingData;
    }

    /**
     * Return the blip signature
     *
     * @return the blip signature
     */
    public short getSignature() {
        switch (EscherRecordTypes.forTypeID(getRecordId())) {
            case BLIP_EMF:  return HSSFPictureData.MSOBI_EMF;
            case BLIP_WMF:  return HSSFPictureData.MSOBI_WMF;
            case BLIP_PICT: return HSSFPictureData.MSOBI_PICT;
        }
        LOGGER.atWarn().log("Unknown metafile: {}", box(getRecordId()));
        return 0;
    }

    @Override
    public void setPictureData(byte[] pictureData) {
    	super.setPictureData(pictureData);
        setUncompressedSize(pictureData.length);

        // info of chicago project:
        // "... LZ compression algorithm in the format used by GNU Zip deflate/inflate with a 32k window ..."
        // not sure what to do, when lookup tables exceed 32k ...

        try {
	        ByteArrayOutputStream bos = new ByteArrayOutputStream();
	        DeflaterOutputStream dos = new DeflaterOutputStream(bos);
	        dos.write(pictureData);
	        dos.close();
	        raw_pictureData = bos.toByteArray();
        } catch (IOException e) {
        	throw new RuntimeException("Can't compress metafile picture data", e);
        }

        setCompressedSize(raw_pictureData.length);
        setCompressed(true);
    }

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        final Map<String, Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
        m.put("uid", this::getUID);
        m.put("uncompressedSize", this::getUncompressedSize);
        m.put("bounds", this::getBounds);
        m.put("sizeInEMU", this::getSizeEMU);
        m.put("compressedSize", this::getCompressedSize);
        m.put("isCompressed", this::isCompressed);
        m.put("filter", this::getFilter);
        return Collections.unmodifiableMap(m);
    }

    @Override
    public EscherMetafileBlip copy() {
        return new EscherMetafileBlip(this);
    }
}
