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

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

import org.eclipse.statet.ltk.ast.core.AstNode;
import org.eclipse.statet.ltk.ast.core.AstVisitor;
import org.eclipse.statet.r.core.rlang.RTerminal;


/**
 * <code>§ref§ [ §args§ ]</code>
 * <code>§ref§ [[ §args§ ]]</code>
 */
public abstract class SubIndexed extends RAstNode {
	
	
	static final class S extends SubIndexed {
		
		
		S() {
		}
		
		
		@Override
		public final NodeType getNodeType() {
			return NodeType.SUB_INDEXED_S;
		}
		
		@Override
		public final RTerminal getOperator(final int index) {
			return RTerminal.SUB_INDEXED_S_OPEN;
		}
		
		
		@Override
		public final boolean equalsSingle(final RAstNode element) {
			return (element.getNodeType() == NodeType.SUB_INDEXED_S && super.equalsSingle(element));
		}
		
	}
	
	static final class D extends SubIndexed {
		
		
		D() {
		}
		
		
		@Override
		public final NodeType getNodeType() {
			return NodeType.SUB_INDEXED_D;
		}
		
		@Override
		public final RTerminal getOperator(final int index) {
			return RTerminal.SUB_INDEXED_D_OPEN;
		}
		
		
		@Override
		public final boolean equalsSingle(final RAstNode element) {
			return (element.getNodeType() == NodeType.SUB_INDEXED_D && super.equalsSingle(element));
		}
		
	}
	
	public static final class Args extends RAstNode {
		
		
		final List<SubIndexed.Arg> specs;
		
		
		Args(final SubIndexed parent) {
			this.rParent= parent;
			this.specs= new ArrayList<>();
		}
		
		@Override
		public final NodeType getNodeType() {
			return NodeType.SUB_INDEXED_ARGS;
		}
		
		@Override
		public final RTerminal getOperator(final int index) {
			return null;
		}
		
		
		@Override
		public final boolean hasChildren() {
			return (!this.specs.isEmpty());
		}
		
		@Override
		public final int getChildCount() {
			return this.specs.size();
		}
		
		@Override
		public final RAstNode getChild(final int index) {
			return this.specs.get(index);
		}
		
		@Override
		public final RAstNode[] getChildren() {
			return this.specs.toArray(new RAstNode[this.specs.size()]);
		}
		
		@Override
		public final int getChildIndex(final AstNode child) {
			for (int i= this.specs.size() - 1; i >= 0; i--) {
				if (this.specs.get(i) == child) {
					return i;
				}
			}
			return -1;
		}
		
		@Override
		public final void acceptInR(final RAstVisitor visitor) throws InvocationTargetException {
			visitor.visit(this);
		}
		
		@Override
		public final void acceptInRChildren(final RAstVisitor visitor) throws InvocationTargetException {
			acceptChildren(visitor, this.specs);
		}
		
		@Override
		public final void acceptInChildren(final AstVisitor visitor) throws InvocationTargetException {
			for (final RAstNode child : this.specs) {
				visitor.visit(child);
			}
		}
		
		
		@Override
		final Expression getExpr(final RAstNode child) {
			return null;
		}
		
		@Override
		final Expression getLeftExpr() {
			return null;
		}
		
		@Override
		final Expression getRightExpr() {
			return null;
		}
		
		
		@Override
		final boolean equalsSingle(final RAstNode element) {
			return (element.getNodeType() == NodeType.SUB_INDEXED_ARGS);
		}
		
		@Override
		final int getMissingExprStatus(final Expression expr) {
			throw new IllegalArgumentException();
		}
		
		@Override
		final void updateEndOffset() {
		}
		
	}
	
	public static final class Arg extends SpecItem {
		
		
		Arg(final SubIndexed.Args parent) {
			this.rParent= parent;
		}
		
		
		@Override
		public final NodeType getNodeType() {
			return NodeType.SUB_INDEXED_ARG;
		}
		
		
		@Override
		public final void acceptInR(final RAstVisitor visitor) throws InvocationTargetException {
			visitor.visit(this);
		}
		
		
		@Override
		public final boolean equalsSingle(final RAstNode element) {
			return (element.getNodeType() == NodeType.SUB_INDEXED_ARG);
		}
		
	}
	
	
	final Expression expr= new Expression();
	final Args sublist= new Args(this);
	int openOffset= NA_OFFSET;
	int closeOffset= NA_OFFSET;
	int close2Offset= NA_OFFSET;
	
	
	protected SubIndexed() {
	}
	
	
	@Override
	public final boolean hasChildren() {
		return true;
	}
	
	@Override
	public final int getChildCount() {
		return 2;
	}
	
	@Override
	public final RAstNode getChild(final int index) {
		switch (index) {
		case 0:
			return this.expr.node;
		case 1:
			return this.sublist;
		default:
			throw new IndexOutOfBoundsException();
		}
	}
	
	@Override
	public final RAstNode[] getChildren() {
		return new RAstNode[] { this.expr.node, this.sublist };
	}
	
	public final RAstNode getRefChild() {
		return this.expr.node;
	}
	
	public final Args getArgsChild() {
		return this.sublist;
	}
	
	public final int getSublistOpenOffset() {
		return this.openOffset;
	}
	
	public final int getSublistCloseOffset() {
		return this.closeOffset;
	}
	
	public final int getSublistClose2Offset() {
		return this.closeOffset;
	}
	
	@Override
	public final int getChildIndex(final AstNode child) {
		if (this.expr.node == child) {
			return 0;
		}
		if (this.sublist == child) {
			return 1;
		}
		return -1;
	}
	
	@Override
	public final void acceptInR(final RAstVisitor visitor) throws InvocationTargetException {
		visitor.visit(this);
	}
	
	@Override
	public final void acceptInRChildren(final RAstVisitor visitor) throws InvocationTargetException {
		this.expr.node.acceptInR(visitor);
		this.sublist.acceptInR(visitor);
	}
	
	@Override
	public final void acceptInChildren(final AstVisitor visitor) throws InvocationTargetException {
		visitor.visit(this.expr.node);
		visitor.visit(this.sublist);
	}
	
	
	@Override
	final Expression getExpr(final RAstNode child) {
		if (this.expr.node == child) {
			return this.expr;
		}
		return null;
	}
	@Override
	final Expression getLeftExpr() {
		return this.expr;
	}
	
	@Override
	final Expression getRightExpr() {
		return null;
	}
	
	@Override
	public boolean equalsSingle(final RAstNode element) {
		final SubIndexed other= (SubIndexed) element;
		return ((this.expr.node == other.expr.node
						|| (this.expr.node != null && this.expr.node.equalsSingle(other.expr.node)) )
				);
	}
	
	
	@Override
	final int getMissingExprStatus(final Expression expr) {
		if (this.expr == expr) {
			return STATUS2_SYNTAX_EXPR_AS_REF_MISSING;
		}
		throw new IllegalArgumentException();
	}
	
	final void updateStartOffset() {
		this.startOffset= this.expr.node.startOffset;
	}
	
	@Override
	final void updateEndOffset() {
		if (this.close2Offset != NA_OFFSET) {
			this.endOffset= this.close2Offset + 1;
		}
		else if (this.closeOffset != NA_OFFSET) {
			this.endOffset= this.closeOffset + 1;
		}
		else {
			this.endOffset= this.sublist.endOffset;
		}
	}
	
}
