/* ====================================================================
   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.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;

/**
 * The BSE record is related closely to the {@code EscherBlipRecord} and stores
 * extra information about the blip.  A blip record is actually stored inside
 * the BSE record even though the BSE record isn't actually a container record.
 *
 * @see EscherBlipRecord
 */
public final class EscherBSERecord extends EscherRecord {

    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 100_000;

    public static final short RECORD_ID = EscherRecordTypes.BSE.typeID;

    private byte field_1_blipTypeWin32;
    private byte field_2_blipTypeMacOS;
    private final byte[] field_3_uid = new byte[16];
    private short field_4_tag;
    private int field_5_size;
    private int field_6_ref;
    private int field_7_offset;
    private byte field_8_usage;
    private byte field_9_name;
    private byte field_10_unused2;
    private byte field_11_unused3;
    private EscherBlipRecord field_12_blipRecord;

    private byte[] _remainingData = new byte[0];

    public EscherBSERecord() {
        setRecordId(RECORD_ID);
    }

    public EscherBSERecord(EscherBSERecord other) {
        super(other);

        field_1_blipTypeWin32 = other.field_1_blipTypeWin32;
        field_2_blipTypeMacOS = other.field_2_blipTypeMacOS;
        System.arraycopy(other.field_3_uid, 0, field_3_uid, 0, field_3_uid.length);
        field_4_tag = other.field_4_tag;
        field_5_size = other.field_5_size;
        field_6_ref = other.field_6_ref;
        field_7_offset = other.field_7_offset;
        field_8_usage = other.field_8_usage;
        field_9_name = other.field_9_name;
        field_10_unused2 = other.field_10_unused2;
        field_11_unused3 = other.field_11_unused3;
        field_12_blipRecord = other.field_12_blipRecord.copy();
        _remainingData = other._remainingData.clone();
    }

    @Override
    public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
        int bytesRemaining = readHeader( data, offset );
        int pos = offset + 8;
        field_1_blipTypeWin32 = data[pos];
        field_2_blipTypeMacOS = data[pos + 1];
        System.arraycopy( data, pos + 2, field_3_uid, 0, 16 );
        field_4_tag = LittleEndian.getShort( data, pos + 18 );
        field_5_size = LittleEndian.getInt( data, pos + 20 );
        field_6_ref = LittleEndian.getInt( data, pos + 24 );
        field_7_offset = LittleEndian.getInt( data, pos + 28 );
        field_8_usage = data[pos + 32];
        field_9_name = data[pos + 33];
        field_10_unused2 = data[pos + 34];
        field_11_unused3 = data[pos + 35];
        bytesRemaining -= 36;

        int bytesRead = 0;
        if (bytesRemaining > 0) {
            // Some older escher formats skip this last record
            field_12_blipRecord = (EscherBlipRecord) recordFactory.createRecord( data, pos + 36 );
            bytesRead = field_12_blipRecord.fillFields( data, pos + 36, recordFactory );
        }
        pos += 36 + bytesRead;
        bytesRemaining -= bytesRead;

        _remainingData = IOUtils.safelyClone(data, pos, bytesRemaining, MAX_RECORD_LENGTH);

        return bytesRemaining + 8 + 36 + (field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize()) ;

    }

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

        if (_remainingData == null) {
            _remainingData = new byte[0];
        }

        LittleEndian.putShort( data, offset, getOptions() );
        LittleEndian.putShort( data, offset + 2, getRecordId() );
        int blipSize = field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize();
        int remainingBytes = _remainingData.length + 36 + blipSize;
        LittleEndian.putInt( data, offset + 4, remainingBytes );

        data[offset + 8] = field_1_blipTypeWin32;
        data[offset + 9] = field_2_blipTypeMacOS;
        System.arraycopy(field_3_uid, 0, data, offset + 10, 16);
        LittleEndian.putShort( data, offset + 26, field_4_tag );
        LittleEndian.putInt( data, offset + 28, field_5_size );
        LittleEndian.putInt( data, offset + 32, field_6_ref );
        LittleEndian.putInt( data, offset + 36, field_7_offset );
        data[offset + 40] = field_8_usage;
        data[offset + 41] = field_9_name;
        data[offset + 42] = field_10_unused2;
        data[offset + 43] = field_11_unused3;
        int bytesWritten = 0;
        if (field_12_blipRecord != null) {
            bytesWritten = field_12_blipRecord.serialize( offset + 44, data, new NullEscherSerializationListener() );
        }
        System.arraycopy( _remainingData, 0, data, offset + 44 + bytesWritten, _remainingData.length );
        int pos = offset + 8 + 36 + _remainingData.length + bytesWritten;

        listener.afterRecordSerialize(pos, getRecordId(), pos - offset, this);
        return pos - offset;
    }

    @Override
    public int getRecordSize() {
        int field_12_size = 0;
        if(field_12_blipRecord != null) {
            field_12_size = field_12_blipRecord.getRecordSize();
        }
        int remaining_size = 0;
        if(_remainingData != null) {
            remaining_size = _remainingData.length;
        }
        return 8 + 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 +
            1 + 1 + field_12_size + remaining_size;
    }

    @Override
    public String getRecordName() {
        return EscherRecordTypes.BSE.recordName;
    }

    /**
     * The expected blip type under windows (failure to match this blip type will result in
     * Excel converting to this format).
     *
     * @return win32 blip type
     */
    public byte getBlipTypeWin32() {
        return field_1_blipTypeWin32;
    }

    public PictureType getPictureTypeWin32() {
        return PictureType.forNativeID(field_1_blipTypeWin32);
    }

    /**
     * Set the expected win32 blip type
     *
     * @param blipTypeWin32 win32 blip type
     */
    public void setBlipTypeWin32(byte blipTypeWin32) {
        field_1_blipTypeWin32 = blipTypeWin32;
    }

    /**
     * The expected blip type under MacOS (failure to match this blip type will result in
     * Excel converting to this format).
     *
     * @return MacOS blip type
     */
    public byte getBlipTypeMacOS() {
        return field_2_blipTypeMacOS;
    }

    public PictureType getPictureTypeMacOS() {
        return PictureType.forNativeID(field_2_blipTypeMacOS);
    }

    /**
     * Set the expected MacOS blip type
     *
     * @param blipTypeMacOS MacOS blip type
     */
    public void setBlipTypeMacOS(byte blipTypeMacOS) {
        field_2_blipTypeMacOS = blipTypeMacOS;
    }

    /**
     * 16 byte MD4 checksum.
     *
     * @return 16 byte MD4 checksum
     */
    public byte[] getUid() {
        return field_3_uid;
    }

    /**
     * 16 byte MD4 checksum.
     *
     * @param uid 16 byte MD4 checksum
     */
    public void setUid(byte[] uid) {
        if (uid == null || uid.length != 16) {
            throw new IllegalArgumentException("uid must be byte[16]");
        }
        System.arraycopy(uid, 0, field_3_uid, 0, field_3_uid.length);
    }

    /**
     * unused
     *
     * @return an unknown tag
     */
    public short getTag() {
        return field_4_tag;
    }

    /**
     * unused
     *
     * @param tag unknown tag
     */
    public void setTag(short tag) {
        field_4_tag = tag;
    }

    /**
     * Blip size in stream.
     *
     * @return the blip size
     */
    public int getSize() {
        return field_5_size;
    }

    /**
     * Blip size in stream.
     *
     * @param size blip size
     */
    public void setSize(int size) {
        field_5_size = size;
    }

    /**
     * The reference count of this blip.
     *
     * @return the reference count
     */
    public int getRef() {
        return field_6_ref;
    }

    /**
     * The reference count of this blip.
     *
     * @param ref the reference count
     */
    public void setRef(int ref) {
        field_6_ref = ref;
    }

    /**
     * File offset in the delay stream.
     *
     * @return the file offset
     */
    public int getOffset() {
        return field_7_offset;
    }

    /**
     * File offset in the delay stream.
     *
     * @param offset the file offset
     */
    public void setOffset(int offset) {
        field_7_offset = offset;
    }

    /**
     * Defines the way this blip is used.
     *
     * @return the blip usage
     */
    public byte getUsage() {
        return field_8_usage;
    }

    /**
     * Defines the way this blip is used.
     *
     * @param usage the blip usae
     */
    public void setUsage(byte usage) {
        field_8_usage = usage;
    }

    /**
     * The length in characters of the blip name.
     *
     * @return the blip name length
     */
    public byte getName() {
        return field_9_name;
    }

    /**
     * The length in characters of the blip name.
     *
     * @param name the blip name length
     */
    public void setName(byte name) {
        field_9_name = name;
    }

    public byte getUnused2() {
        return field_10_unused2;
    }

    public void setUnused2(byte unused2) {
        field_10_unused2 = unused2;
    }

    public byte getUnused3() {
        return field_11_unused3;
    }

    public void setUnused3(byte unused3) {
        field_11_unused3 = unused3;
    }

    public EscherBlipRecord getBlipRecord() {
        return field_12_blipRecord;
    }

    public void setBlipRecord(EscherBlipRecord blipRecord) {
        field_12_blipRecord = blipRecord;
    }

    /**
     * Any remaining data in this record.
     *
     * @return the remaining bytes
     */
    public byte[] getRemainingData() {
        return _remainingData;
    }

    /**
     * Any remaining data in this record.
     *
     * @param remainingData the remaining bytes
     */
    public void setRemainingData(byte[] remainingData) {
        _remainingData = (remainingData == null) ? new byte[0] : remainingData.clone();
    }

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        final Map<String, Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
        m.put("blipTypeWin32", this::getBlipTypeWin32);
        m.put("pictureTypeWin32", this::getPictureTypeWin32);
        m.put("blipTypeMacOS", this::getBlipTypeMacOS);
        m.put("pictureTypeMacOS", this::getPictureTypeMacOS);
        m.put("suid", this::getUid);
        m.put("tag", this::getTag);
        m.put("size", this::getSize);
        m.put("ref", this::getRef);
        m.put("offset", this::getOffset);
        m.put("usage", this::getUsage);
        m.put("name", this::getName);
        m.put("unused2", this::getUnused2);
        m.put("unused3", this::getUnused3);
        m.put("blipRecord", this::getBlipRecord);
        m.put("remainingData", this::getRemainingData);
        return Collections.unmodifiableMap(m);
    }

    @Override
    public Enum getGenericRecordType() {
        return EscherRecordTypes.BSE;
    }

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