/* ====================================================================
   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.formula.ptg.ArrayPtg;
import org.apache.poi.ss.formula.ptg.AttrPtg;
import org.apache.poi.ss.formula.ptg.FuncVarPtg;
import org.apache.poi.ss.formula.ptg.MemAreaPtg;
import org.apache.poi.ss.formula.ptg.MemFuncPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
/**
 * Represents a syntactic element from a formula by encapsulating the corresponding <tt>Ptg</tt>
 * token.  Each <tt>ParseNode</tt> may have child <tt>ParseNode</tt>s in the case when the wrapped
 * <tt>Ptg</tt> is non-atomic.
 */
final class ParseNode {

	public static final ParseNode[] EMPTY_ARRAY = { };
	private final Ptg _token;
	private final ParseNode[] _children;
	private boolean _isIf;
	private final int _tokenCount;

	public ParseNode(Ptg token, ParseNode[] children) {
		if (token == null) {
			throw new IllegalArgumentException("token must not be null");
		}
		_token = token;
		_children = children.clone();
		_isIf = isIf(token);
		int tokenCount = 1;
		for (int i = 0; i < children.length; i++) {
			tokenCount += children[i].getTokenCount();
		}
		if (_isIf) {
			// there will be 2 or 3 extra tAttr tokens according to whether the false param is present
			tokenCount += children.length;
		}
		_tokenCount = tokenCount;
	}
	public ParseNode(Ptg token) {
		this(token, EMPTY_ARRAY);
	}
	public ParseNode(Ptg token, ParseNode child0) {
		this(token, new ParseNode[] { child0, });
	}
	public ParseNode(Ptg token, ParseNode child0, ParseNode child1) {
		this(token, new ParseNode[] { child0, child1, });
	}
	private int getTokenCount() {
		return _tokenCount;
	}
	public int getEncodedSize() {
		int result = _token instanceof ArrayPtg ? ArrayPtg.PLAIN_TOKEN_SIZE : _token.getSize();
		for (int i = 0; i < _children.length; i++) {
			result += _children[i].getEncodedSize();
		}
		return result;
	}

	/**
	 * Collects the array of <tt>Ptg</tt> tokens for the specified tree.
	 */
	public static Ptg[] toTokenArray(ParseNode rootNode) {
		TokenCollector temp = new TokenCollector(rootNode.getTokenCount());
		rootNode.collectPtgs(temp);
		return temp.getResult();
	}
	private void collectPtgs(TokenCollector temp) {
		if (isIf(_token)) {
			collectIfPtgs(temp);
			return;
		}
		boolean isPreFixOperator = _token instanceof MemFuncPtg || _token instanceof MemAreaPtg;
		if (isPreFixOperator) {
			temp.add(_token);
		}
		for (int i=0; i< getChildren().length; i++) {
			getChildren()[i].collectPtgs(temp);
		}
		if (!isPreFixOperator) {
			temp.add(_token);
		}
	}
	/**
	 * The IF() function gets marked up with two or three tAttr tokens.
	 * Similar logic will be required for CHOOSE() when it is supported
	 *
	 * See excelfileformat.pdf sec 3.10.5 "tAttr (19H)
	 */
	private void collectIfPtgs(TokenCollector temp) {

		// condition goes first
		getChildren()[0].collectPtgs(temp);

		// placeholder for tAttrIf
		int ifAttrIndex = temp.createPlaceholder();

		// true parameter
		getChildren()[1].collectPtgs(temp);

		// placeholder for first skip attr
		int skipAfterTrueParamIndex = temp.createPlaceholder();
		int trueParamSize = temp.sumTokenSizes(ifAttrIndex+1, skipAfterTrueParamIndex);

		AttrPtg attrIf = AttrPtg.createIf(trueParamSize + 4); // distance to start of false parameter/tFuncVar. +4 for tAttrSkip after true

		if (getChildren().length > 2) {
			// false param present

			// false parameter
			getChildren()[2].collectPtgs(temp);

			int skipAfterFalseParamIndex = temp.createPlaceholder();

			int falseParamSize =  temp.sumTokenSizes(skipAfterTrueParamIndex+1, skipAfterFalseParamIndex);

			AttrPtg attrSkipAfterTrue = AttrPtg.createSkip(falseParamSize + 4 + 4 - 1); // 1 less than distance to end of if FuncVar(size=4). +4 for attr skip before
			AttrPtg attrSkipAfterFalse = AttrPtg.createSkip(4 - 1); // 1 less than distance to end of if FuncVar(size=4).

			temp.setPlaceholder(ifAttrIndex, attrIf);
			temp.setPlaceholder(skipAfterTrueParamIndex, attrSkipAfterTrue);
			temp.setPlaceholder(skipAfterFalseParamIndex, attrSkipAfterFalse);
		} else {
			// false parameter not present
			AttrPtg attrSkipAfterTrue = AttrPtg.createSkip(4 - 1); // 1 less than distance to end of if FuncVar(size=4).

			temp.setPlaceholder(ifAttrIndex, attrIf);
			temp.setPlaceholder(skipAfterTrueParamIndex, attrSkipAfterTrue);
		}
		temp.add(_token);
	}

	private static boolean isIf(Ptg token) {
		if (token instanceof FuncVarPtg) {
			FuncVarPtg func = (FuncVarPtg) token;
			if (FunctionMetadataRegistry.FUNCTION_NAME_IF.equals(func.getName())) {
				return true;
			}
		}
		return false;
	}

	public Ptg getToken() {
		return _token;
	}

	public ParseNode[] getChildren() {
		return _children;
	}

	private static final class TokenCollector {

		private final Ptg[] _ptgs;
		private int _offset;

		public TokenCollector(int tokenCount) {
			_ptgs = new Ptg[tokenCount];
			_offset = 0;
		}

		public int sumTokenSizes(int fromIx, int toIx) {
			int result = 0;
			for (int i=fromIx; i<toIx; i++) {
				result += _ptgs[i].getSize();
			}
			return result;
		}

		public int createPlaceholder() {
			return _offset++;
		}

		public void add(Ptg token) {
			if (token == null) {
				throw new IllegalArgumentException("token must not be null");
			}
			_ptgs[_offset] = token;
			_offset++;
		}

		public void setPlaceholder(int index, Ptg token) {
			if (_ptgs[index] != null) {
				throw new IllegalStateException("Invalid placeholder index (" + index + ")");
			}
			_ptgs[index] = token;
		}

		public Ptg[] getResult() {
			return _ptgs;
		}
	}
}
