/* ====================================================================
   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.
 *
 * @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);
    }
}
