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

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheetRange;
import org.apache.poi.ss.formula.constant.ErrorConstant;
import org.apache.poi.ss.formula.eval.AreaEval;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.ExternalNameEval;
import org.apache.poi.ss.formula.eval.FunctionNameEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellReference.NameType;

/**
 * Contains all the contextual information required to evaluate an operation
 * within a formula
 *
 * For POI internal use only
 */
public final class OperationEvaluationContext {
    public static final FreeRefFunction UDF = UserDefinedFunction.instance;
    private final EvaluationWorkbook _workbook;
    private final int _sheetIndex;
    private final int _rowIndex;
    private final int _columnIndex;
    private final EvaluationTracker _tracker;
    private final WorkbookEvaluator _bookEvaluator;
    private final boolean _isSingleValue;
    private boolean _isInArrayContext;

    public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum,
            int srcColNum, EvaluationTracker tracker) {
        this(bookEvaluator, workbook, sheetIndex, srcRowNum, srcColNum, tracker, true);
    }

    public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum,
            int srcColNum, EvaluationTracker tracker, boolean isSingleValue) {
        _bookEvaluator = bookEvaluator;
        _workbook = workbook;
        _sheetIndex = sheetIndex;
        _rowIndex = srcRowNum;
        _columnIndex = srcColNum;
        _tracker = tracker;
        _isSingleValue = isSingleValue;
    }

    public boolean isArraymode(){
        return _isInArrayContext;
    }
    public void setArrayMode(boolean value){
        _isInArrayContext = value;
    }

    public EvaluationWorkbook getWorkbook() {
        return _workbook;
    }

    public int getRowIndex() {
        return _rowIndex;
    }

    public int getColumnIndex() {
        return _columnIndex;
    }

    SheetRangeEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
        return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
    }
    SheetRangeEvaluator createExternSheetRefEvaluator(String firstSheetName, String lastSheetName, int externalWorkbookNumber) {
        ExternalSheet externalSheet = _workbook.getExternalSheet(firstSheetName, lastSheetName, externalWorkbookNumber);
        return createExternSheetRefEvaluator(externalSheet);
    }
    SheetRangeEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
        ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
        return createExternSheetRefEvaluator(externalSheet);
    }
    SheetRangeEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
        WorkbookEvaluator targetEvaluator;
        int otherFirstSheetIndex;
        int otherLastSheetIndex = -1;
        if (externalSheet == null || externalSheet.getWorkbookName() == null) {
            // sheet is in same workbook
            targetEvaluator = _bookEvaluator;
            if(externalSheet == null) {
                otherFirstSheetIndex = 0;
            } else {
                otherFirstSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
            }

            if (externalSheet instanceof ExternalSheetRange) {
                String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
                otherLastSheetIndex = _workbook.getSheetIndex(lastSheetName);
            }
        } else {
            // look up sheet by name from external workbook
            String workbookName = externalSheet.getWorkbookName();
            try {
                targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
            } catch (WorkbookNotFoundException e) {
                throw new RuntimeException(e.getMessage(), e);
            }

            otherFirstSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());
            if (externalSheet instanceof ExternalSheetRange) {
                String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
                otherLastSheetIndex = targetEvaluator.getSheetIndex(lastSheetName);
            }

            if (otherFirstSheetIndex < 0) {
                throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName()
                        + "' in bool '" + workbookName + "'.");
            }
        }

        if (otherLastSheetIndex == -1) {
            // Reference to just one sheet
            otherLastSheetIndex = otherFirstSheetIndex;
        }

        SheetRefEvaluator[] evals = new SheetRefEvaluator[otherLastSheetIndex-otherFirstSheetIndex+1];
        for (int i=0; i<evals.length; i++) {
            int otherSheetIndex = i+otherFirstSheetIndex;
            evals[i] = new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
        }
        return new SheetRangeEvaluator(otherFirstSheetIndex, otherLastSheetIndex, evals);
    }

    /**
     * @return {@code null} if either workbook or sheet is not found
     */
    private SheetRefEvaluator createExternSheetRefEvaluator(String workbookName, String sheetName) {
        WorkbookEvaluator targetEvaluator;
        if (workbookName == null) {
            targetEvaluator = _bookEvaluator;
        } else {
            if (sheetName == null) {
                throw new IllegalArgumentException("sheetName must not be null if workbookName is provided");
            }
            try {
                targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
            } catch (WorkbookNotFoundException e) {
                return null;
            }
        }
        int otherSheetIndex = sheetName == null ? _sheetIndex : targetEvaluator.getSheetIndex(sheetName);
        if (otherSheetIndex < 0) {
            return null;
        }
        return new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
    }

    public SheetRangeEvaluator getRefEvaluatorForCurrentSheet() {
        SheetRefEvaluator sre = new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex);
        return new SheetRangeEvaluator(_sheetIndex, sre);
    }



    /**
     * Resolves a cell or area reference dynamically.
     * @param workbookName the name of the workbook containing the reference.  If {@code null}
     * the current workbook is assumed.  Note - to evaluate formulas which use multiple workbooks,
     * a {@link CollaboratingWorkbooksEnvironment} must be set up.
     * @param sheetName the name of the sheet containing the reference.  May be {@code null}
     * (when {@code workbookName} is also null) in which case the current workbook and sheet is
     * assumed.
     * @param refStrPart1 the single cell reference or first part of the area reference.  Must not
     * be {@code null}.
     * @param refStrPart2 the second part of the area reference. For single cell references this
     * parameter must be {@code null}
     * @param isA1Style specifies the format for {@code refStrPart1} and {@code refStrPart2}.
     * Pass {@code true} for 'A1' style and {@code false} for 'R1C1' style.
     * TODO - currently POI only supports 'A1' reference style
     * @return a {@link RefEval} or {@link AreaEval}
     */
    public ValueEval getDynamicReference(String workbookName, String sheetName, String refStrPart1,
            String refStrPart2, boolean isA1Style) {
        if (!isA1Style) {
            throw new RuntimeException("R1C1 style not supported yet");
        }
        SheetRefEvaluator se = createExternSheetRefEvaluator(workbookName, sheetName);
        if (se == null) {
            return ErrorEval.REF_INVALID;
        }
        SheetRangeEvaluator sre = new SheetRangeEvaluator(_sheetIndex, se);

        // ugly typecast - TODO - make spreadsheet version more easily accessible
        SpreadsheetVersion ssVersion = _workbook.getSpreadsheetVersion();

        NameType part1refType = classifyCellReference(refStrPart1, ssVersion);
        switch (part1refType) {
            case BAD_CELL_OR_NAMED_RANGE:
                return ErrorEval.REF_INVALID;
            case NAMED_RANGE:
                EvaluationName nm = _workbook.getName(refStrPart1, _sheetIndex);
                if(!nm.isRange()){
                    throw new RuntimeException("Specified name '" + refStrPart1 + "' is not a range as expected.");
                }
                return _bookEvaluator.evaluateNameFormula(nm.getNameDefinition(), this);
        }
        if (refStrPart2 == null) {
            // no ':'
            switch (part1refType) {
                case COLUMN:
                case ROW:
                    return ErrorEval.REF_INVALID;
                case CELL:
                    CellReference cr = new CellReference(refStrPart1);
                    return new LazyRefEval(cr.getRow(), cr.getCol(), sre);
            }
            throw new IllegalStateException("Unexpected reference classification of '" + refStrPart1 + "'.");
        }
        NameType part2refType = classifyCellReference(refStrPart1, ssVersion);
        switch (part2refType) {
            case BAD_CELL_OR_NAMED_RANGE:
                return ErrorEval.REF_INVALID;
            case NAMED_RANGE:
                throw new RuntimeException("Cannot evaluate '" + refStrPart1
                        + "'. Indirect evaluation of defined names not supported yet");
        }

        if (part2refType != part1refType) {
            // LHS and RHS of ':' must be compatible
            return ErrorEval.REF_INVALID;
        }
        int firstRow, firstCol, lastRow, lastCol;
        switch (part1refType) {
            case COLUMN:
                firstRow =0;
                if (part2refType.equals(NameType.COLUMN))
                {
                    lastRow = ssVersion.getLastRowIndex();
                    firstCol = parseRowRef(refStrPart1);
                    lastCol = parseRowRef(refStrPart2);
                }
                else {
                    lastRow = ssVersion.getLastRowIndex();
                    firstCol = parseColRef(refStrPart1);
                    lastCol = parseColRef(refStrPart2);
                }
                break;
            case ROW:
                // support of cell range in the form of integer:integer
                firstCol = 0;
                if (part2refType.equals(NameType.ROW))
                {
                    firstRow = parseColRef(refStrPart1);
                    lastRow = parseColRef(refStrPart2);
                    lastCol = ssVersion.getLastColumnIndex();
                } else {
                    lastCol = ssVersion.getLastColumnIndex();
                    firstRow = parseRowRef(refStrPart1);
                    lastRow = parseRowRef(refStrPart2);
                }
                break;
            case CELL:
                CellReference cr;
                cr = new CellReference(refStrPart1);
                firstRow = cr.getRow();
                firstCol = cr.getCol();
                cr = new CellReference(refStrPart2);
                lastRow = cr.getRow();
                lastCol = cr.getCol();
                break;
            default:
                throw new IllegalStateException("Unexpected reference classification of '" + refStrPart1 + "'.");
        }
        return new LazyAreaEval(firstRow, firstCol, lastRow, lastCol, sre);
    }

    private static int parseRowRef(String refStrPart) {
        return CellReference.convertColStringToIndex(refStrPart);
    }

    private static int parseColRef(String refStrPart) {
        return Integer.parseInt(refStrPart) - 1;
    }

    private static NameType classifyCellReference(String str, SpreadsheetVersion ssVersion) {
        int len = str.length();
        if (len < 1) {
            return CellReference.NameType.BAD_CELL_OR_NAMED_RANGE;
        }
        return CellReference.classifyCellReference(str, ssVersion);
    }

    public FreeRefFunction findUserDefinedFunction(String functionName) {
        return _bookEvaluator.findUserDefinedFunction(functionName);
    }

    public ValueEval getRefEval(int rowIndex, int columnIndex) {
        SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
        return new LazyRefEval(rowIndex, columnIndex, sre);
    }
    public ValueEval getRef3DEval(Ref3DPtg rptg) {
        SheetRangeEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
        return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
    }
    public ValueEval getRef3DEval(Ref3DPxg rptg) {
        SheetRangeEvaluator sre = createExternSheetRefEvaluator(
                rptg.getSheetName(), rptg.getLastSheetName(), rptg.getExternalWorkbookNumber());
        return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
    }

    public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex,
            int lastRowIndex, int lastColumnIndex) {
        SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
        return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
    }
    public ValueEval getArea3DEval(Area3DPtg aptg) {
        SheetRangeEvaluator sre = createExternSheetRefEvaluator(aptg.getExternSheetIndex());
        return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
                aptg.getLastRow(), aptg.getLastColumn(), sre);
    }
    public ValueEval getArea3DEval(Area3DPxg aptg) {
        SheetRangeEvaluator sre = createExternSheetRefEvaluator(
                aptg.getSheetName(), aptg.getLastSheetName(), aptg.getExternalWorkbookNumber());
        return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
                aptg.getLastRow(), aptg.getLastColumn(), sre);
    }

    public ValueEval getAreaValueEval(int firstRowIndex, int firstColumnIndex,
            int lastRowIndex, int lastColumnIndex, Object[][] tokens) {

        ValueEval[] values = new ValueEval[tokens.length * tokens[0].length];

        int index = 0;
        for (Object[] token : tokens) {
            for (int idx = 0; idx < tokens[0].length; idx++) {
                values[index++] = convertObjectEval(token[idx]);
            }
        }

        return new CacheAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex,
                                 lastColumnIndex, values);
    }

    private ValueEval convertObjectEval(Object token) {
        if (token == null) {
            throw new RuntimeException("Array item cannot be null");
        }
        if (token instanceof String) {
            return new StringEval((String)token);
        }
        if (token instanceof Double) {
            return new NumberEval((Double) token);
        }
        if (token instanceof Boolean) {
            return BoolEval.valueOf((Boolean) token);
        }
        if (token instanceof ErrorConstant) {
            return ErrorEval.valueOf(((ErrorConstant)token).getErrorCode());
        }
        throw new IllegalArgumentException("Unexpected constant class (" + token.getClass().getName() + ")");
    }


    public ValueEval getNameXEval(NameXPtg nameXPtg) {
        // Is the name actually on our workbook?
        ExternalSheet externSheet = _workbook.getExternalSheet(nameXPtg.getSheetRefIndex());
        if(externSheet == null || externSheet.getWorkbookName() == null) {
            // External reference to our own workbook's name
            return getLocalNameXEval(nameXPtg);
        }

        // Look it up for the external workbook
        String workbookName = externSheet.getWorkbookName();
        ExternalName externName = _workbook.getExternalName(
              nameXPtg.getSheetRefIndex(),
              nameXPtg.getNameIndex()
        );
        return getExternalNameXEval(externName, workbookName);
    }
    public ValueEval getNameXEval(NameXPxg nameXPxg) {
        ExternalSheet externSheet = _workbook.getExternalSheet(nameXPxg.getSheetName(), null, nameXPxg.getExternalWorkbookNumber());
        if(externSheet == null || externSheet.getWorkbookName() == null) {
            // External reference to our own workbook's name
            return getLocalNameXEval(nameXPxg);
        }

        // Look it up for the external workbook
        String workbookName = externSheet.getWorkbookName();
        ExternalName externName = _workbook.getExternalName(
              nameXPxg.getNameName(),
              nameXPxg.getSheetName(),
              nameXPxg.getExternalWorkbookNumber()
        );
        return getExternalNameXEval(externName, workbookName);
    }

    private ValueEval getLocalNameXEval(NameXPxg nameXPxg) {
        // Look up the sheet, if present
        int sIdx = -1;
        if (nameXPxg.getSheetName() != null) {
            sIdx = _workbook.getSheetIndex(nameXPxg.getSheetName());
        }

        // Is it a name or a function?
        String name = nameXPxg.getNameName();
        EvaluationName evalName = _workbook.getName(name, sIdx);
        if (evalName != null) {
            // Process it as a name
            return new ExternalNameEval(evalName);
        } else {
            // Must be an external function
            return new FunctionNameEval(name);
        }
    }
    private ValueEval getLocalNameXEval(NameXPtg nameXPtg) {
        String name = _workbook.resolveNameXText(nameXPtg);

        // Try to parse it as a name
        int sheetNameAt = name.indexOf('!');
        EvaluationName evalName;
        if (sheetNameAt > -1) {
            // Sheet based name
            String sheetName = name.substring(0, sheetNameAt);
            String nameName = name.substring(sheetNameAt+1);
            evalName = _workbook.getName(nameName, _workbook.getSheetIndex(sheetName));
        } else {
            // Workbook based name
            evalName = _workbook.getName(name, -1);
        }

        if (evalName != null) {
            // Process it as a name
            return new ExternalNameEval(evalName);
        } else {
            // Must be an external function
            return new FunctionNameEval(name);
        }
    }
    public int getSheetIndex() {
        return _sheetIndex;
    }

    /**
     * default true
     * @return flag indicating whether evaluation should "unwrap" the result to a single value based on the context row/column
     */
    public boolean isSingleValue() {
        return _isSingleValue;
    }

    private ValueEval getExternalNameXEval(ExternalName externName, String workbookName) {
        try {
            // Fetch the workbook this refers to, and the name as defined with that
            WorkbookEvaluator refWorkbookEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
            EvaluationName evaluationName = refWorkbookEvaluator.getName(externName.getName(),externName.getIx()-1);
            if (evaluationName != null && evaluationName.hasFormula()){
                if (evaluationName.getNameDefinition().length > 1) {
                    throw new RuntimeException("Complex name formulas not supported yet");
                }

                // Need to evaluate the reference in the context of the other book
                OperationEvaluationContext refWorkbookContext = new OperationEvaluationContext(
                        refWorkbookEvaluator, refWorkbookEvaluator.getWorkbook(), -1, -1, -1, _tracker);

                Ptg ptg = evaluationName.getNameDefinition()[0];
                if (ptg instanceof Ref3DPtg){
                    Ref3DPtg ref3D = (Ref3DPtg)ptg;
                    return refWorkbookContext.getRef3DEval(ref3D);
                } else if (ptg instanceof Ref3DPxg){
                    Ref3DPxg ref3D = (Ref3DPxg)ptg;
                    return refWorkbookContext.getRef3DEval(ref3D);
                } else if(ptg instanceof Area3DPtg){
                    Area3DPtg area3D = (Area3DPtg)ptg;
                    return refWorkbookContext.getArea3DEval(area3D);
                } else if(ptg instanceof Area3DPxg){
                    Area3DPxg area3D = (Area3DPxg)ptg;
                    return refWorkbookContext.getArea3DEval(area3D);
                }
            }
            return ErrorEval.REF_INVALID;
        } catch(WorkbookNotFoundException wnfe){
            return ErrorEval.REF_INVALID;
        }
   }
}
