/*=============================================================================#
 # Copyright (c) 2007, 2019 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.r.core.rsource.ast;

import static org.eclipse.statet.r.core.rsource.IRSourceConstants.STATUS1_SYNTAX_MISSING_TOKEN;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.ltk.ast.core.AstNode;
import org.eclipse.statet.ltk.ast.core.AstVisitor;


/**
 * <code>expr; expr; ...</code>
 */
@NonNullByDefault
abstract class ExpressionList extends RAstNode {
	
	
	final List<Expression> expressions= new ArrayList<>();
	
	
	ExpressionList() {
	}
	
	
	@Override
	public final boolean hasChildren() {
		return (this.expressions.size() > 0);
	}
	
	@Override
	public final RAstNode[] getChildren() {
		final int n= this.expressions.size();
		final RAstNode[] children= new @NonNull RAstNode[n];
		for (int i= 0; i < n; i++) {
			children[i]= this.expressions.get(i).node;
		}
		return children;
	}
	
	@Override
	public final int getChildIndex(final AstNode child) {
		for (int i= this.expressions.size() - 1; i >= 0; i--) {
			if (this.expressions.get(i).node == child) {
				return i;
			}
		}
		return -1;
	}
	
	@Override
	public final int getChildCount() {
		return this.expressions.size();
	}
	
	@Override
	public final RAstNode getChild(final int i) {
		return this.expressions.get(i).node;
	}
	
	@Override
	public final void acceptInRChildren(final RAstVisitor visitor) throws InvocationTargetException {
		acceptChildrenExpr(visitor, this.expressions);
	}
	
	@Override
	public final void acceptInChildren(final AstVisitor visitor) throws InvocationTargetException {
		for (final Expression expr : this.expressions) {
			visitor.visit(expr.node);
		}
	}
	
	
	@Override
	final @Nullable Expression getExpr(final RAstNode child) {
		for (int i= this.expressions.size() - 1; i >= 0; i--) {
			if (this.expressions.get(i).node == child) {
				return this.expressions.get(i);
			}
		}
		return null;
	}
	
	@Override
	final @Nullable Expression getLeftExpr() {
		return null;
	}
	
	@Override
	final @Nullable Expression getRightExpr() {
		return null;
	}
	
	Expression appendNewExpr() {
		final Expression expr= new Expression();
		this.expressions.add(expr);
		return expr;
	}
	
	void setSeparator(final int offset) {
	}
	
	
	@Override
	final int getMissingExprStatus(final Expression expr) {
		return STATUS1_SYNTAX_MISSING_TOKEN;
	}
	
}
