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

import org.apache.poi.hssf.record.ArrayRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SharedFormulaRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.ptg.ExpPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.FormulaError;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.RecordFormatException;

/**
 * The formula record aggregate is used to join together the formula record and it's
 * (optional) string record and (optional) Shared Formula Record (template reads, excel optimization).
 */
public final class FormulaRecordAggregate extends RecordAggregate implements CellValueRecordInterface {

    private final FormulaRecord _formulaRecord;
    private SharedValueManager _sharedValueManager;
    /** caches the calculated result of the formula */
    private StringRecord _stringRecord;
    private SharedFormulaRecord _sharedFormulaRecord;

    /**
     * @param stringRec may be <code>null</code> if this formula does not have a cached text
     * value.
     * @param svm the {@link SharedValueManager} for the current sheet
     */
    public FormulaRecordAggregate(FormulaRecord formulaRec, StringRecord stringRec, SharedValueManager svm) {
        if (svm == null) {
            throw new IllegalArgumentException("sfm must not be null");
        }
        if (formulaRec.hasCachedResultString()) {
            if (stringRec == null) {
                throw new RecordFormatException("Formula record flag is set but String record was not found");
            }
            _stringRecord = stringRec;
        } else {
            // Usually stringRec is null here (in agreement with what the formula rec says).
            // In the case where an extra StringRecord is erroneously present, Excel (2007)
            // ignores it (see bug 46213).
            _stringRecord = null;
        }

        _formulaRecord = formulaRec;
        _sharedValueManager = svm;
        if (formulaRec.isSharedFormula()) {
            CellReference firstCell = formulaRec.getFormula().getExpReference();
            if (firstCell == null) {
                handleMissingSharedFormulaRecord(formulaRec);
            } else {
                _sharedFormulaRecord = svm.linkSharedFormulaRecord(firstCell, this);
            }
        }
    }

    /**
     * Sometimes the shared formula flag "seems" to be erroneously set (because the corresponding
     * {@link SharedFormulaRecord} does not exist). Normally this would leave no way of determining
     * the {@link Ptg} tokens for the formula.  However as it turns out in these
     * cases, Excel encodes the unshared {@link Ptg} tokens in the right place (inside the {@link
     * FormulaRecord}).  So the the only thing that needs to be done is to ignore the erroneous
     * shared formula flag.<br>
     *
     * This method may also be used for setting breakpoints to help diagnose issues regarding the
     * abnormally-set 'shared formula' flags.
     * (see TestValueRecordsAggregate.testSpuriousSharedFormulaFlag()).<p>
     */
    private static void handleMissingSharedFormulaRecord(FormulaRecord formula) {
        // make sure 'unshared' formula is actually available
        Ptg firstToken = formula.getParsedExpression()[0];
        if (firstToken instanceof ExpPtg) {
            throw new RecordFormatException(
                    "SharedFormulaRecord not found for FormulaRecord with (isSharedFormula=true)");
        }
        // could log an info message here since this is a fairly unusual occurrence.
        formula.setSharedFormula(false); // no point leaving the flag erroneously set
    }

    public FormulaRecord getFormulaRecord() {
        return _formulaRecord;
    }

    /**
     * debug only
     * TODO - encapsulate
     */
    public StringRecord getStringRecord() {
        return _stringRecord;
    }

    public short getXFIndex() {
        return _formulaRecord.getXFIndex();
    }

    public void setXFIndex(short xf) {
        _formulaRecord.setXFIndex(xf);
    }

    public void setColumn(short col) {
        _formulaRecord.setColumn(col);
    }

    public void setRow(int row) {
        _formulaRecord.setRow(row);
    }

    public short getColumn() {
        return _formulaRecord.getColumn();
    }

    public int getRow() {
        return _formulaRecord.getRow();
    }

    public String toString() {
        return _formulaRecord.toString();
    }

    @Override
    public void visitContainedRecords(RecordVisitor rv) {
         rv.visitRecord(_formulaRecord);
         Record sharedFormulaRecord = _sharedValueManager.getRecordForFirstCell(this);
         if (sharedFormulaRecord != null) {
             rv.visitRecord(sharedFormulaRecord);
         }
         if (_formulaRecord.hasCachedResultString() && _stringRecord != null) {
             rv.visitRecord(_stringRecord);
         }
    }

    public String getStringValue() {
        if(_stringRecord==null) {
            return null;
        }
        return _stringRecord.getString();
    }

    public void setCachedStringResult(String value) {

        // Save the string into a String Record, creating one if required
        if(_stringRecord == null) {
            _stringRecord = new StringRecord();
        }
        _stringRecord.setString(value);
        if (value.length() < 1) {
            _formulaRecord.setCachedResultTypeEmptyString();
        } else {
            _formulaRecord.setCachedResultTypeString();
        }
    }
    public void setCachedBooleanResult(boolean value) {
        _stringRecord = null;
        _formulaRecord.setCachedResultBoolean(value);
    }
    public void setCachedErrorResult(int errorCode) {
        _stringRecord = null;
        _formulaRecord.setCachedResultErrorCode(errorCode);
    }
    public void setCachedErrorResult(FormulaError error) {
        setCachedErrorResult(error.getCode());
    }
    public void setCachedDoubleResult(double value) {
        _stringRecord = null;
        _formulaRecord.setValue(value);
    }

    public Ptg[] getFormulaTokens() {
        if (_sharedFormulaRecord != null) {
            return _sharedFormulaRecord.getFormulaTokens(_formulaRecord);
        }
        CellReference expRef = _formulaRecord.getFormula().getExpReference();
        if (expRef != null) {
            ArrayRecord arec = _sharedValueManager.getArrayRecord(expRef.getRow(), expRef.getCol());
            return arec.getFormulaTokens();
        }
        return _formulaRecord.getParsedExpression();
    }

    /**
     * Also checks for a related shared formula and unlinks it if found
     */
    public void setParsedExpression(Ptg[] ptgs) {
        notifyFormulaChanging();
        _formulaRecord.setParsedExpression(ptgs);
    }

    public void unlinkSharedFormula() {
        SharedFormulaRecord sfr = _sharedFormulaRecord;
        if (sfr == null) {
            throw new IllegalStateException("Formula not linked to shared formula");
        }
        Ptg[] ptgs = sfr.getFormulaTokens(_formulaRecord);
        _formulaRecord.setParsedExpression(ptgs);
        //Now its not shared!
        _formulaRecord.setSharedFormula(false);
        _sharedFormulaRecord = null;
    }
    /**
     * Should be called by any code which is either deleting this formula cell, or changing
     * its type.  This method gives the aggregate a chance to unlink any shared formula
     * that may be involved with this cell formula.
     */
    public void notifyFormulaChanging() {
        if (_sharedFormulaRecord != null) {
            _sharedValueManager.unlink(_sharedFormulaRecord);
        }
    }
    public boolean isPartOfArrayFormula() {
        if (_sharedFormulaRecord != null) {
            return false;
        }
        CellReference expRef = _formulaRecord.getFormula().getExpReference();
        ArrayRecord arec = expRef == null ? null : _sharedValueManager.getArrayRecord(expRef.getRow(), expRef.getCol());
        return arec != null;
    }

    public CellRangeAddress getArrayFormulaRange() {
        if (_sharedFormulaRecord != null) {
            throw new IllegalStateException("not an array formula cell.");
        }
        CellReference expRef = _formulaRecord.getFormula().getExpReference();
        if (expRef == null) {
            throw new IllegalStateException("not an array formula cell.");
        }
        ArrayRecord arec = _sharedValueManager.getArrayRecord(expRef.getRow(), expRef.getCol());
        if (arec == null) {
            throw new IllegalStateException("ArrayRecord was not found for the locator " + expRef.formatAsString());
        }
        CellRangeAddress8Bit a = arec.getRange();
        return new CellRangeAddress(a.getFirstRow(), a.getLastRow(), a.getFirstColumn(),a.getLastColumn());
    }

    public void setArrayFormula(CellRangeAddress r, Ptg[] ptgs) {

        ArrayRecord arr = new ArrayRecord(Formula.create(ptgs), new CellRangeAddress8Bit(r.getFirstRow(), r.getLastRow(), r.getFirstColumn(), r.getLastColumn()));
        _sharedValueManager.addArrayRecord(arr);
    }
    /**
     * Removes an array formula
     * @return the range of the array formula containing the specified cell. Never <code>null</code>
     */
    public CellRangeAddress removeArrayFormula(int rowIndex, int columnIndex) {
        CellRangeAddress8Bit a = _sharedValueManager.removeArrayFormula(rowIndex, columnIndex);
        // at this point FormulaRecordAggregate#isPartOfArrayFormula() should return false
        _formulaRecord.setParsedExpression(null);
        return new CellRangeAddress(a.getFirstRow(), a.getLastRow(), a.getFirstColumn(), a.getLastColumn());
    }
}
