/* ====================================================================
   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.util.IOUtils;
import org.apache.poi.util.LittleEndian;

/**
 * The escher client anchor specifies which rows and cells the shape is bound to as well as
 * the offsets within those cells.  Each cell is 1024 units wide by 256 units long regardless
 * of the actual size of the cell.  The EscherClientAnchorRecord only applies to the top-most
 * shapes. Shapes contained in groups are bound using the EscherChildAnchorRecords. Referred to as an
 * {@code OfficeArtClientAnchor} by {@code [MS-PPT] - v20210216}.
 *
 * @see EscherChildAnchorRecord
 */
public class EscherClientAnchorRecord extends EscherRecord {
    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 100_000;

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

    /**
     * bit[0] -  fMove (1 bit): A bit that specifies whether the shape will be kept intact when the cells are moved.
     * bit[1] - fSize (1 bit): A bit that specifies whether the shape will be kept intact when the cells are resized. If fMove is 1, the value MUST be 1.
     * bit[2-4] - reserved, MUST be 0 and MUST be ignored
     * bit[5-15]- Undefined and MUST be ignored.
     *
     * it can take values: 0, 2, 3
     */
    private short field_1_flag;
    private short field_2_col1;
    private short field_3_dx1;
    private short field_4_row1;
    private short field_5_dy1;
    private short field_6_col2;
    private short field_7_dx2;
    private short field_8_row2;
    private short field_9_dy2;
    private byte[] remainingData = new byte[0];
    private boolean shortRecord;

    public EscherClientAnchorRecord() {}

    public EscherClientAnchorRecord(EscherClientAnchorRecord other) {
        super(other);
        field_1_flag = other.field_1_flag;
        field_2_col1 = other.field_2_col1;
        field_3_dx1 = other.field_3_dx1;
        field_4_row1 = other.field_4_row1;
        field_5_dy1 = other.field_5_dy1;
        field_6_col2 = other.field_6_col2;
        field_7_dx2 = other.field_7_dx2;
        field_8_row2 = other.field_8_row2;
        field_9_dy2 = other.field_9_dy2;
        remainingData = (other.remainingData == null) ? null : other.remainingData.clone();
        shortRecord = other.shortRecord;
    }

    @Override
    public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
        int bytesRemaining = readHeader( data, offset );
        int pos            = offset + 8;
        int size           = 0;

        // Always find 4 two byte entries. Sometimes find 9
        /*if (bytesRemaining == 4) // Word format only 4 bytes
        {
            // Not sure exactly what the format is quite yet, likely a reference to a PLC
        }
        else */
        if (bytesRemaining != 4) // Word format only 4 bytes
        {
            field_1_flag   =  LittleEndian.getShort( data, pos + size );     size += 2;
            field_2_col1   =  LittleEndian.getShort( data, pos + size );     size += 2;
            field_3_dx1    =  LittleEndian.getShort( data, pos + size );     size += 2;
            field_4_row1   =  LittleEndian.getShort( data, pos + size );     size += 2;
            if(bytesRemaining >= 18) {
                field_5_dy1    =  LittleEndian.getShort( data, pos + size );     size += 2;
                field_6_col2   =  LittleEndian.getShort( data, pos + size );     size += 2;
                field_7_dx2    =  LittleEndian.getShort( data, pos + size );     size += 2;
                field_8_row2   =  LittleEndian.getShort( data, pos + size );     size += 2;
                field_9_dy2    =  LittleEndian.getShort( data, pos + size );     size += 2;
                shortRecord = false;
            } else {
                shortRecord = true;
            }
        }
        bytesRemaining -= size;
        remainingData  = IOUtils.safelyClone(data, pos + size, bytesRemaining, MAX_RECORD_LENGTH);

        return 8 + size + bytesRemaining;
    }

    @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 remainingBytes = remainingData.length + (shortRecord ? 8 : 18);
        LittleEndian.putInt( data, offset + 4, remainingBytes );
        LittleEndian.putShort( data, offset + 8, field_1_flag );
        LittleEndian.putShort( data, offset + 10, field_2_col1 );
        LittleEndian.putShort( data, offset + 12, field_3_dx1 );
        LittleEndian.putShort( data, offset + 14, field_4_row1 );
        if(!shortRecord) {
            LittleEndian.putShort( data, offset + 16, field_5_dy1 );
            LittleEndian.putShort( data, offset + 18, field_6_col2 );
            LittleEndian.putShort( data, offset + 20, field_7_dx2 );
            LittleEndian.putShort( data, offset + 22, field_8_row2 );
            LittleEndian.putShort( data, offset + 24, field_9_dy2 );
        }
        System.arraycopy( remainingData, 0, data, offset + (shortRecord ? 16 : 26), remainingData.length );
        int pos = offset + 8 + (shortRecord ? 8 : 18) + remainingData.length;

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

    @Override
    public int getRecordSize()
    {
        return 8 + (shortRecord ? 8 : 18) + (remainingData == null ? 0 : remainingData.length);
    }

    @Override
    public short getRecordId() {
        return RECORD_ID;
    }

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

    /**
     * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
     *
     * @return the move/size flag
     */
    public short getFlag()
    {
        return field_1_flag;
    }

    /**
     * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
     *
     * @param field_1_flag the move/size flag
     */
    public void setFlag( short field_1_flag )
    {
        this.field_1_flag = field_1_flag;
    }

    /**
     * The column number for the top-left position.  0 based.
     *
     * @return the column number of the top-left corner
     */
    public short getCol1()
    {
        return field_2_col1;
    }

    /**
     * The column number for the top-left position.  0 based.
     *
     * @param field_2_col1 the column number of the top-left corner
     */
    public void setCol1( short field_2_col1 )
    {
        this.field_2_col1 = field_2_col1;
    }

    /**
     * The x offset within the top-left cell.  Range is from 0 to 1023.
     *
     * @return the x offset of the top-left corner
     */
    public short getDx1()
    {
        return field_3_dx1;
    }

    /**
     * The x offset within the top-left cell.  Range is from 0 to 1023.
     *
     * @param field_3_dx1 the x offset of the top-left corner
     */
    public void setDx1( short field_3_dx1 )
    {
        this.field_3_dx1 = field_3_dx1;
    }

    /**
     * The row number for the top-left corner of the shape.
     *
     * @return the row number of the top-left corner
     */
    public short getRow1()
    {
        return field_4_row1;
    }

    /**
     * The row number of the top-left corner of the shape.
     *
     * @param field_4_row1 the row number of the top-left corner
     */
    public void setRow1( short field_4_row1 )
    {
        this.field_4_row1 = field_4_row1;
    }

    /**
     * The y offset within the top-left corner of the current shape.
     *
     * @return the y offset of the top-left corner
     */
    public short getDy1()
    {
        return field_5_dy1;
    }

    /**
     * The y offset within the top-left corner of the current shape.
     *
     * @param field_5_dy1 the y offset of the top-left corner
     */
    public void setDy1( short field_5_dy1 )
    {
        shortRecord = false;
        this.field_5_dy1 = field_5_dy1;
    }

    /**
     * The column of the bottom right corner of this shape.
     *
     * @return the column of the bottom right corner
     */
    public short getCol2()
    {
        return field_6_col2;
    }

    /**
     * The column of the bottom right corner of this shape.
     *
     * @param field_6_col2 the column of the bottom right corner
     */
    public void setCol2( short field_6_col2 )
    {
        shortRecord = false;
        this.field_6_col2 = field_6_col2;
    }

    /**
     * The x offset withing the cell for the bottom-right corner of this shape.
     *
     * @return the x offset of the bottom-right corner
     */
    public short getDx2()
    {
        return field_7_dx2;
    }

    /**
     * The x offset withing the cell for the bottom-right corner of this shape.
     *
     * @param field_7_dx2 the x offset of the bottom-right corner
     */
    public void setDx2( short field_7_dx2 )
    {
        shortRecord = false;
        this.field_7_dx2 = field_7_dx2;
    }

    /**
     * The row number for the bottom-right corner of the current shape.
     *
     * @return the row number for the bottom-right corner
     */
    public short getRow2()
    {
        return field_8_row2;
    }

    /**
     * The row number for the bottom-right corner of the current shape.
     *
     * @param field_8_row2 the row number for the bottom-right corner
     */
    public void setRow2( short field_8_row2 )
    {
        shortRecord = false;
        this.field_8_row2 = field_8_row2;
    }

    /**
     * The y offset withing the cell for the bottom-right corner of this shape.
     *
     * @return the y offset of the bottom-right corner
     */
    public short getDy2()
    {
        return field_9_dy2;
    }

    /**
     * The y offset withing the cell for the bottom-right corner of this shape.
     *
     * @param field_9_dy2 the y offset of the bottom-right corner
     */
    public void setDy2( short field_9_dy2 )
    {
        shortRecord = false;
        this.field_9_dy2 = field_9_dy2;
    }

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

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

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        final Map<String,Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
        m.put("flag", this::getFlag);
        m.put("col1", this::getCol1);
        m.put("dx1", this::getDx1);
        m.put("row1", this::getRow1);
        m.put("dy1", this::getDy1);
        m.put("col2", this::getCol2);
        m.put("dx2", this::getDx2);
        m.put("row2", this::getRow2);
        m.put("dy2", this::getDy2);
        m.put("remainingData", this::getRemainingData);
        return Collections.unmodifiableMap(m);
    }

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

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