using System;
using System.Collections.Generic;
using System.IO;

class FSObject
{
    public string Name;                      
    public FSObject Parent;                  
    public List<FSObject> Children = new();  
    public bool IsFolder;                    
    public string Content;                   
}

class Program
{
    static FSObject Root = new FSObject { Name = "c:", IsFolder = true }; 
    static FSObject Current = Root;                                      
    static Dictionary<string, string> RealFiles = new();                 

    static void Main()
    {
        // cikls komandu ievade
        while (true)
        {
            Console.Write(GetPath() + "> ");
            var input = Console.ReadLine().Trim().ToLower();
            if (input == "exit" || input == "bye") break;
            ExecuteCommand(input.Split(' '));
        }
    }

    // atgriež ceļu no saknes līdz aktuālajai mapei
    static string GetPath()
    {
        var path = "";
        var current = Current;
        while (current != null)
        {
            path = $"/{current.Name}{path}";
            current = current.Parent;
        }
        return path;
    }

    // komandas izpildes funkcija
    static void ExecuteCommand(string[] parts)
    {
        if (parts.Length == 0) return;

        try
        {
            switch (parts[0])
            {
                case "mkdir": CreateItems(parts, true); break;   // izveidot mapi
                case "create": CreateItems(parts, false); break; // izveidot failu
                case "rm": DeleteItems(parts, true); break;      // dzēst mapi
                case "del": DeleteItems(parts, false); break;    // dzēst failu
                case "dir": ShowDir(parts); break;               // parādīt saturu
                case "cd": ChangeDir(parts); break;              // mainīt direktoriju
                case "edit": EditFile(parts); break;             // parādīt faila saturu
                default: Console.WriteLine("Nezināma komanda"); break;
            }
        }
        catch (Exception ex) { Console.WriteLine("Kļūda: " + ex.Message); }
    }

    // izveido failus vai mapes
    static void CreateItems(string[] parts, bool isFolder)
    {
        if (parts.Length < 2) throw new Exception("Norādi nosaukumu");

        for (int i = 1; i < parts.Length && i < 4; i++)
        {
            if (Current.Children.Exists(x => x.Name.Equals(parts[i], StringComparison.OrdinalIgnoreCase)))
                throw new Exception($"{parts[i]} jau eksistē");

            Current.Children.Add(new FSObject {
                Name = parts[i],
                IsFolder = isFolder,
                Parent = Current
            });
            Console.WriteLine($"Izveidots {(isFolder ? "mape" : "fails")}: {parts[i]}");
        }
    }

    // dzēš failus vai mapes
    static void DeleteItems(string[] parts, bool isFolder)
    {
        if (parts.Length < 2) throw new Exception("Norādi nosaukumu");

        for (int i = 1; i < parts.Length && i < 4; i++)
        {
            var item = Current.Children.Find(x =>
                x.Name.Equals(parts[i], StringComparison.OrdinalIgnoreCase) &&
                x.IsFolder == isFolder);

            if (item == null) throw new Exception($"{parts[i]} nav atrasts");

            if (isFolder && item.Children.Count > 0)
            {
                Console.Write($"Vai izdzēst {item.Name} un visu saturu? (y/n): ");
                if (Console.ReadLine().ToLower() != "y") continue;
            }

            Current.Children.Remove(item);

            // ja fails bija reāls, dzēš arī no diska
            if (!isFolder && RealFiles.ContainsKey(item.Name))
            {
                File.Delete(RealFiles[item.Name]);
                RealFiles.Remove(item.Name);
            }

            Console.WriteLine($"Izdzēsts: {item.Name}");
        }
    }

    // rāda direktorijas saturu vai saglabā to failā
    static void ShowDir(string[] parts)
    {
        if (parts.Length == 1)
        {
            Current.Children.ForEach(x =>
                Console.WriteLine(x.IsFolder ? $"/{x.Name}/" : $"/~{x.Name}~"));
        }
        else if (parts.Length == 3 && parts[1] == ">")
        {
            var file = Current.Children.Find(x =>
                !x.IsFolder && x.Name.Equals(parts[2], StringComparison.OrdinalIgnoreCase))
                ?? new FSObject { Name = parts[2], Parent = Current };

            using (var sw = new StreamWriter(file.Name))
            {
                Current.Children.ForEach(x =>
                    sw.WriteLine(x.IsFolder ? $"/{x.Name}/" : $"/~{x.Name}~"));
            }

            RealFiles[file.Name] = Path.GetFullPath(file.Name);
            Console.WriteLine($"Saglabāts failā: {file.Name}");
        }
    }

    // maina pašreizējo mapi
    static void ChangeDir(string[] parts)
    {
        if (parts.Length != 2) throw new Exception("Lieto: cd [mape] vai cd .. vai cd /");

        if (parts[1] == "..") Current = Current.Parent ?? Current;
        else if (parts[1] == "/") Current = Root;
        else
        {
            var folder = Current.Children.Find(x =>
                x.IsFolder && x.Name.Equals(parts[1], StringComparison.OrdinalIgnoreCase));
            if (folder == null) throw new Exception("Mape nav atrasta");
            Current = folder;
        }
    }

    // parāda faila saturu, ja tas ir īsts fails uz diska
    static void EditFile(string[] parts)
    {
        if (parts.Length != 2) throw new Exception("Norādi faila nosaukumu");

        var file = Current.Children.Find(x =>
            !x.IsFolder && x.Name.Equals(parts[1], StringComparison.OrdinalIgnoreCase));

        if (file == null) throw new Exception("Fails nav atrasts");

        if (RealFiles.TryGetValue(file.Name, out var path))
            Console.WriteLine(File.ReadAllText(path));
        else
            Console.WriteLine("Fails nav saglabāts uz diska");
    }
}

    // https://www.w3schools.com/cs/cs_switch.php
    // https://learn.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings