using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace AtomUI.Generator;

internal class ControlTokenPropertyWalker : CSharpSyntaxWalker
{
    public const string NotTokenDefinitionAttribute = "NotTokenDefinition";
    public ControlTokenInfo ControlTokenInfo { get; }
    private readonly SemanticModel _semanticModel;
    public string? TokenResourceCatalog { get; set; }

    public ControlTokenPropertyWalker(SemanticModel semanticModel)
    {
        _semanticModel   = semanticModel;
        ControlTokenInfo = new ControlTokenInfo();
    }

    public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
    {
        var isSkip = node.AttributeLists
                         .SelectMany(attrList => attrList.Attributes)
                         .Any(attr => attr.Name.ToString() == NotTokenDefinitionAttribute);
        if (!isSkip)
        {
            ControlTokenInfo.Tokens.Add(new TokenName(node.Identifier.Text, TokenResourceCatalog!));
        }
    }

    public override void VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        ControlTokenInfo.ControlName = node.Identifier.Text;
        if (node.Parent is FileScopedNamespaceDeclarationSyntax fileScopedNamespaceDecl)
        {
            ControlTokenInfo.ControlNamespace = fileScopedNamespaceDecl.Name.ToString();
        }
        else if (node.Parent is NamespaceDeclarationSyntax namespaceDecl)
        {
            ControlTokenInfo.ControlNamespace = namespaceDecl.Name.ToString();
        }

        var classDeclaredSymbol = _semanticModel.GetDeclaredSymbol(node);
        if (classDeclaredSymbol is not null)
        {
            foreach (var attribute in classDeclaredSymbol.GetAttributes())
            {
                if (attribute.ConstructorArguments.Any() && attribute.ConstructorArguments[0].Value is string catalog)
                {
                    TokenResourceCatalog = catalog;
                }
            }
        }

        base.VisitClassDeclaration(node);
    }
}