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

import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.util.Removal;

/**
 * A client anchor is attached to an excel worksheet.  It anchors against a
 * top-left and buttom-right cell.
 */
public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {

    public static final int MAX_COL = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
    public static final int MAX_ROW = SpreadsheetVersion.EXCEL97.getLastRowIndex();

    private EscherClientAnchorRecord _escherClientAnchor;

    public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
        this._escherClientAnchor = escherClientAnchorRecord;
    }

    /**
     * Creates a new client anchor and defaults all the anchor positions to 0.
     */
    public HSSFClientAnchor() {
    }

    /**
     * Creates a new client anchor and sets the top-left and bottom-right
     * coordinates of the anchor.
     * 
     * Note: Microsoft Excel seems to sometimes disallow 
     * higher y1 than y2 or higher x1 than x2, you might need to 
     * reverse them and draw shapes vertically or horizontally flipped! 
     *
     * @param dx1  the x coordinate within the first cell.
     * @param dy1  the y coordinate within the first cell.
     * @param dx2  the x coordinate within the second cell.
     * @param dy2  the y coordinate within the second cell.
     * @param col1 the column (0 based) of the first cell.
     * @param row1 the row (0 based) of the first cell.
     * @param col2 the column (0 based) of the second cell.
     * @param row2 the row (0 based) of the second cell.
     */
    public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) {
        super(dx1, dy1, dx2, dy2);

        checkRange(dx1, 0, 1023, "dx1");
        checkRange(dx2, 0, 1023, "dx2");
        checkRange(dy1, 0, 255, "dy1");
        checkRange(dy2, 0, 255, "dy2");
        checkRange(col1, 0, MAX_COL, "col1");
        checkRange(col2, 0, MAX_COL, "col2");
        checkRange(row1, 0, MAX_ROW, "row1");
        checkRange(row2, 0, MAX_ROW, "row2");

        setCol1((short) Math.min(col1, col2));
        setCol2((short) Math.max(col1, col2));
        setRow1(Math.min(row1, row2));
        setRow2(Math.max(row1, row2));

        if (col1 > col2){
            _isHorizontallyFlipped = true;
        }
        if (row1 > row2){
            _isVerticallyFlipped = true;
        }
    }

    /**
     * Calculates the height of a client anchor in points.
     *
     * @param sheet the sheet the anchor will be attached to
     * @return the shape height.
     */
    public float getAnchorHeightInPoints(HSSFSheet sheet) {
        int y1 = getDy1();
        int y2 = getDy2();
        int row1 = Math.min(getRow1(), getRow2());
        int row2 = Math.max(getRow1(), getRow2());

        float points = 0;
        if (row1 == row2) {
            points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2);
        } else {
            points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1);
            for (int i = row1 + 1; i < row2; i++) {
                points += getRowHeightInPoints(sheet, i);
            }
            points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2);
        }

        return points;
    }

    private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) {
        HSSFRow row = sheet.getRow(rowNum);
        if (row == null) {
            return sheet.getDefaultRowHeightInPoints();
        }
        return row.getHeightInPoints();
    }

    /**
     * @return the column(0 based) of the first cell.
     */
    public short getCol1() {
        return _escherClientAnchor.getCol1();
    }

    /**
     * @param col1 the column(0 based) of the first cell.
     */
    public void setCol1(short col1) {
        checkRange(col1, 0, MAX_COL, "col1");
        _escherClientAnchor.setCol1(col1);
    }

    /**
     * @param col1 0-based column of the first cell.
     */
    public void setCol1(int col1) {
        setCol1((short) col1);
    }

    /**
     * @return the column(0 based) of the first cell.
     */
    public short getCol2() {
        return _escherClientAnchor.getCol2();
    }

    /**
     * @param col2 the column(0 based) of the second cell.
     */
    public void setCol2(short col2) {
        checkRange(col2, 0, MAX_COL, "col2");
        _escherClientAnchor.setCol2(col2);
    }

    /**
     * @param col2 the column(0 based) of the second cell.
     */
    public void setCol2(int col2) {
        setCol2((short) col2);
    }

    /**
     * @return the row(0 based) of the first cell.
     */
    public int getRow1() {
        return unsignedValue(_escherClientAnchor.getRow1());
    }

    /**
     * @param row1 0-based row of the first cell.
     */
    public void setRow1(int row1) {
        checkRange(row1, 0, MAX_ROW, "row1");
        _escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue());
    }

    /**
     * @return the row(0 based) of the second cell.
     */
    public int getRow2() {
        return unsignedValue(_escherClientAnchor.getRow2());
    }

    /**
     * @param row2 the row(0 based) of the second cell.
     */
    public void setRow2(int row2) {
        checkRange(row2, 0, MAX_ROW, "row2");
        _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue());
    }

    /**
     * Sets the top-left and bottom-right coordinates of 
     * the anchor.
     * 
     * Note: Microsoft Excel seems to sometimes disallow 
     * higher y1 than y2 or higher x1 than x2, you might need to 
     * reverse them and draw shapes vertically or horizontally flipped! 
     *
     * @param x1   the x coordinate within the first cell.
     * @param y1   the y coordinate within the first cell.
     * @param x2   the x coordinate within the second cell.
     * @param y2   the y coordinate within the second cell.
     * @param col1 the column (0 based) of the first cell.
     * @param row1 the row (0 based) of the first cell.
     * @param col2 the column (0 based) of the second cell.
     * @param row2 the row (0 based) of the second cell.
     */
    public void setAnchor(short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2) {
        checkRange(getDx1(), 0, 1023, "dx1");
        checkRange(getDx2(), 0, 1023, "dx2");
        checkRange(getDy1(), 0, 255, "dy1");
        checkRange(getDy2(), 0, 255, "dy2");
        checkRange(getCol1(), 0, MAX_COL, "col1");
        checkRange(getCol2(), 0, MAX_COL, "col2");
        checkRange(getRow1(), 0, MAX_ROW, "row1");
        checkRange(getRow2(), 0, MAX_ROW, "row2");

        setCol1(col1);
        setRow1(row1);
        setDx1(x1);
        setDy1(y1);
        setCol2(col2);
        setRow2(row2);
        setDx2(x2);
        setDy2(y2);
    }

    public boolean isHorizontallyFlipped() {
        return _isHorizontallyFlipped;
    }

    public boolean isVerticallyFlipped() {
        return _isVerticallyFlipped;
    }

    @Override
    protected EscherRecord getEscherAnchor() {
        return _escherClientAnchor;
    }

    @Override
    protected void createEscherAnchor() {
        _escherClientAnchor = new EscherClientAnchorRecord();
    }

    /**
     * Gets the anchor type
     * Changed from returning an int to an enum in POI 3.14 beta 1.
     * @return the anchor type
     */
    @Override
    public AnchorType getAnchorType() {
        return AnchorType.byId(_escherClientAnchor.getFlag());
    }

    /**
     * Sets the anchor type
     * @param anchorType the anchor type to set
     * @since POI 3.14
     */
    @Override
    public void setAnchorType(AnchorType anchorType) {
        _escherClientAnchor.setFlag(anchorType.value);
    }
    /**
     * Sets the anchor type
     * @param anchorType the anchor type to set
     * @deprecated POI 3.15. Use {@link #setAnchorType(AnchorType)} instead.
     */
    @Removal(version="3.17")
    @Override
    public void setAnchorType(int anchorType) {
        _escherClientAnchor.setFlag((short) anchorType);
    }

    private void checkRange(int value, int minRange, int maxRange, String varName) {
        if (value < minRange || value > maxRange)
            throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange + ", but was: " + value);
    }

    /**
     * Given a 16-bit unsigned integer stored in a short, return the unsigned value.
     *
     * @param s A 16-bit value intended to be interpreted as an unsigned integer.
     * @return The value represented by <code>s</code>.
     */
    private static int unsignedValue(final short s) {
        return (s < 0 ? 0x10000 + s : s);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (obj == this)
            return true;
        if (obj.getClass() != getClass())
            return false;
        HSSFClientAnchor anchor = (HSSFClientAnchor) obj;

        return anchor.getCol1() == getCol1() && anchor.getCol2() == getCol2() && anchor.getDx1() == getDx1()
                && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() && anchor.getDy2() == getDy2()
                && anchor.getRow1() == getRow1() && anchor.getRow2() == getRow2() && anchor.getAnchorType() == getAnchorType();
    }

    @Override
    public int hashCode() {
        assert false : "hashCode not designed";
        return 42; // any arbitrary constant will do
      }

    @Override
    public int getDx1() {
        return _escherClientAnchor.getDx1();
    }

    @Override
    public void setDx1(int dx1) {
        _escherClientAnchor.setDx1(Integer.valueOf(dx1).shortValue());
    }

    @Override
    public int getDy1() {
        return _escherClientAnchor.getDy1();
    }

    @Override
    public void setDy1(int dy1) {
        _escherClientAnchor.setDy1(Integer.valueOf(dy1).shortValue());
    }

    @Override
    public int getDy2() {
        return _escherClientAnchor.getDy2();
    }

    @Override
    public void setDy2(int dy2) {
        _escherClientAnchor.setDy2(Integer.valueOf(dy2).shortValue());
    }

    @Override
    public int getDx2() {
        return _escherClientAnchor.getDx2();
    }

    @Override
    public void setDx2(int dx2) {
        _escherClientAnchor.setDx2(Integer.valueOf(dx2).shortValue());
    }
}
