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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.cf.BorderFormatting;
import org.apache.poi.hssf.record.cf.FontFormatting;
import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianOutput;

/**
 * Conditional Formatting Rules. This can hold old-style rules
 *
 *
 * <p>This is for the older-style Excel conditional formattings,
 *  new-style (Excel 2007+) also make use of {@link CFRule12Record}
 *  for their rules.</p>
 */
public abstract class CFRuleBase extends StandardRecord {
    // FIXME: Merge with org.apache.poi.ss.usermodel.ComparisonOperator and rewrite as an enum
    public interface ComparisonOperator {
        byte NO_COMPARISON = 0;
        byte BETWEEN       = 1;
        byte NOT_BETWEEN   = 2;
        byte EQUAL         = 3;
        byte NOT_EQUAL     = 4;
        byte GT            = 5;
        byte LT            = 6;
        byte GE            = 7;
        byte LE            = 8;
        byte max_operator  = 8;
    }

    // The only kinds that CFRuleRecord handles
    public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
    public static final byte CONDITION_TYPE_FORMULA = 2;
    // These are CFRule12Rule only
    public static final byte CONDITION_TYPE_COLOR_SCALE = 3;
    public static final byte CONDITION_TYPE_DATA_BAR = 4;
    public static final byte CONDITION_TYPE_FILTER = 5;
    public static final byte CONDITION_TYPE_ICON_SET = 6;

    public static final int TEMPLATE_CELL_VALUE = 0x0000;
    public static final int TEMPLATE_FORMULA = 0x0001;
    public static final int TEMPLATE_COLOR_SCALE_FORMATTING = 0x0002;
    public static final int TEMPLATE_DATA_BAR_FORMATTING = 0x0003;
    public static final int TEMPLATE_ICON_SET_FORMATTING = 0x0004;
    public static final int TEMPLATE_FILTER = 0x0005;
    public static final int TEMPLATE_UNIQUE_VALUES = 0x0007;
    public static final int TEMPLATE_CONTAINS_TEXT = 0x0008;
    public static final int TEMPLATE_CONTAINS_BLANKS = 0x0009;
    public static final int TEMPLATE_CONTAINS_NO_BLANKS = 0x000A;
    public static final int TEMPLATE_CONTAINS_ERRORS = 0x000B;
    public static final int TEMPLATE_CONTAINS_NO_ERRORS = 0x000C;
    public static final int TEMPLATE_TODAY = 0x000F;
    public static final int TEMPLATE_TOMORROW = 0x0010;
    public static final int TEMPLATE_YESTERDAY = 0x0011;
    public static final int TEMPLATE_LAST_7_DAYS = 0x0012;
    public static final int TEMPLATE_LAST_MONTH = 0x0013;
    public static final int TEMPLATE_NEXT_MONTH = 0x0014;
    public static final int TEMPLATE_THIS_WEEK = 0x0015;
    public static final int TEMPLATE_NEXT_WEEK = 0x0016;
    public static final int TEMPLATE_LAST_WEEK = 0x0017;
    public static final int TEMPLATE_THIS_MONTH = 0x0018;
    public static final int TEMPLATE_ABOVE_AVERAGE = 0x0019;
    public static final int TEMPLATE_BELOW_AVERAGE = 0x001A;
    public static final int TEMPLATE_DUPLICATE_VALUES = 0x001B;
    public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D;
    public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E;

    protected static final Logger LOG = LogManager.getLogger(CFRuleBase.class);

    static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
    static final BitField alignHor         = bf(0x00000001); // 0 = Horizontal alignment modified
    static final BitField alignVer         = bf(0x00000002); // 0 = Vertical alignment modified
    static final BitField alignWrap        = bf(0x00000004); // 0 = Text wrapped flag modified
    static final BitField alignRot         = bf(0x00000008); // 0 = Text rotation modified
    static final BitField alignJustLast    = bf(0x00000010); // 0 = Justify last line flag modified
    static final BitField alignIndent      = bf(0x00000020); // 0 = Indentation modified
    static final BitField alignShrin       = bf(0x00000040); // 0 = Shrink to fit flag modified
    static final BitField mergeCell        = bf(0x00000080); // Normally 1, 0 = Merge Cell flag modified
    static final BitField protLocked       = bf(0x00000100); // 0 = Cell locked flag modified
    static final BitField protHidden       = bf(0x00000200); // 0 = Cell hidden flag modified
    static final BitField bordLeft         = bf(0x00000400); // 0 = Left border style and colour modified
    static final BitField bordRight        = bf(0x00000800); // 0 = Right border style and colour modified
    static final BitField bordTop          = bf(0x00001000); // 0 = Top border style and colour modified
    static final BitField bordBot          = bf(0x00002000); // 0 = Bottom border style and colour modified
    static final BitField bordTlBr         = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified
    static final BitField bordBlTr         = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified
    static final BitField pattStyle        = bf(0x00010000); // 0 = Pattern style modified
    static final BitField pattCol          = bf(0x00020000); // 0 = Pattern colour modified
    static final BitField pattBgCol        = bf(0x00040000); // 0 = Pattern background colour modified
    static final BitField notUsed2         = bf(0x00380000); // Always 111 (ifmt / ifnt / 1)
    static final BitField undocumented     = bf(0x03C00000); // Undocumented bits
    static final BitField fmtBlockBits     = bf(0x7C000000); // Bits: font,align,bord,patt,prot
    static final BitField font             = bf(0x04000000); // 1 = Record contains font formatting block
    static final BitField align            = bf(0x08000000); // 1 = Record contains alignment formatting block
    static final BitField bord             = bf(0x10000000); // 1 = Record contains border formatting block
    static final BitField patt             = bf(0x20000000); // 1 = Record contains pattern formatting block
    static final BitField prot             = bf(0x40000000); // 1 = Record contains protection formatting block
    static final BitField alignTextDir     = bf(0x80000000); // 0 = Text direction modified

    private static BitField bf(int i) {
        return BitFieldFactory.getInstance(i);
    }


    private byte condition_type;
    private byte comparison_operator;

    protected int formatting_options;
    // TODO Decode this properly
    protected short formatting_not_used;

    protected FontFormatting _fontFormatting;
    protected BorderFormatting _borderFormatting;
    protected PatternFormatting _patternFormatting;

    private Formula formula1;
    private Formula formula2;

    /**
     * Creates new CFRuleRecord
     *
     * @param conditionType the condition type
     * @param comparisonOperation the comparison operation
     */
    protected CFRuleBase(byte conditionType, byte comparisonOperation) {
        setConditionType(conditionType);
        setComparisonOperation(comparisonOperation);
        formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY);
        formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY);
    }

    protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
        this(conditionType, comparisonOperation);
        this.formula1 = Formula.create(formula1);
        this.formula2 = Formula.create(formula2);
    }

    protected CFRuleBase() {}

    protected CFRuleBase(CFRuleBase other) {
        super(other);
        setConditionType(other.getConditionType());
        setComparisonOperation(other.getComparisonOperation());
        formatting_options = other.formatting_options;
        formatting_not_used = other.formatting_not_used;
        _fontFormatting = (!other.containsFontFormattingBlock()) ? null : other.getFontFormatting().copy();
        _borderFormatting = (!other.containsBorderFormattingBlock()) ? null : other.getBorderFormatting().copy();
        _patternFormatting = (!other.containsPatternFormattingBlock()) ? null : other.getPatternFormatting().copy();
        formula1 = other.getFormula1().copy();
        formula2 = other.getFormula2().copy();
    }

    protected int readFormatOptions(RecordInputStream in) {
        formatting_options = in.readInt();
        formatting_not_used = in.readShort();

        int len = 6;

        if (containsFontFormattingBlock()) {
            _fontFormatting = new FontFormatting(in);
            len += _fontFormatting.getDataLength();
        }

        if (containsBorderFormattingBlock()) {
            _borderFormatting = new BorderFormatting(in);
            len += _borderFormatting.getDataLength();
        }

        if (containsPatternFormattingBlock()) {
            _patternFormatting = new PatternFormatting(in);
            len += _patternFormatting.getDataLength();
        }

        return len;
    }

    public byte getConditionType() {
        return condition_type;
    }
    protected void setConditionType(byte condition_type) {
        if ((this instanceof CFRuleRecord)) {
            if (!(condition_type == CONDITION_TYPE_CELL_VALUE_IS ||
                condition_type == CONDITION_TYPE_FORMULA)) {
                throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types");
            }
        }
        this.condition_type = condition_type;
    }

    public void setComparisonOperation(byte operation) {
        if (operation < 0 || operation > ComparisonOperator.max_operator)
            throw new IllegalArgumentException(
                    "Valid operators are only in the range 0 to " +ComparisonOperator.max_operator);

        this.comparison_operator = operation;
    }
    public byte getComparisonOperation() {
        return comparison_operator;
    }

    public boolean containsFontFormattingBlock() {
        return getOptionFlag(font);
    }
    public void setFontFormatting(FontFormatting fontFormatting) {
        _fontFormatting = fontFormatting;
        setOptionFlag(fontFormatting != null, font);
    }
    public FontFormatting getFontFormatting() {
        if( containsFontFormattingBlock()) {
            return _fontFormatting;
        }
        return null;
    }

    public boolean containsAlignFormattingBlock() {
        return getOptionFlag(align);
    }
    public void setAlignFormattingUnchanged() {
        setOptionFlag(false,align);
    }

    public boolean containsBorderFormattingBlock() {
        return getOptionFlag(bord);
    }
    public void setBorderFormatting(BorderFormatting borderFormatting) {
        _borderFormatting = borderFormatting;
        setOptionFlag(borderFormatting != null, bord);
    }
    public BorderFormatting getBorderFormatting() {
        if( containsBorderFormattingBlock()) {
            return _borderFormatting;
        }
        return null;
    }

    public boolean containsPatternFormattingBlock() {
        return getOptionFlag(patt);
    }
    public void setPatternFormatting(PatternFormatting patternFormatting) {
        _patternFormatting = patternFormatting;
        setOptionFlag(patternFormatting!=null, patt);
    }
    public PatternFormatting getPatternFormatting() {
        if( containsPatternFormattingBlock())
        {
            return _patternFormatting;
        }
        return null;
    }

    public boolean containsProtectionFormattingBlock() {
        return getOptionFlag(prot);
    }
    public void setProtectionFormattingUnchanged() {
        setOptionFlag(false,prot);
    }

    /**
     * get the option flags
     *
     * @return bit mask
     */
    public int getOptions() {
        return formatting_options;
    }

    private boolean isModified(BitField field) {
        return !field.isSet(formatting_options);
    }
    private void setModified(boolean modified, BitField field) {
        formatting_options = field.setBoolean(formatting_options, !modified);
    }

    public boolean isLeftBorderModified() {
        return isModified(bordLeft);
    }
    public void setLeftBorderModified(boolean modified) {
        setModified(modified,bordLeft);
    }

    public boolean isRightBorderModified() {
        return isModified(bordRight);
    }
    public void setRightBorderModified(boolean modified)
    {
        setModified(modified,bordRight);
    }

    public boolean isTopBorderModified() {
        return isModified(bordTop);
    }
    public void setTopBorderModified(boolean modified) {
        setModified(modified,bordTop);
    }

    public boolean isBottomBorderModified() {
        return isModified(bordBot);
    }
    public void setBottomBorderModified(boolean modified) {
        setModified(modified,bordBot);
    }

    public boolean isTopLeftBottomRightBorderModified() {
        return isModified(bordTlBr);
    }
    public void setTopLeftBottomRightBorderModified(boolean modified) {
        setModified(modified,bordTlBr);
    }

    public boolean isBottomLeftTopRightBorderModified() {
        return isModified(bordBlTr);
    }
    public void setBottomLeftTopRightBorderModified(boolean modified) {
        setModified(modified,bordBlTr);
    }

    public boolean isPatternStyleModified() {
        return isModified(pattStyle);
    }
    public void setPatternStyleModified(boolean modified) {
        setModified(modified,pattStyle);
    }

    public boolean isPatternColorModified() {
        return isModified(pattCol);
    }
    public void setPatternColorModified(boolean modified) {
        setModified(modified,pattCol);
    }

    public boolean isPatternBackgroundColorModified() {
        return isModified(pattBgCol);
    }
    public void setPatternBackgroundColorModified(boolean modified) {
        setModified(modified,pattBgCol);
    }

    private boolean getOptionFlag(BitField field) {
        return field.isSet(formatting_options);
    }
    private void setOptionFlag(boolean flag, BitField field) {
        formatting_options = field.setBoolean(formatting_options, flag);
    }

    protected int getFormattingBlockSize() {
        return 6 +
          (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
          (containsBorderFormattingBlock()?8:0)+
          (containsPatternFormattingBlock()?4:0);
    }
    protected void serializeFormattingBlock(LittleEndianOutput out) {
        out.writeInt(formatting_options);
        out.writeShort(formatting_not_used);

        if (containsFontFormattingBlock()) {
            byte[] fontFormattingRawRecord  = _fontFormatting.getRawRecord();
            out.write(fontFormattingRawRecord);
        }

        if (containsBorderFormattingBlock()) {
            _borderFormatting.serialize(out);
        }

        if (containsPatternFormattingBlock()) {
            _patternFormatting.serialize(out);
        }
    }

    /**
     * get the stack of the 1st expression as a list
     *
     * @return list of tokens (casts stack to a list and returns it!)
     * this method can return null is we are unable to create Ptgs from
     *	 existing excel file
     * callers should check for null!
     */
    public Ptg[] getParsedExpression1() {
        return formula1.getTokens();
    }
    public void setParsedExpression1(Ptg[] ptgs) {
        formula1 = Formula.create(ptgs);
    }
    protected Formula getFormula1() {
        return formula1;
    }
    protected void setFormula1(Formula formula1) {
        this.formula1 = formula1;
    }

    /**
     * get the stack of the 2nd expression as a list
     *
     * @return array of {@link Ptg}s, possibly <code>null</code>
     */
    public Ptg[] getParsedExpression2() {
        return Formula.getTokens(formula2);
    }
    public void setParsedExpression2(Ptg[] ptgs) {
        formula2 = Formula.create(ptgs);
    }
    protected Formula getFormula2() {
        return formula2;
    }
    protected void setFormula2(Formula formula2) {
        this.formula2 = formula2;
    }

    /**
     * @param formula must not be <code>null</code>
     * @return encoded size of the formula tokens (does not include 2 bytes for ushort length)
     */
    protected static int getFormulaSize(Formula formula) {
        return formula.getEncodedTokenSize();
    }

    /**
     * TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea
     * this call will produce the wrong results if the formula contains any cell references
     * One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int)
     * Note - two extra parameters (rowIx &amp; colIx) will be required. They probably come from one of the Region objects.
     *
     * @param formula  The formula to parse, excluding the leading equals sign.
     * @param sheet  The sheet that the formula is on.
     * @return <code>null</code> if <tt>formula</tt> was null.
     */
    public static Ptg[] parseFormula(String formula, HSSFSheet sheet) {
        if(formula == null) {
            return null;
        }
        int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
        return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex);
    }

    @Override
    public abstract CFRuleBase copy();

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        return GenericRecordUtil.getGenericProperties(
            "conditionType", this::getConditionType,
            "comparisonOperation", this::getComparisonOperation,
            "formattingOptions", this::getOptions,
            "formattingNotUsed", () -> formatting_not_used,
            "fontFormatting", this::getFontFormatting,
            "borderFormatting", this::getBorderFormatting,
            "patternFormatting", this::getPatternFormatting,
            "formula1", this::getFormula1,
            "formula2", this::getFormula2
        );
    }
}
