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

import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;

/**
 * A complex property differs from a simple property in that the data can not fit inside a 32 bit
 * integer.  See the specification for more detailed information regarding exactly what is
 * stored here.
 */
public class EscherComplexProperty extends EscherProperty {
    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 100_000_000;

    private byte[] complexData;

    /**
     * Create a complex property using the property id and a byte array containing the complex
     * data value size.
     *
     * @param id          The id consists of the property number, a flag indicating whether this is a blip id and a flag
     *                    indicating that this is a complex property.
     * @param complexSize The byte size of this property.
     */
    public EscherComplexProperty(short id, int complexSize) {
        super((short)(id | IS_COMPLEX));
        complexData = IOUtils.safelyAllocate(complexSize, MAX_RECORD_LENGTH);
    }

    /**
     * Create a complex property using the property number, a flag to indicate whether this is a
     * blip reference and the complex property data size.
     *
     * @param propertyNumber The property number
     * @param isBlipId       Whether this is a blip id.  Should be false.
     * @param complexSize    The byte size of this property.
     */
    public EscherComplexProperty(short propertyNumber, boolean isBlipId, int complexSize) {
        this((short)(propertyNumber | (isBlipId ? IS_BLIP : 0)), complexSize);
    }

    /**
     * Create a complex property using the property type, a flag to indicate whether this is a
     * blip reference and the complex property data size.
     *
     * @param type           The property type
     * @param isBlipId       Whether this is a blip id.  Should be false.
     * @param complexSize    The byte size of this property.
     */
    public EscherComplexProperty(EscherPropertyTypes type, boolean isBlipId, int complexSize) {
        this((short)(type.propNumber | (isBlipId ? IS_BLIP : 0)), complexSize);
    }

    /**
     * Serializes the simple part of this property.  i.e. the first 6 bytes.
     */
    @Override
    public int serializeSimplePart(byte[] data, int pos) {
        LittleEndian.putShort(data, pos, getId());
        LittleEndian.putInt(data, pos + 2, complexData.length);
        return 6;
    }

    /**
     * Serializes the complex part of this property
     *
     * @param data The data array to serialize to
     * @param pos  The offset within data to start serializing to.
     * @return The number of bytes serialized.
     */
    @Override
    public int serializeComplexPart(byte[] data, int pos) {
        System.arraycopy(complexData, 0, data, pos, complexData.length);
        return complexData.length;
    }

    /**
     * Get the complex data value.
     *
     * @return the complex bytes
     */
    public byte[] getComplexData() {
        return complexData;
    }

    public int setComplexData(byte[] complexData) {
        return setComplexData(complexData, 0);
    }

    public int setComplexData(byte[] complexData, int offset) {
        if (complexData == null) {
            return 0;
        } else {
            int copySize = Math.max(0, Math.min(this.complexData.length, complexData.length - offset));
            System.arraycopy(complexData, offset, this.complexData, 0, copySize);
            return copySize;
        }
    }



    protected void resizeComplexData(int newSize) {
        resizeComplexData(newSize, Integer.MAX_VALUE);
    }

    protected void resizeComplexData(int newSize, int copyLen) {
        if (newSize == complexData.length) {
            return;
        }
        byte[] newArray = IOUtils.safelyAllocate(newSize, MAX_RECORD_LENGTH);
        System.arraycopy(complexData, 0, newArray, 0, Math.min(Math.min(complexData.length, copyLen),newSize));
        complexData = newArray;
    }

    /**
     * Determine whether this property is equal to another property.
     *
     * @param o The object to compare to.
     * @return True if the objects are equal.
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof EscherComplexProperty)) {
            return false;
        }

        EscherComplexProperty escherComplexProperty = (EscherComplexProperty) o;

        return Arrays.equals(complexData, escherComplexProperty.complexData);
    }

    /**
     * Calculates the number of bytes required to serialize this property.
     *
     * @return Number of bytes
     */
    @Override
    public int getPropertySize() {
        return 6 + complexData.length;
    }

    @Override
    public int hashCode() {
        return Arrays.deepHashCode(new Object[]{complexData, getId()});
    }

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        return GenericRecordUtil.getGenericProperties(
            "base", super::getGenericProperties,
            "data", this::getComplexData
        );
    }
}
