/* ====================================================================
   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 java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.ValueEval;

/**
 * Instances of this class keep track of multiple dependent cell evaluations due
 * to recursive calls to {@link WorkbookEvaluator#evaluate(EvaluationCell)}}
 * The main purpose of this class is to detect an attempt to evaluate a cell
 * that is already being evaluated. In other words, it detects circular
 * references in spreadsheet formulas.
 *
 * @author Josh Micich
 */
final class EvaluationTracker {
	// TODO - consider deleting this class and letting CellEvaluationFrame take care of itself
	private final List<CellEvaluationFrame> _evaluationFrames;
	private final Set<FormulaCellCacheEntry> _currentlyEvaluatingCells;
	private final EvaluationCache _cache;

	public EvaluationTracker(EvaluationCache cache) {
		_cache = cache;
		_evaluationFrames = new ArrayList<CellEvaluationFrame>();
		_currentlyEvaluatingCells = new HashSet<FormulaCellCacheEntry>();
	}

	/**
	 * Notifies this evaluation tracker that evaluation of the specified cell is
	 * about to start.<br/>
	 *
	 * In the case of a <code>true</code> return code, the caller should
	 * continue evaluation of the specified cell, and also be sure to call
	 * <tt>endEvaluate()</tt> when complete.<br/>
	 *
	 * In the case of a <code>null</code> return code, the caller should
	 * return an evaluation result of
	 * <tt>ErrorEval.CIRCULAR_REF_ERROR<tt>, and not call <tt>endEvaluate()</tt>.
	 * <br/>
	 * @return <code>false</code> if the specified cell is already being evaluated
	 */
	public boolean startEvaluate(FormulaCellCacheEntry cce) {
		if (cce == null) {
			throw new IllegalArgumentException("cellLoc must not be null");
		}
		if (_currentlyEvaluatingCells.contains(cce)) {
			return false;
		}
		_currentlyEvaluatingCells.add(cce);
		_evaluationFrames.add(new CellEvaluationFrame(cce));
		return true;
	}

	public void updateCacheResult(ValueEval result) {

		int nFrames = _evaluationFrames.size();
		if (nFrames < 1) {
			throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
		}
		CellEvaluationFrame frame = _evaluationFrames.get(nFrames-1);
		if (result == ErrorEval.CIRCULAR_REF_ERROR && nFrames > 1) {
			// Don't cache a circular ref error result if this cell is not the top evaluated cell.
			// A true circular ref error will propagate all the way around the loop.  However, it's
			// possible to have parts of the formula tree (/ parts of the loop) to evaluate to
			// CIRCULAR_REF_ERROR, and that value not get used in the final cell result (see the
			// unit tests for a simple example). Thus, the only CIRCULAR_REF_ERROR result that can
			// safely be cached is that of the top evaluated cell.
			return;
		}

		frame.updateFormulaResult(result);
	}

	/**
	 * Notifies this evaluation tracker that the evaluation of the specified cell is complete. <p/>
	 *
	 * Every successful call to <tt>startEvaluate</tt> must be followed by a call to <tt>endEvaluate</tt> (recommended in a finally block) to enable
	 * proper tracking of which cells are being evaluated at any point in time.<p/>
	 *
	 * Assuming a well behaved client, parameters to this method would not be
	 * required. However, they have been included to assert correct behaviour,
	 * and form more meaningful error messages.
	 */
	public void endEvaluate(CellCacheEntry cce) {

		int nFrames = _evaluationFrames.size();
		if (nFrames < 1) {
			throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
		}

		nFrames--;
		CellEvaluationFrame frame = _evaluationFrames.get(nFrames);
		if (cce != frame.getCCE()) {
			throw new IllegalStateException("Wrong cell specified. ");
		}
		// else - no problems so pop current frame
		_evaluationFrames.remove(nFrames);
		_currentlyEvaluatingCells.remove(cce);
	}

	public void acceptFormulaDependency(CellCacheEntry cce) {
		// Tell the currently evaluating cell frame that it has a dependency on the specified
		int prevFrameIndex = _evaluationFrames.size()-1;
		if (prevFrameIndex < 0) {
			// Top level frame, there is no 'cell' above this frame that is using the current cell
		} else {
			CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
			consumingFrame.addSensitiveInputCell(cce);
		}
	}

	public void acceptPlainValueDependency(int bookIndex, int sheetIndex,
			int rowIndex, int columnIndex, ValueEval value) {
		// Tell the currently evaluating cell frame that it has a dependency on the specified
		int prevFrameIndex = _evaluationFrames.size() - 1;
		if (prevFrameIndex < 0) {
			// Top level frame, there is no 'cell' above this frame that is using the current cell
		} else {
			CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
			if (value == BlankEval.instance) {
				consumingFrame.addUsedBlankCell(bookIndex, sheetIndex, rowIndex, columnIndex);
			} else {
				PlainValueCellCacheEntry cce = _cache.getPlainValueEntry(bookIndex, sheetIndex,
						rowIndex, columnIndex, value);
				consumingFrame.addSensitiveInputCell(cce);
			}
		}
	}
}
