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

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Legacy;

namespace Microsoft.AspNetCore.Razor.Language.Syntax
{
    internal class SyntaxToken : RazorSyntaxNode
    {
        internal SyntaxToken(GreenNode green, SyntaxNode parent, int position)
            : base(green, parent, position)
        {
        }

        internal new InternalSyntax.SyntaxToken Green => (InternalSyntax.SyntaxToken)base.Green;

        public string Content => Green.Content;

        internal sealed override SyntaxNode GetCachedSlot(int index)
        {
            throw new InvalidOperationException("Tokens can't have slots.");
        }

        internal sealed override SyntaxNode GetNodeSlot(int slot)
        {
            throw new InvalidOperationException("Tokens can't have slots.");
        }

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

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

        public SyntaxToken WithLeadingTrivia(SyntaxNode trivia)
        {
            return Green != null
                ? new SyntaxToken(Green.WithLeadingTrivia(trivia.Green), parent: null, position: 0)
                : default(SyntaxToken);
        }

        public SyntaxToken WithTrailingTrivia(SyntaxNode trivia)
        {
            return Green != null
                ? new SyntaxToken(Green.WithTrailingTrivia(trivia.Green), parent: null, position: 0)
                : default(SyntaxToken);
        }

        public SyntaxToken WithLeadingTrivia(IEnumerable<SyntaxTrivia> trivia)
        {
            var greenList = trivia?.Select(t => t.Green);
            return WithLeadingTrivia(Green.CreateList(greenList)?.CreateRed());
        }

        public SyntaxToken WithTrailingTrivia(IEnumerable<SyntaxTrivia> trivia)
        {
            var greenList = trivia?.Select(t => t.Green);
            return WithTrailingTrivia(Green.CreateList(greenList)?.CreateRed());
        }

        public override SyntaxTriviaList GetLeadingTrivia()
        {
            var leading = Green.GetLeadingTrivia();
            if (leading == null)
            {
                return default(SyntaxTriviaList);
            }

            return new SyntaxTriviaList(leading.CreateRed(this, Position), Position);
        }

        public override SyntaxTriviaList GetTrailingTrivia()
        {
            var trailing = Green.GetTrailingTrivia();
            if (trailing == null)
            {
                return default(SyntaxTriviaList);
            }

            var leading = Green.GetLeadingTrivia();
            var index = 0;
            if (leading != null)
            {
                index = leading.IsList ? leading.SlotCount : 1;
            }
            int trailingPosition = Position + FullWidth;
            trailingPosition -= trailing.FullWidth;

            return new SyntaxTriviaList(trailing.CreateRed(this, trailingPosition), trailingPosition, index);
        }

        public override string ToString()
        {
            return Content;
        }
    }
}
