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

import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndianOutput;

/**
 * Stores the row information for the sheet.
 *
 * @since 2.0-pre
 */
public final class RowRecord extends StandardRecord {
    public static final short sid = 0x0208;

    public static final int ENCODED_SIZE = 20;

    private static final int OPTION_BITS_ALWAYS_SET = 0x0100;
    //private static final int DEFAULT_HEIGHT_BIT = 0x8000;

    private static final BitField outlineLevel  = BitFieldFactory.getInstance(0x07);
    // bit 3 reserved
    private static final BitField collapsed     = BitFieldFactory.getInstance(0x10);
    private static final BitField zeroHeight    = BitFieldFactory.getInstance(0x20);
    private static final BitField badFontHeight = BitFieldFactory.getInstance(0x40);
    private static final BitField formatted     = BitFieldFactory.getInstance(0x80);

    private static final BitField xfIndex       = BitFieldFactory.getInstance(0xFFF);
    private static final BitField topBorder     = BitFieldFactory.getInstance(0x1000);
    private static final BitField bottomBorder  = BitFieldFactory.getInstance(0x2000);
    private static final BitField phoneticGuide = BitFieldFactory.getInstance(0x4000);
    // bit 15 is unused

    private int field_1_row_number;
    private int field_2_first_col;
    private int field_3_last_col; // plus 1
    private short field_4_height;
    private short field_5_optimize; // hint field for gui, can/should be set to zero

    // for generated sheets.
    private short field_6_reserved;
    /** 16 bit options flags */
    private int field_7_option_flags;
    /** 16 bit options flags */
    private int field_8_option_flags;   // only if isFormatted

    public RowRecord(RowRecord other) {
        super(other);
        field_1_row_number = other.field_1_row_number;
        field_2_first_col = other.field_2_first_col;
        field_3_last_col = other.field_3_last_col;
        field_4_height = other.field_4_height;
        field_5_optimize = other.field_5_optimize;
        field_6_reserved = other.field_6_reserved;
        field_7_option_flags = other.field_7_option_flags;
        field_8_option_flags = other.field_8_option_flags;
    }


    public RowRecord(int rowNumber) {
    	if(rowNumber < 0) {
    		throw new IllegalArgumentException("Invalid row number (" + rowNumber + ")");
    	}
        field_1_row_number = rowNumber;
        field_4_height = (short)0xFF;
        field_5_optimize = ( short ) 0;
        field_6_reserved = ( short ) 0;
        field_7_option_flags = OPTION_BITS_ALWAYS_SET; // seems necessary for outlining

        field_8_option_flags = ( short ) 0xf;
        setEmpty();
    }

    public RowRecord(RecordInputStream in) {
        field_1_row_number   = in.readUShort();
    	if(field_1_row_number < 0) {
    		throw new IllegalArgumentException("Invalid row number " + field_1_row_number + " found in InputStream");
    	}
        field_2_first_col    = in.readShort();
        field_3_last_col     = in.readShort();
        field_4_height       = in.readShort();
        field_5_optimize     = in.readShort();
        field_6_reserved     = in.readShort();
        field_7_option_flags = in.readShort();
        field_8_option_flags = in.readShort();
    }

    /**
     * Updates the firstCol and lastCol fields to the reserved value (-1)
     * to signify that this row is empty
     */
    public void setEmpty() {
        field_2_first_col = 0;
        field_3_last_col = 0;
    }
    public boolean isEmpty() {
        return (field_2_first_col | field_3_last_col) == 0;
    }

    /**
     * set the logical row number for this row (0 based index)
     * @param row - the row number
     */
    public void setRowNumber(int row) {
        field_1_row_number = row;
    }

    /**
     * set the logical col number for the first cell this row (0 based index)
     * @param col - the col number
     */
    public void setFirstCol(int col) {
        field_2_first_col = col;
    }

    /**
     * @param col - one past the zero-based index to the last cell in this row
     */
    public void setLastCol(int col) {
        field_3_last_col = col;
    }

    /**
     * set the height of the row
     * @param height of the row
     */
    public void setHeight(short height) {
        field_4_height = height;
    }

    /**
     * set whether to optimize or not (set to 0)
     * @param optimize (set to 0)
     */
    public void setOptimize(short optimize) {
        field_5_optimize = optimize;
    }

    // option bitfields

    /**
     * set the outline level of this row
     * @param ol - the outline level
     */
    public void setOutlineLevel(short ol) {
        field_7_option_flags = outlineLevel.setValue(field_7_option_flags, ol);
    }

    /**
     * set whether or not to collapse this row
     * @param c - collapse or not
     */
    public void setColapsed(boolean c) {
        field_7_option_flags = collapsed.setBoolean(field_7_option_flags, c);
    }

    /**
     * set whether or not to display this row with 0 height
     * @param z  height is zero or not.
     */
    public void setZeroHeight(boolean z) {
        field_7_option_flags = zeroHeight.setBoolean(field_7_option_flags, z);
    }

    /**
     * set whether the font and row height are not compatible
     * @param  f  true if they aren't compatible (damn not logic)
     */
    public void setBadFontHeight(boolean f) {
        field_7_option_flags = badFontHeight.setBoolean(field_7_option_flags, f);
    }

    /**
     * set whether the row has been formatted (even if its got all blank cells)
     * @param f  formatted or not
     */
    public void setFormatted(boolean f) {
        field_7_option_flags = formatted.setBoolean(field_7_option_flags, f);
    }

    // end bitfields

    /**
     * if the row is formatted then this is the index to the extended format record
     * @see org.apache.poi.hssf.record.ExtendedFormatRecord
     * @param index to the XF record
     */
    public void setXFIndex(short index) {
    	field_8_option_flags = xfIndex.setValue(field_8_option_flags, index);
    }

    /**
     * bit that specifies whether any cell in the row has a thick top border, or any
     * cell in the row directly above the current row has a thick bottom border.
     * @param f has thick top border
     */
    public void setTopBorder(boolean f) {
    	field_8_option_flags = topBorder.setBoolean(field_8_option_flags, f);
    }

    /**
     * A bit that specifies whether any cell in the row has a medium or thick
     * bottom border, or any cell in the row directly below the current row has
     * a medium or thick top border.
     * @param f has thick bottom border
     */
    public void setBottomBorder(boolean f) {
    	field_8_option_flags = bottomBorder.setBoolean(field_8_option_flags, f);
    }

    /**
     * A bit that specifies whether the phonetic guide feature is enabled for
     * any cell in this row.
     * @param f use phoenetic guide
     */
    public void setPhoeneticGuide(boolean f) {
    	field_8_option_flags = phoneticGuide.setBoolean(field_8_option_flags, f);
    }

    /**
     * get the logical row number for this row (0 based index)
     * @return row - the row number
     */
    public int getRowNumber() {
        return field_1_row_number;
    }

    /**
     * get the logical col number for the first cell this row (0 based index)
     * @return col - the col number
     */
    public int getFirstCol() {
        return field_2_first_col;
    }

    /**
     * get the logical col number for the last cell this row (0 based index), plus one
     * @return col - the last col index + 1
     */
    public int getLastCol() {
        return field_3_last_col;
    }

    /**
     * get the height of the row
     * @return height of the row
     */
    public short getHeight() {
        return field_4_height;
    }

    /**
     * get whether to optimize or not (set to 0)
     * @return optimize (set to 0)
     */
    public short getOptimize() {
        return field_5_optimize;
    }

    /**
     * gets the option bitmask.  (use the individual bit setters that refer to this
     * method)
     * @return options - the bitmask
     */
    public short getOptionFlags() {
        return (short)field_7_option_flags;
    }

    // option bitfields

    /**
     * get the outline level of this row
     * @return ol - the outline level
     * @see #getOptionFlags()
     */
    public short getOutlineLevel() {
        return (short)outlineLevel.getValue(field_7_option_flags);
    }

    /**
     * get whether or not to colapse this row
     * @return c - colapse or not
     * @see #getOptionFlags()
     */
    public boolean getColapsed() {
        return (collapsed.isSet(field_7_option_flags));
    }

    /**
     * get whether or not to display this row with 0 height
     * @return - z height is zero or not.
     * @see #getOptionFlags()
     */
    public boolean getZeroHeight() {
        return zeroHeight.isSet(field_7_option_flags);
    }

    /**
     * get whether the font and row height are not compatible
     * @return - f -true if they aren't compatible (damn not logic)
     * @see #getOptionFlags()
     */
    public boolean getBadFontHeight() {
        return badFontHeight.isSet(field_7_option_flags);
    }

    /**
     * get whether the row has been formatted (even if its got all blank cells)
     * @return formatted or not
     * @see #getOptionFlags()
     */
    public boolean getFormatted() {
        return formatted.isSet(field_7_option_flags);
    }

    // end bitfields

    /**
     * gets the 2nd option bitmask.  (use the individual bit setters that refer to this
     * method)
     * @return options - the bitmask
     */
    public short getOptionFlags2() {
        return (short)field_8_option_flags;
    }

    /**
     * if the row is formatted then this is the index to the extended format record
     * @see org.apache.poi.hssf.record.ExtendedFormatRecord
     * @return index to the XF record or bogus value (undefined) if isn't formatted
     */
    public short getXFIndex() {
    	return xfIndex.getShortValue((short)field_8_option_flags);
    }

    /**
     * A bit that specifies whether any cell in the row has a thick top border, or any
     * cell in the row directly above the current row has a thick bottom border.
     * @return has cells with a thick top border
     */
    public boolean getTopBorder() {
    	return topBorder.isSet(field_8_option_flags);
    }

    /**
     * A bit that specifies whether any cell in the row has a medium or thick bottom border,
     * or any cell in the row directly below the current row has a medium or thick top border.
     * @return has cells with a thick bottom border
     */
    public boolean getBottomBorder() {
    	return bottomBorder.isSet(field_8_option_flags);
    }

    /**
     * A bit that specifies whether the phonetic guide feature is enabled for
     * any cell in this row.
     * @return has phoentic guide
     */
    public boolean getPhoeneticGuide() {
    	return phoneticGuide.isSet(field_8_option_flags);
    }

    public void serialize(LittleEndianOutput out) {
        out.writeShort(getRowNumber());
        out.writeShort(getFirstCol() == -1 ? (short)0 : getFirstCol());
        out.writeShort(getLastCol() == -1 ? (short)0 : getLastCol());
        out.writeShort(getHeight());
        out.writeShort(getOptimize());
        out.writeShort(field_6_reserved);
        out.writeShort(getOptionFlags());
        out.writeShort(getOptionFlags2());
    }

    protected int getDataSize() {
        return ENCODED_SIZE - 4;
    }

    public short getSid() {
        return sid;
    }

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

    @Override
    public HSSFRecordTypes getGenericRecordType() {
        return HSSFRecordTypes.ROW;
    }

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        final Map<String,Supplier<?>> m = new LinkedHashMap<>();
        m.put("rowNumber", this::getRowNumber);
        m.put("firstCol", this::getFirstCol);
        m.put("lastCol", this::getLastCol);
        m.put("height", this::getHeight);
        m.put("optimized", this::getOptimize);
        m.put("reserved", () -> field_6_reserved);
        m.put("options", getBitsAsString(this::getOptionFlags,
            new BitField[]{collapsed,zeroHeight,badFontHeight,formatted},
            new String[]{"COLAPSED","ZERO_HEIGHT","BAD_FONT_HEIGHT","FORMATTED"}));
        m.put("outlineLevel", this::getOutlineLevel);
        m.put("optionFlags2", getBitsAsString(this::getOptionFlags2,
            new BitField[]{topBorder, bottomBorder, phoneticGuide},
            new String[]{"TOP_BORDER","BOTTOM_BORDER","PHOENETIC_GUIDE"}));
        m.put("xfIndex", this::getXFIndex);
        return Collections.unmodifiableMap(m);
    }
}
