@using LANCommander.Extensions;

<GridRow Class="text-editor">
    <GridCol Span="6">
        <Tree TItem="FileTreeNode"
              DataSource="FileTree"
              TitleExpression="x => x.DataItem.Name"
              ChildrenExpression="x => x.DataItem.Children"
              IsLeafExpression="x => !x.DataItem.HasChildren"
              OnDblClick="(args) => OpenFile(args.Node.DataItem)">
        </Tree>
    </GridCol>

    <GridCol Span="18">
        <Tabs Type="@TabType.EditableCard" HideAdd @bind-ActiveKey="ActiveFile" OnClose="OnTabClose">
            @foreach (var file in OpenFiles)
            {
                <TextEditorPane FilePath="@file" />
            }
        </Tabs>
    </GridCol>
</GridRow>

<style>
    .monaco-editor-container {
        min-height: 600px;
    }

    .text-editor {
        background: #252525;
        min-height: 600px;
    }

    .text-editor .ant-tree {
        background: none;
        color: #ccc;
        padding-top: 16px;
        padding-left: 8px;
    }

    .text-editor .ant-tree-node-content-wrapper:hover {
        background: none;
    }

    .text-editor .ant-tree-treenode:hover {
        background: #37373d;
    }

    .text-editor .text-editor-info-bar {
        padding-left: 16px;
        padding-right: 16px;
        margin-top: 0;
        margin-bottom: 0;
        padding-top: 8px;
        padding-bottom: 8px;
        background: #1e1e1e;
    }

    .text-editor .text-editor-info-bar .ant-breadcrumb,
    .text-editor .ant-breadcrumb-separator,
    .text-editor .ant-breadcrumb li:last-child {
        color: #a9a9a9;
    }

    .text-editor .ant-tabs-card.ant-tabs-top > .ant-tabs-nav .ant-tabs-tab,
    .text-editor .ant-tabs-card.ant-tabs-top > div > .ant-tabs-nav .ant-tabs-tab {
        border-radius: 0;
        background: #2d2d2d;
        padding: 4px 10px;
        color: #a9a9a9;
        border: none;
    }

    .text-editor .ant-tabs-card > .ant-tabs-nav .ant-tabs-tab-active,
    .text-editor .ant-tabs-card > div > .ant-tabs-nav .ant-tabs-tab-active {
        background: #1e1e1e !important;
    }

    .text-editor .ant-tabs-tab .ant-tabs-tab-remove .anticon {
        color: #a9a9a9;
    }

    .text-editor .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn,
    .text-editor .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-remove .anticon {
        color: #fff;
    }

    .text-editor .ant-tabs-top > .ant-tabs-nav::before {
        border: none;
    }

    .text-editor .ant-tabs-nav {
        margin: 0;
    }
</style>

@code {
    [Parameter] public string WorkingDirectory { get; set; }

    StandaloneCodeEditor? Editor;

    IEnumerable<string> Files;
    HashSet<FileTreeNode> FileTree { get; set; } = new HashSet<FileTreeNode>();
    string CurrentFile = "";

    List<string> OpenFiles = new List<string>();
    string ActiveFile;

    private StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
    {
        return new StandaloneEditorConstructionOptions
        {
            AutomaticLayout = true,
            Theme = "vs-dark"
        };
    }

    protected override async Task OnParametersSetAsync()
    {
        var root = new FileTreeNode
            {
                Name = "/",
                FullName = WorkingDirectory,
                IsExpanded = true
            };

        root.PopulateChildren(WorkingDirectory);

        foreach (var child in root.Children)
        {
            FileTree.Add(child);
        }
    }

    private void OpenFile(FileTreeNode node)
    {
        if (!OpenFiles.Contains(node.FullName))
            OpenFiles.Add(node.FullName);

        ActiveFile = node.FullName;

        StateHasChanged();
    }

    private void OnTabClose(string key)
    {
        OpenFiles.Remove(key);

        StateHasChanged();
    }

    public class FileTreeNode
    {
        public string Name { get; set; }
        public string FullName { get; set; }
        public bool IsExpanded { get; set; } = false;
        public bool IsDirectory { get; set; } = false;
        public bool HasChildren => Children != null && Children.Count > 0;
        public HashSet<FileTreeNode> Children { get; set; } = new HashSet<FileTreeNode>();

        public void PopulateChildren(string path)
        {
            if (Directory.Exists(path))
            {
                try
                {
                    foreach (var file in Directory.GetFiles(path))
                    {
                        var fileInfo = new FileInfo(file);

                        Children.Add(new FileTreeNode
                        {
                            Name = fileInfo.Name,
                            FullName = fileInfo.FullName,
                            IsDirectory = false
                        });
                    }
                }
                catch { }

                try
                {
                    foreach (var directory in Directory.GetDirectories(path))
                    {
                        var directoryInfo = new DirectoryInfo(directory);

                        var child = new FileTreeNode
                        {
                            Name = directoryInfo.Name,
                            FullName = directoryInfo.FullName,
                            IsDirectory = true
                        };

                        child.PopulateChildren(directoryInfo.FullName);

                        Children.Add(child);
                    }
                }
                catch { }
            }
        }

        public void PopulateChildren(IEnumerable<string> paths)
        {
            var childPaths = paths.Where(p => p.StartsWith(FullName) && p.EndsWith(Path.PathSeparator));
            var directChildren = childPaths.Where(p => p != FullName && p.Substring(FullName.Length + 1).TrimEnd(Path.PathSeparator).Split(Path.PathSeparator).Length == 1);

            foreach (var directChild in directChildren)
            {
                var child = new FileTreeNode()
                {
                    FullName = directChild,
                    Name = directChild.Substring(FullName.Length).TrimEnd(Path.PathSeparator)
                };

                child.PopulateChildren(paths);

                Children.Add(child);
            }
        }
    }
}
