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

#nullable disable

using System;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Xunit;

namespace Microsoft.AspNetCore.Razor.Language.Intermediate;

// These tests cover the methods on ExtensionIntermediateNode that are used to implement visitors
// that special case an extension node.
public class ExtensionIntermediateNodeTest
{
    [Fact]
    public void Accept_CallsStandardVisitExtension_ForStandardVisitor()
    {
        // Arrange
        var node = new TestExtensionIntermediateNode();
        var visitor = new StandardVisitor();

        // Act
        node.Accept(visitor);

        // Assert
        Assert.True(visitor.WasStandardMethodCalled);
        Assert.False(visitor.WasSpecificMethodCalled);
    }

    [Fact]
    public void Accept_CallsSpecialVisitExtension_ForSpecialVisitor()
    {
        // Arrange
        var node = new TestExtensionIntermediateNode();
        var visitor = new SpecialVisitor();

        // Act
        node.Accept(visitor);

        // Assert
        Assert.False(visitor.WasStandardMethodCalled);
        Assert.True(visitor.WasSpecificMethodCalled);
    }

    private class TestExtensionIntermediateNode : ExtensionIntermediateNode
    {
        public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;

        public override void Accept(IntermediateNodeVisitor visitor)
        {
            // This is the standard visitor boilerplate for an extension node.
            AcceptExtensionNode<TestExtensionIntermediateNode>(this, visitor);
        }

        public override void WriteNode(CodeTarget target, CodeRenderingContext context)
        {
            throw new NotImplementedException();
        }
    }

    private class StandardVisitor : IntermediateNodeVisitor
    {
        public bool WasStandardMethodCalled { get; private set; }
        public bool WasSpecificMethodCalled { get; private set; }

        public override void VisitExtension(ExtensionIntermediateNode node)
        {
            WasStandardMethodCalled = true;
        }

        public void VisitExtension(TestExtensionIntermediateNode node)
        {
            WasSpecificMethodCalled = true;
        }
    }

    private class SpecialVisitor : IntermediateNodeVisitor, IExtensionIntermediateNodeVisitor<TestExtensionIntermediateNode>
    {
        public bool WasStandardMethodCalled { get; private set; }
        public bool WasSpecificMethodCalled { get; private set; }

        public override void VisitExtension(ExtensionIntermediateNode node)
        {
            WasStandardMethodCalled = true;
        }

        public void VisitExtension(TestExtensionIntermediateNode node)
        {
            WasSpecificMethodCalled = true;
        }
    }
}
