/*=============================================================================#
 # 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.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;
import org.eclipse.statet.r.core.rlang.RTerminal;


/**
 * <code>§ref§ [ §args§ ]</code>
 * <code>§ref§ [[ §args§ ]]</code>
 */
@NonNullByDefault
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;
		}
		
	}
	
	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;
		}
		
	}
	
	public static final class Args extends RAstNode {
		
		
		final List<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 @Nullable 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 @NonNull 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 @Nullable Expression getExpr(final RAstNode child) {
			return null;
		}
		
		@Override
		final @Nullable Expression getLeftExpr() {
			return null;
		}
		
		@Override
		final @Nullable Expression getRightExpr() {
			return null;
		}
		
		
		@Override
		final boolean equalsSingle(final RAstNode element) {
			return (NodeType.SUB_INDEXED_ARGS == element.getNodeType());
		}
		
		@Override
		final int getMissingExprStatus(final Expression expr) {
			throw new IllegalArgumentException();
		}
		
		@Override
		final void updateEndOffset() {
		}
		
	}
	
	public static final class Arg extends SpecItem {
		
		
		Arg(final Args parent) {
			this.rParent= parent;
		}
		
		
		@Override
		public final NodeType getNodeType() {
			return NodeType.SUB_INDEXED_ARG;
		}
		
		
		@Override
		public @Nullable Args getRParent() {
			return (Args)this.rParent;
		}
		
		
		@Override
		public final void acceptInR(final RAstVisitor visitor) throws InvocationTargetException {
			visitor.visit(this);
		}
		
		
		@Override
		public final boolean equalsSingle(final RAstNode element) {
			return (NodeType.SUB_INDEXED_ARG == element.getNodeType());
		}
		
	}
	
	
	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 @Nullable Expression getExpr(final RAstNode child) {
		if (this.expr.node == child) {
			return this.expr;
		}
		return null;
	}
	@Override
	final Expression getLeftExpr() {
		return this.expr;
	}
	
	@Override
	final @Nullable Expression getRightExpr() {
		return null;
	}
	
	@Override
	public final boolean equalsSingle(final RAstNode element) {
		if (getNodeType() == element.getNodeType()) {
			final SubIndexed other= (SubIndexed)element;
			return ((this.expr.node == other.expr.node
							|| (this.expr.node != null && this.expr.node.equalsSingle(other.expr.node)) )
					);
		}
		return false;
	}
	
	
	@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;
		}
	}
	
}
