// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.AspNetCore.Razor.Language.Syntax
{
	internal abstract class SyntaxList : SyntaxNode
	{
		internal SyntaxList( InternalSyntax.SyntaxList green, SyntaxNode parent, int position )
			: base( green, parent, position )
		{
		}

		public override TResult Accept<TResult>( SyntaxVisitor<TResult> visitor )
		{
			return visitor.Visit( this );
		}

		public override void Accept( SyntaxVisitor visitor )
		{
			visitor.Visit( this );
		}

		internal class WithTwoChildren : SyntaxList
		{
			private SyntaxNode _child0;
			private SyntaxNode _child1;

			internal WithTwoChildren( InternalSyntax.SyntaxList green, SyntaxNode parent, int position )
				: base( green, parent, position )
			{
			}

			internal override SyntaxNode GetNodeSlot( int index )
			{
				switch ( index )
				{
					case 0:
						return GetRedElement( ref _child0, 0 );
					case 1:
						return GetRedElement( ref _child1, 1 );
					default:
						return null;
				}
			}

			internal override SyntaxNode GetCachedSlot( int index )
			{
				switch ( index )
				{
					case 0:
						return _child0;
					case 1:
						return _child1;
					default:
						return null;
				}
			}
		}

		internal class WithThreeChildren : SyntaxList
		{
			private SyntaxNode _child0;
			private SyntaxNode _child1;
			private SyntaxNode _child2;

			internal WithThreeChildren( InternalSyntax.SyntaxList green, SyntaxNode parent, int position )
				: base( green, parent, position )
			{
			}

			internal override SyntaxNode GetNodeSlot( int index )
			{
				switch ( index )
				{
					case 0:
						return GetRedElement( ref _child0, 0 );
					case 1:
						return GetRedElement( ref _child1, 1 );
					case 2:
						return GetRedElement( ref _child2, 2 );
					default:
						return null;
				}
			}

			internal override SyntaxNode GetCachedSlot( int index )
			{
				switch ( index )
				{
					case 0:
						return _child0;
					case 1:
						return _child1;
					case 2:
						return _child2;
					default:
						return null;
				}
			}
		}

		internal class WithManyChildren : SyntaxList
		{
			private readonly ArrayElement<SyntaxNode>[] _children;

			internal WithManyChildren( InternalSyntax.SyntaxList green, SyntaxNode parent, int position )
				: base( green, parent, position )
			{
				_children = new ArrayElement<SyntaxNode>[green.SlotCount];
			}

			internal override SyntaxNode GetNodeSlot( int index )
			{
				return this.GetRedElement( ref _children[index].Value, index );
			}

			internal override SyntaxNode GetCachedSlot( int index )
			{
				return _children[index];
			}
		}
	}
}
