ApplicationCommandOption? GetOption(CommandNode node)
        {
            ApplicationCommandOption option = getOptionRep(node);

            var options = new List<ApplicationCommandOption>();

            //All the sub nodes are arguments, we need to flatten them
            var nodes = node.GetChildNodes().Map(n => n.GetChildNodes()).ToList();
            if (nodes.All(i => i is IArgumentNode))
            {
                options.AddRange(nodes.Select(getOptionRep));
            }
            else
            {
                foreach (var n in node.GetChildNodes())
                {
                    options.Add(GetOption(n));
                }    
            }

            option.Options = options.ToArray();
            
            return option;
        }
        SlashCommand? GetCommand(CommandNode cmdNode)
        {
            var command = new ApplicationCommand();
            command.Name = cmdNode.Name;
            command.Description = "top level";
            var options = new List<ApplicationCommandOption>();

            foreach (var node in cmdNode.GetChildNodes())
            {
                options.Add(GetOption(node));
            }

            command.Options = options.ToArray();
            
            var meta = cmdNode.Meta as CommandMetaData;
            var t = new SlashCommand(command, meta?.guild_id, meta);
            //t._applicationCommand = command;
            return t;
        }
        ApplicationCommandOption getOptionRep(CommandNode node)
        {
            ApplicationCommandOption option = new ApplicationCommandOption();
            option.Name = node.Name;
            option.Description = "Test: " + node.Name;

            if (node is LiteralNode)
            {
                var nodes = node.GetChildNodes().Map(n => n.GetChildNodes()).ToList();
                if (node.EndNode || nodes.All(i => i is IArgumentNode))
                {
                    option.Type = ApplicationCommandOptionType.SubCommand;    
                }
                else
                {
                    option.Type = ApplicationCommandOptionType.SubCommandGroup;
                }
                
            }
            else if (node is ArgumentNode<DiscordUser> userArg)
            {
                option.Type = ApplicationCommandOptionType.User;
                option.Required = true;
            }
            else if(node is ArgumentNode<string> stringArg)
            {
                option.Type = ApplicationCommandOptionType.String;
                option.Required = true;
            }
            else if(node is ArgumentNode<int>)
            {
                option.Type = ApplicationCommandOptionType.Integer;
                option.Required = true;
            }
            
            return option;
        }
        public static void ParseOptions(CommandNode node, ApplicationCommandInteractionDataOption[] data, ParseResult parseResult)
        {
            var nodes = node.GetChildNodes().Map(n => n.GetChildNodes()).ToList();

            if (node.EndNode || nodes.All(i => i is IArgumentNode))
            {
                foreach (var option in data)
                {
                    foreach (var child in nodes)
                    {
                        if (child.Name == option.Name)
                        {
                            //This is a argument with a value
                            if (option.Value is not null)
                            {
                                string d = option.Value.ToString();
                                if (child.CanParse(d))
                                {
                                    child.ParseSingleToken(d, parseResult);
                                }
                            }
                            if (child.EndNode)
                            {
                                //The command string is empty and we are end node
                                parseResult.Callback = child.Callback;
                            }
                        }
                    }
                }
            }
            else if (!node.Children.Any())
            {
                if (node.EndNode)
                {
                    //The command string is empty and we are end node
                    parseResult.Callback = node.Callback;
                }
            }
            else
            {
                foreach (var option in data)
                {
                    foreach (var child in node.Children)
                    {
                        if (child.Name == option.Name)
                        {
                            //This is a argument with a value
                            if (option.Value is not null && option.Value is string d)
                            {
                                if (child.CanParse(d))
                                {
                                    child.ParseSingleToken(d, parseResult);
                                }
                            }

                            if (option.Options is not null)
                            {
                                ParseOptions(child, option.Options, parseResult);
                            }
                        }
                    }
                }
            }
        }