from os import path
from typing import NamedTuple, TypedDict

from platformdirs import PlatformDirs
from rich._spinners import SPINNERS

dirs = PlatformDirs("rovr", ".")  # Ah yes, my name is "."


class PlatformDirsVars(TypedDict):
    DOCUMENTS: str
    DOWNLOADS: str
    MUSIC: str
    PICTURES: str
    DESKTOP: str
    HOME: str
    VIDEOS: str
    CONFIG: str


VAR_TO_DIR: PlatformDirsVars = {
    "DOCUMENTS": dirs.user_documents_dir.replace("\\", "/"),
    "DOWNLOADS": dirs.user_downloads_dir.replace("\\", "/"),
    "MUSIC": dirs.user_music_dir.replace("\\", "/"),
    "PICTURES": dirs.user_pictures_dir.replace("\\", "/"),
    "DESKTOP": dirs.user_desktop_dir.replace("\\", "/"),
    "HOME": path.expanduser("~").replace("\\", "/"),
    "VIDEOS": dirs.user_videos_dir.replace("\\", "/"),
    "CONFIG": dirs.user_config_dir.replace("\\", "/"),
}

ASCII_ICONS = {
    "general": {
        "new": ["+", "green"],
        "open": ["O", "blue"],
        "save": ["S", "cyan"],
        "search": ["?", "orange"],
        "refresh": ["R", "teal"],
        "settings": ["#", "gray"],
        "close": ["X", "red"],
        "up": ["^", "white"],
        "down": ["v", "white"],
        "left": ["<", "white"],
        "right": [">", "white"],
        "home": ["~", "indigo"],
        "check": ["/", "white"],
        "copy": ["C", "white"],
        "paste": ["P", "white"],
        "cut": ["X", "white"],
        "rename": ["R", "white"],
        "delete": ["D", "red"],
        "zip": ["Z", "yellow"],
    },
    "folder": {
        "default": ["D", "#DAA520"],
        "open": ["O", "orange"],
        "empty": ["E", "yellow"],
        "home": ["~", "cyan"],
        ":/drive:": ["D", "white"],
    },
    "file": {
        "default": ["F", "#ffffff"],
    },
}

ICONS = {
    "general": {
        "new": ["\uea7f", "green"],
        "open": ["\uf07c", "blue"],
        "save": ["\uf0c7", "cyan"],
        "search": ["\uf002", "orange"],
        "refresh": ["\uf021", "teal"],
        "settings": ["\uf013", "gray"],
        "close": ["\uf00d", "red"],
        "up": ["\uf062", "white"],
        "down": ["\uf063", "white"],
        "left": ["\uf060", "white"],
        "right": ["\uf061", "white"],
        "home": ["\uf015", "indigo"],
        "check": ["\uf00c", "green"],
        "copy": ["\uf0c5", "white"],
        "paste": ["\uf429", "white"],
        "cut": ["\uf0c4", "white"],
        "rename": ["\uf246", "white"],
        "delete": ["\uf014", "red"],
        "zip": ["\uf410", "yellow"],
        "link": ["\U000f0337", "cyan"],
        "symlink": ["\uf481", "cyan"],
        "special": ["\uf2dc", "magenta"],
    },
    "sorting": {
        "alpha_asc": ["\uf15d", "white"],
        "alpha_desc": ["\uf15e", "white"],
        "numeric_asc": ["\uf162", "white"],
        "numeric_desc": ["\uf163", "white"],
        "time_asc": ["\U000f1549", "white"],
        "time_desc": ["\U000f154b", "white"],
        "alpha_alt_asc": ["\U000f05bd", "white"],
        "alpha_alt_desc": ["\U000f05bf", "white"],
        "time_alt_asc": ["\U000f154a", "white"],
        "time_alt_desc": ["\U000f154c", "white"],
        "numeric_alt_asc": ["\U000f090d", "white"],
        "numeric_alt_desc": ["\U000f0ad2", "white"],
        "generic_asc": ["\U000f04bc", "white"],
        "generic_desc": ["\U000f033c", "white"],
    },
    "folder": {
        "default": ["\uf07b", "#DAA520"],
        "api": ["\U000f048d", "#4CAF50"],
        "assets": ["\uf0c7", "#F1C40F"],
        "astro": ["\ue735", "#ed45cf"],
        "atom": ["\ue764", "#84AFDB"],
        "audio": ["\U000f1359", "#FF5252"],
        "backups": ["\U000f006f", "#3498DB"],
        "bash": ["\U000f1183", "#4EAA25"],
        "bin": ["\ue5fc", "#F39C12"],
        "build": ["\uf487", "#F1C40F"],
        "bun": ["\ue76f", "#fcf3e5"],
        "cache": ["\U000f00e8", "#7F8C8D"],
        "cargo": ["\ue68b", "#F74C00"],
        "conf": ["\ue615", "#2C3E50"],
        "config": ["\ue5fc", "#3498DB"],
        "contacts": ["\U000f024c", "coral"],
        "content": ["\uf0c7", "#3498DB"],
        "css": ["\ue749", "#1572B6"],
        "desktop": ["\uf108", "grey"],
        "device": ["\U000f072b", "orange"],
        "dist": ["\U000f107f", "#F1C40F"],
        "doc": ["\uf02d", "#3498DB"],
        "documents": ["\U000f0c82", "coral"],
        "downloads": ["\U000f024d", "lime"],
        "empty": ["\uf115", "yellow"],
        "etc": ["\ue5fc", "#7F8C8D"],
        "favorites": ["\U000f069d", "orange"],
        "git": ["\ue5fb", "#F05032"],
        "github": ["\ue5fd", "#181717"],
        "gitlab": ["\ue7eb", "#e5543c"],
        "gradle": ["\ue660", "#41bcc5"],
        "hidden": ["\U000f179e", "gray"],
        "home": ["\uf015", "cyan"],
        "icons": ["\uf005", "#F1C40F"],
        "img": ["\uf1c5", "#3498DB"],
        "include": ["\ue5fc", "#3498DB"],
        "java": ["\ue256", "#007396"],
        "js": ["\ue74e", "#F7DF1E"],
        "lib": ["\uf121", "#3498DB"],
        "log": ["\uf18d", "#7F8C8D"],
        "media": ["\uf40f", "#E74C3C"],
        "music": ["\U000f1359", "magenta"],
        "node_modules": ["\ue5fa", "#83CD29"],
        "onedrive": ["\U000f03ca", "#22a8de"],
        "open": ["\uf07c", "orange"],
        "pictures": ["\U000f024f", "purple"],
        "pipe": ["\U000f0232", "blue"],
        "pnpm": ["\ue865", "#4c4c4c"],
        "rovr": ["\uf14e", "teal"],
        "scripts": ["\uf489", "#2ECC71"],
        "socket": ["\U000f01a8", "purple"],
        "src": ["\U000f19fc", "#3498DB"],
        "static": ["\uf0c7", "#3498DB"],
        "styles": ["\ue749", "#1572B6"],
        "templates": ["\uf32e", "#7F8C8D"],
        "tests": ["\U000f0668", "#9B59B6"],
        "trash": ["\uf1f8", "red"],
        "ts": ["\ue628", "#3178C6"],
        "vendor": ["\U000f0ae6", "#7F8C8D"],
        "videos": ["\U000f19fa", "violet"],
        "vscode": ["\ue70c", "#23a9f2"],
        ":/drive:": ["\uf0a0", "white"],
    },
    # shout out to
    # - https://github.com/acarl005/ls-go
    # - https://github.com/eza-community/eza
    # - https://github.com/lsd-rs/lsd
    # for their icons, and
    # - Claude 3.7 thinking
    # for spending time to set each icon's color
    "file": {
        "default": ["\uf016", "#ffffff"],
        "hidden": ["\U000f0613", "gray"],
        "a": ["\ue624", "#8892BF"],
        "ai": ["\ue7b4", "#FF9A00"],
        "android": ["\uf17b", "#3DDC84"],
        "apk": ["\ue70e", "#3DDC84"],
        "apple": ["\ue711", "#999999"],
        "asm": ["\uf471", "#6E4C13"],
        "astro": ["\ue735", "#ed45cf"],
        "audio": ["\uf001", "#FF5252"],
        "avi": ["\uf008", "#8E44AD"],
        "avif": ["\uf1c5", "#E74C3C"],
        "avro": ["\ue60b", "#C7254E"],
        "bash": ["\uf489", "#4EAA25"],
        "binary": ["\ueae8", "#FF7844"],
        "bmp": ["\uf1c5", "#E74C3C"],
        "bun": ["\ue76f", "#fcf3e5"],
        "c": ["\ue61e", "#0188d2"],
        "cc": ["\ue61d", "#0188d2"],
        "certificate": ["\ueafa", "yellow"],
        "cfg": ["\ue615", "#8B8B8B"],
        "cjs": ["\ue74e", "#F7DF1E"],
        "clj": ["\ue768", "#68b338"],
        "cmd": ["\uf17a", "#0078D6"],
        "coffee": ["\uf0f4", "#2F2625"],
        "conf": ["\ue615", "#8B8B8B"],
        "cpp": ["\ue61d", "#0188d2"],
        "crate": ["\ued75", "#e8ad3a"],
        "cs": ["\U000f031b", "#239120"],
        "css": ["\ue749", "#1572B6"],
        "csv": ["\uf1c3", "#217346"],
        "dart": ["\ue798", "#0175C2"],
        "db": ["\uf1c0", "#FF8400"],
        "deb": ["\uf187", "#A80030"],
        "diff": ["\ue728", "#3498DB"],
        "doc": ["\uf1c2", "#2B579A"],
        "dockerfile": ["\uf308", "#2496ED"],
        "docx": ["\uf1c2", "#2B579A"],
        "ebook": ["\ue28b", "#67b500"],
        "elixir": ["\ue62d", "#4B275F"],
        "elm": ["\ue62c", "#60B5CC"],
        "emacs": ["\U000f0172", "#7F5AB6"],
        "env": ["\uf462", "#ECD53F"],
        "eot": ["\uf031", "#3498DB"],
        "epub": ["\ue28a", "#67b500"],
        "erlang": ["\ue7b1", "#A90533"],
        "exe": ["\uf17a", "#0078D6"],
        "f": ["\uf24f", "#8e44ad"],
        "fish": ["\uf489", "#2ecc71"],
        "font": ["\uf031", "#3498DB"],
        "fs": ["\ue7a7", "#378BBA"],
        "gb": ["\ue272", "#f1c40f"],
        "gform": ["\uf298", "#9b59b6"],
        "gif": ["\uf1c5", "#E74C3C"],
        "git": ["\uf1d3", "#F05032"],
        "gitlab": ["\ue7eb", "#e5543c"],
        "go": ["\ue627", "#00ADD8"],
        "gradle": ["\ue660", "#41bcc5"],
        "graphql": ["\ue662", "#E10098"],
        "groovy": ["\ue775", "#4298B8"],
        "gruntfile.js": ["\ue611", "#F78C40"],
        "gulpfile.js": ["\ue610", "#DB4446"],
        "gv": ["\U000f1049", "#9b59b6"],
        "h": ["\uf0fd", "#3498db"],
        "haml": ["\ue664", "#ECECEC"],
        "hbs": ["\ue60f", "#F7931E"],
        "heic": ["\uf1c5", "#E74C3C"],
        "hpp": ["\uf0fd", "#3498db"],
        "hs": ["\ue777", "#5D4F85"],
        "htm": ["\uf13b", "#E44D26"],
        "html": ["\uf13b", "#E44D26"],
        "hx": ["\ue666", "#EA8220"],
        "ics": ["\uf073", "#f1c40f"],
        "image": ["\uf1c5", "#E74C3C"],
        "iml": ["\ue7b5", "#F74E1E"],
        "ini": ["\ue615", "#f1c40f"],
        "ino": ["\ue255", "#00979D"],
        "installable": ["\U000f19d5", "#9b59b6"],
        "ipynb": ["\ue606", "#F37626"],
        "iso": ["\uf1c0", "#f1c40f"],
        "jade": ["\ue66c", "#00A4BC"],
        "java": ["\ue738", "#007396"],
        "jenkinsfile": ["\ue767", "#D33833"],
        "jl": ["\ue624", "#9558B2"],
        "jpeg": ["\uf1c5", "#E74C3C"],
        "jpg": ["\uf1c5", "#E74C3C"],
        "js": ["\ue74e", "#F7DF1E"],
        "json": ["\ue60b", "#3498DB"],
        "jsx": ["\ue7ba", "#61DAFB"],
        "jule": ["\ue80c", "#5f7389"],
        "key": ["\U000f0306", "#F1C40F"],
        "ko": ["\uebc6", "#9b59b6"],
        "kt": ["\ue634", "#7F52FF"],
        "less": ["\ue758", "#1D365D"],
        "license": ["\ue60a", "#E7E480"],
        "lisp": ["\ue6b0", "black"],
        "lock": ["\uf023", "#F1C40F"],
        "log": ["\uf18d", "#7F8C8D"],
        "lua": ["\ue620", "#000080"],
        "maintainers": ["\uf0c0", "#7F8C8D"],
        "makefile": ["\ue615", "#9B7761"],
        "markdown": ["\uf48a", "#7f8c8d"],
        "mjs": ["\ue74e", "#F7DF1E"],
        "ml": ["\ue67a", "#EC6813"],
        "mov": ["\uf008", "#8E44AD"],
        "mp3": ["\uf001", "#FF5252"],
        "mp4": ["\uf008", "#8E44AD"],
        "msexcel": ["\uf1c3", "#217346"],
        "msonenote": ["\U000f0747", "#7719AA"],
        "msppt": ["\uf1c4", "#D24726"],
        "msword": ["\uf1c2", "#2B579A"],
        "mustache": ["\ue60f", "#F0772B"],
        "nc": ["\U000f02c1", "#F1C40F"],
        "nim": ["\ue677", "#FFC200"],
        "nix": ["\uf313", "#5277C3"],
        "npmignore": ["\ue71e", "#CB3837"],
        "o": ["\ueae8", "#FF7844"],
        "otf": ["\uf031", "#3498DB"],
        "package": ["\U000f03d7", "#CB3837"],
        "passwd": ["\uf023", "#F1C40F"],
        "patch": ["\ue728", "#E67E22"],
        "pdf": ["\uf1c1", "#E74C3C"],
        "pem": ["\U000f0306", "#F1C40F"],
        "php": ["\ue608", "#8892BF"],
        "pl": ["\ue67e", "#0073A1"],
        "png": ["\uf1c5", "#E74C3C"],
        "prisma": ["\ue684", "#5A67D8"],
        "ps1": ["\uf489", "#5391FE"],
        "psd": ["\ue7b8", "#31A8FF"],
        "pub": ["\U000f0306", "#F1C40F"],
        "pug": ["\ue686", "#A86454"],
        "pwsh": ["\ue86c", "#5391FE"],
        "py": ["\ue606", "#FFD43B"],
        "pyc": ["\ue606", "#3776AB"],
        "r": ["\U000f07d4", "#276DC3"],
        "rake": ["\ue21e", "#CC342D"],
        "rar": ["\uf410", "#E74C3C"],
        "rb": ["\ue21e", "#CC342D"],
        "rdb": ["\ue76d", "#9B59B6"],
        "robots": ["\uee0d", "#00B496"],
        "rpm": ["\uf17c", "#E74C3C"],
        "rs": ["\ue68b", "#F74C00"],
        "rss": ["\uf09e", "#F26522"],
        "rst": ["\U000f016b", "#2ecc71"],
        "rubydoc": ["\ue73b", "#CC342D"],
        "sass": ["\ue603", "#CD6799"],
        "scala": ["\ue737", "#DC322F"],
        "scheme": ["\ue6b1", "black"],
        "scss": ["\ue603", "#CD6799"],
        "security": ["\U000f0483", "red"],
        "sh": ["\uf489", "#4EAA25"],
        "shell": ["\uf489", "#4EAA25"],
        "shield_check": ["\U000f0565", "green"],
        "shield_lock": ["\U000f099d", "teal"],
        "shp": ["\U000f065e", "#F1C40F"],
        "signed_file": ["\U000f19c3", "blue"],
        "so": ["\ue624", "#8892BF"],
        "sol": ["\U000f086a", "#65AFFF"],
        "sql": ["\uf1c0", "#4479A1"],
        "sqlite": ["\ue7c4", "#3498DB"],
        "styl": ["\ue600", "#B3D107"],
        "svelte": ["\ue697", "#FF3E00"],
        "svg": ["\uf1c5", "#FFB13B"],
        "swift": ["\ue755", "#F05138"],
        "tar": ["\uf410", "#E74C3C"],
        "tex": ["\ue600", "#3D6117"],
        "text": ["\uf15c", "#FFFFFF"],
        "tf": ["\ue69a", "#7B42BC"],
        "tgz": ["\uf410", "#E74C3C"],
        "toml": ["\ue60b", "#9C4221"],
        "ts": ["\ue628", "#3178C6"],
        "tsx": ["\ue7ba", "#61DAFB"],
        "ttf": ["\uf031", "#3498DB"],
        "twig": ["\ue61c", "#8BC34A"],
        "txt": ["\uf15c", "#7F8C8D"],
        "typst": ["\uf37f", "#5BC0AF"],
        "vagrantfile": ["\ue615", "#1868F2"],
        "version_lock": ["\U000f1757", "#F1C40F"],
        "video": ["\uf008", "#8E44AD"],
        "vim": ["\ue62b", "#019733"],
        "vite": ["\ue8d7", "#ae47fe"],
        "vue": ["\U000f0844", "#41B883"],
        "wav": ["\uf001", "#FF5252"],
        "webp": ["\uf1c5", "#E74C3C"],
        "windows": ["\uf17a", "#0078D6"],
        "woff": ["\uf031", "#3498DB"],
        "woff2": ["\uf031", "#3498DB"],
        "xml": ["\uf121", "#0085C3"],
        "xsl": ["\uf121", "#5A96C6"],
        "yaml": ["\ue60b", "#F71A10"],
        "yml": ["\ue60b", "#F71A10"],
        "zig": ["\ue6a9", "#F7A41D"],
        "zip": ["\uf410", "#E74C3C"],
    },
}

FOLDER_MAP = {
    # api
    "api": "api",
    # assets
    "assets": "assets",
    "fonts": "assets",
    "icons": "icons",
    "images": "pictures",
    "textures": "pictures",
    # audio
    "audio": "audio",
    "music": "music",
    "songs": "music",
    "sounds": "music",
    # backups
    "backups": "backups",
    "backup": "backups",
    # build
    "build": "build",
    "dist": "dist",
    "release": "dist",
    "releases": "dist",
    "out": "dist",
    "output": "dist",
    # cache
    ".cache": "cache",
    "cache": "cache",
    ".ccls-cache": "cache",
    ".mypy_cache": "cache",
    "__pycache__": "cache",
    # cargo
    "cargo": "cargo",
    ".cargo": "cargo",
    # config
    ".atom": "atom",
    ".bpython_history": "py",
    ".config": "config",
    "conf": "conf",
    "conf.d": "conf",
    "config": "config",
    # content
    "content": "content",
    # css
    "css": "css",
    "sass": "sass",
    "scss": "sass",
    "styles": "styles",
    # desktop
    "desktop": "desktop",
    # development
    ".dbus": "dev",
    ".doom.d": "dev",
    ".electron-gyp": "dev",
    ".emacs.d": "dev",
    ".idlerc": "dev",
    ".java": "java",
    ".jupyter": "py",
    ".node-gyp": "js",
    ".npm": "js",
    ".nvm": "js",
    ".pyenv": "py",
    ".python-version": "py",
    ".rustup": "cargo",
    ".rvm": "rb",
    ".tox": "py",
    ".venv": "py",
    "dev": "src",
    "venv": "py",
    # documents
    "book": "documents",
    "books": "documents",
    "doc": "doc",
    "docs": "documents",
    "documents": "documents",
    "licenses": "documents",
    # downloads
    "download": "downloads",
    "downloads": "downloads",
    # git
    ".git": "git",
    ".github": "github",
    ".gitlab": "gitlab",
    ".gitlab-ci": "gitlab",
    # gradle
    "gradle": "gradle",
    # home
    "home": "home",
    # include
    "include": "include",
    # java
    "java": "java",
    # js
    "js": "js",
    "jsx": "js",
    "mjs": "js",
    "node_modules": "node_modules",
    "ts": "ts",
    "tsx": "ts",
    # lib
    "lib": "lib",
    "lib32": "lib",
    "lib64": "lib",
    "library": "lib",
    "libraries": "lib",
    "libexec": "lib",
    # logs
    "log": "log",
    "logs": "log",
    # media
    "media": "media",
    # onedrive
    "onedrive": "onedrive",
    # pictures
    "img": "pictures",
    "image": "pictures",
    "photos": "pictures",
    "pictures": "pictures",
    # rovr
    "rovr": "rovr",
    # scripts
    "bin": "bin",
    "script": "scripts",
    "scripts": "scripts",
    # src
    "source": "src",
    "src": "src",
    # static
    "static": "static",
    # templates
    "template": "templates",
    "templates": "templates",
    # tests
    "specs": "tests",
    "test": "tests",
    "tests": "tests",
    # vendor
    "vendor": "vendor",
    "vendors": "vendor",
    # videos
    "movies": "videos",
    "video": "videos",
    "videos": "videos",
    # vscode
    ".vscode": "vscode",
    # frameworks
    ".astro": "astro",
    ".gradle": "gradle",
    ".pnpm": "pnpm",
}

FILE_MAP = {
    # Text files
    ".log": "log",
    ".markdown": "markdown",
    ".md": "markdown",
    ".rdoc": "markdown",
    ".rst": "rst",
    ".text": "text",
    ".txt": "txt",
    # Image files
    ".ai": "ai",
    ".apng": "image",
    ".avif": "image",
    ".bmp": "image",
    ".gif": "image",
    ".heic": "image",
    ".heif": "image",
    ".heix": "image",
    ".ico": "image",
    ".jpeg": "image",
    ".jpg": "image",
    ".png": "image",
    ".psd": "psd",
    ".pxm": "image",
    ".svg": "image",
    ".webp": "image",
    ".xcf": "image",
    # Audio files
    ".ape": "audio",
    ".cue": "audio",
    ".flac": "audio",
    ".m4a": "audio",
    ".mp3": "audio",
    ".ogg": "audio",
    ".opus": "audio",
    ".vlc": "audio",
    ".wav": "audio",
    ".wma": "audio",
    ".wpl": "audio",
    # Video files
    ".avi": "video",
    ".flv": "video",
    ".m4v": "video",
    ".mkv": "video",
    ".mov": "video",
    ".mp4": "video",
    ".ogv": "video",
    ".webm": "video",
    ".wmv": "video",
    # Subtitle files
    ".sbv": "text",
    ".scc": "text",
    ".smi": "text",
    ".srt": "text",
    ".sub": "text",
    ".vtt": "text",
    # Document files
    ".csv": "csv",
    ".doc": "msword",
    ".docx": "msword",
    ".gdoc": "msword",
    ".gform": "gform",
    ".gsheet": "msexcel",
    ".gslides": "msppt",
    ".ics": "ics",
    ".odp": "msppt",
    ".ods": "msexcel",
    ".odt": "msword",
    ".one": "msonenote",
    ".onetoc2": "msonenote",
    ".pdf": "pdf",
    ".ppt": "msppt",
    ".pptx": "msppt",
    ".rtf": "text",
    ".xls": "msexcel",
    ".xlsx": "msexcel",
    # Ebook files
    ".ebook": "ebook",
    ".epub": "ebook",
    ".mobi": "ebook",
    # Archive files
    ".7z": "zip",
    ".ar": "zip",
    ".bz2": "zip",
    ".deb": "deb",
    ".gz": "zip",
    ".iso": "iso",
    ".lz": "zip",
    ".pkg": "zip",
    ".rar": "zip",
    ".rpm": "rpm",
    ".tar": "zip",
    ".tbz": "zip",
    ".tbz2": "zip",
    ".tgz": "zip",
    ".xbps": "zip",
    ".xz": "zip",
    ".zip": "zip",
    ".zst": "zip",
    # Programming files
    ".a": "a",
    ".asm": "asm",
    ".asp": "html",
    ".astro": "astro",
    ".awk": "shell",
    ".bash": "shell",
    ".bat": "shell",
    ".c": "c",
    ".cc": "cc",
    ".cjs": "cjs",
    ".class": "java",
    ".clj": "clj",
    ".cljs": "clj",
    ".cmd": "cmd",
    ".coffee": "coffee",
    ".cpp": "cpp",
    ".cp": "cpp",
    ".cs": "cs",
    ".csh": "shell",
    ".css": "css",
    ".csproj": "cs",
    ".cshtml": "html",
    ".csx": "cs",
    ".cts": "ts",
    ".c++": "cpp",
    ".cxx": "cpp",
    ".cypher": "db",
    ".dart": "dart",
    ".el": "emacs",
    ".elc": "emacs",
    ".elm": "elm",
    ".elv": "shell",
    ".erb": "rb",
    ".erl": "erlang",
    ".ex": "elixir",
    ".exs": "elixir",
    ".f": "f",
    ".fish": "fish",
    ".fnl": "lua",
    ".fs": "fs",
    ".fsi": "fs",
    ".fsx": "fs",
    ".go": "go",
    ".gradle": "gradle",
    ".groovy": "groovy",
    ".h": "h",
    ".haml": "haml",
    ".hbs": "hbs",
    ".hh": "h",
    ".hpp": "hpp",
    ".hs": "hs",
    ".htm": "html",
    ".html": "html",
    ".hx": "hx",
    ".ipynb": "py",
    ".jade": "jade",
    ".jar": "java",
    ".java": "java",
    ".jinja": "html",
    ".jl": "jl",
    ".js": "js",
    ".json": "json",
    ".jsonc": "json",
    ".jsx": "jsx",
    ".jule": "jule",
    ".kt": "kt",
    ".kts": "kt",
    ".less": "less",
    ".lhs": "hs",
    ".lisp": "lisp",
    ".lua": "lua",
    ".malloy": "sql",
    ".mjs": "mjs",
    ".ml": "ml",
    ".mli": "ml",
    ".mll": "ml",
    ".mly": "ml",
    ".mts": "ts",
    ".mustache": "mustache",
    ".nim": "nim",
    ".nimble": "nim",
    ".nix": "nix",
    ".nu": "shell",
    ".php": "php",
    ".phar": "php",
    ".pl": "pl",
    ".plx": "pl",
    ".pm": "pl",
    ".pod": "pl",
    ".pp": "rb",
    ".prql": "sql",
    ".ps1": "pwsh",
    ".pug": "pug",
    ".py": "py",
    ".pyc": "py",
    ".pyw": "py",
    ".r": "r",
    ".rb": "rb",
    ".rdata": "r",
    ".rdb": "rdb",
    ".rds": "r",
    ".rlib": "rs",
    ".rl": "shell",
    ".rs": "rs",
    ".rproj": "r",
    ".rq": "sql",
    ".sass": "sass",
    ".scala": "scala",
    ".scss": "scss",
    ".sh": "sh",
    ".shell": "shell",
    ".sol": "sol",
    ".sql": "sql",
    ".styl": "styl",
    ".stylus": "styl",
    ".svelte": "svelte",
    ".swift": "swift",
    ".tcss": "css",
    ".tex": "tex",
    ".ts": "ts",
    ".tsx": "tsx",
    ".ttf": "ttf",
    ".twig": "twig",
    ".typ": "typst",
    ".typst": "typst",
    ".vim": "vim",
    ".vue": "vue",
    ".woff": "woff",
    ".woff2": "woff2",
    ".zig": "zig",
    ".zon": "toml",
    ".zsh": "shell",
    # Config files
    ".cfg": "cfg",
    ".conf": "conf",
    ".editorconfig": "conf",
    ".env": "env",
    ".flake": "nix",
    ".ini": "ini",
    ".lock": "lock",
    ".npmignore": "npmignore",
    ".properties": "json",
    ".toml": "toml",
    ".yaml": "yaml",
    ".yml": "yml",
    # Git
    ".gitattributes": "git",
    ".gitignore": "git",
    ".gitmodules": "git",
    ".gitkeep": "git",
    # Binary files
    ".bin": "binary",
    ".dll": "windows",
    ".elf": "binary",
    ".exe": "windows",
    ".o": "o",
    ".so": "so",
    ".sym": "binary",
    # Installable
    ".apk": "apk",
    ".msi": "installable",
    ".whl": "installable",
    # Compiled
    ".crate": "crate",
    # Certificates
    ".gpg": "shield_lock",
    ".age": "shield_lock",
    ".signature": "signed_file",
    ".sha1": "shield_check",
    ".sha224": "shield_check",
    ".sha256": "shield_check",
    ".sha384": "shield_check",
    ".sha512": "shield_check",
    ".cert": "certificate",
    ".asc": "shield_lock",
    ".cer": "certificate",
    ".crt": "certificate",
    ".pem": "certificate",
    ".pub": "pub",
    ".sig": "signed_file",
    # Other
    ".bak": "log",
    ".db": "db",
    ".dat": "db",
    ".diff": "diff",
    ".dump": "db",
    ".font": "font",
    ".gb": "gb",
    ".graphql": "graphql",
    ".gv": "gv",
    ".iml": "iml",
    ".ino": "ino",
    ".ko": "ko",
    ".kusto": "db",
    ".ldb": "db",
    ".ld": "binary",
    ".nc": "nc",
    ".old": "log",
    ".orig": "log",
    ".part": "binary",
    ".patch": "patch",
    ".pdb": "binary",
    ".prisma": "prisma",
    ".rmd": "markdown",
    ".shp": "shp",
    ".sqlite": "sqlite",
    ".sqlite3": "sqlite",
    ".swp": "vim",
    ".tf": "tf",
    ".timestamp": "log",
    ".torrent": "link",
    ".xml": "xml",
    ".xul": "xml",
}

EXT_TO_LANG_MAP = {
    ".py": "python",
    ".md": "markdown",
    ".json": "json",
    ".toml": "toml",
    ".yaml": "yaml",
    ".yml": "yaml",
    ".html": "html",
    ".css": "css",
    ".js": "javascript",
    ".rs": "rust",
    ".go": "go",
    ".sql": "sql",
    ".java": "java",
    ".sh": "bash",
    ".xml": "xml",
    ".lock": "toml",
}

FILES_MAP = {
    # python
    ".python-version": "py",
    "pyproject.toml": "package",
    "py.typed": "py",
    "requirements.txt": "package",
    "runtime.txt": "py",
    "setup.py": "py",
    "tox.ini": "py",
    "poetry.lock": "version_lock",
    "uv.lock": "version_lock",
    "Pipfile.lock": "version_lock",
    # rust
    "cargo.lock": "version_lock",
    "cargo.toml": "package",
    "rustfmt.toml": "rs",
    ".release.toml": "rs",
    # npm
    ".npmignore": "npmignore",
    ".npmrc": "npmignore",
    "npmignore": "npmignore",
    "package-lock.json": "version_lock",
    "package.json": "package",
    "yarn.lock": "version_lock",
    ".yarnrc": "package",
    # bun
    "bunfig.toml": "bun",
    "bun.lockb": "bun",
    # web
    "favicon.ico": "html",
    "robots.txt": "robots",
    # shell
    ".bash_history": "shell",
    ".bash_logout": "shell",
    ".bash_profile": "shell",
    ".bashrc": "shell",
    ".cshrc": "shell",
    ".kshrc": "shell",
    ".shellcheckrc": "shell",
    ".zlogin": "shell",
    ".zlogout": "shell",
    ".zprofile": "shell",
    ".zsh_history": "shell",
    ".zshrc": "shell",
    # build files
    "gruntfile.js": "gruntfile.js",
    "gulpfile.js": "gulpfile.js",
    "makefile": "makefile",
    "makefile.ac": "makefile",
    # git
    ".gitattributes": "git",
    ".gitconfig": "git",
    ".git-credentials": "key",
    ".gitignore": "git",
    ".gitkeep": "git",
    ".gitmodules": "git",
    # docker
    "containerfile": "dockerfile",
    "docker-compose.yml": "dockerfile",
    # config
    ".bpython_history": "py",
    ".clang-format": "cfg",
    ".editorconfig": "cfg",
    ".env": "env",
    ".eslintrc.js": "js",
    ".eslintrc.json": "json",
    ".eslintrc.yml": "yml",
    ".htaccess": "cfg",
    ".htpasswd": "cfg",
    ".inputrc": "cfg",
    ".lynxrc": "cfg",
    ".mailcap": "cfg",
    ".mime.types": "cfg",
    ".muttrc": "cfg",
    ".neomuttrc": "cfg",
    ".python_history": "py",
    ".sqlite_history": "db",
    ".viminfo": "vim",
    ".vimrc": "vim",
    ".wgetrc": "cfg",
    ".xinitrc": "cfg",
    ".xmodmap": "cfg",
    ".Xmodmap": "cfg",
    ".xprofile": "cfg",
    ".Xprofile": "cfg",
    ".xresources": "cfg",
    "bspwmrc": "cfg",
    "config.ac": "cfg",
    "config.el": "emacs",
    "config.mk": "cfg",
    "crypttab": "cfg",
    "custom.el": "emacs",
    "dockerfile": "dockerfile",
    "environment": "env",
    "fstab": "cfg",
    "group": "cfg",
    "gshadow": "cfg",
    "hostname": "cfg",
    "hosts": "cfg",
    "htoprc": "cfg",
    "init.el": "emacs",
    "kdeglobals": "cfg",
    "kdenliverc": "cfg",
    "known_hosts": "cfg",
    "lsb-release": "cfg",
    "metadata.xml": "cfg",
    "neomuttrc": "cfg",
    "os-release": "cfg",
    "packages.el": "emacs",
    "passwd": "passwd",
    "profile": "cfg",
    ".profile": "cfg",
    "shadow": "cfg",
    "shells": "cfg",
    "subgid": "cfg",
    "subuid": "cfg",
    "sudoers": "key",
    "sxhkdrc": "cfg",
    "tigrc": "cfg",
    "timezone": "cfg",
    "url": "link",
    "user-dirs.dirs": "cfg",
    "vimrc": "vim",
    "xmonad.hs": "hs",
    "zathurarc": "cfg",
    # documentation
    "changelog": "markdown",
    "contributing": "markdown",
    "copyright": "markdown",
    "license.md": "license",
    "license.txt": "license",
    "security": "security",
    "security.md": "security",
    "unlicense": "license",
    # ruby
    "gemfile": "rb",
    "gemfile.lock": "version_lock",
    "procfile": "rb",
    "rakefile": "rb",
    "rubydoc": "rubydoc",
    # gitlab
    ".gitlab-ci.yml": "github",
    # ci
    ".travis.yml": "yml",
    "appveyor.yml": "yml",
    "heroku.yml": "yml",
    "netlify.toml": "toml",
    # frameworks
    "webpack.config.js": "js",
    # security
    "authorized_keys": "key",
    ".gnupg": "key",
    ".pki": "key",
    ".ssh": "key",
    "id_dsa": "key",
    "id_ecdsa": "key",
    "id_rsa": "key",
    # checksum
    "md5sum": "log",
    "sha256sum": "log",
    # special
    "a.out": "binary",
    ".ds_store": "hidden",
    "localized": "hidden",
    "manifest": "json",
    "module.symvers": "binary",
    "pkgbuild": "package",
    # bots
    "agents.md": "robots",
    "crush.md": "robots",
    "gemini.md": "robots",
    "claude.md": "robots",
    "llms.txt": "robots",
    # general
    "license": "license",
    "maintainers": "maintainers",
    "magic": "binary",
    "vagrantfile": "vagrantfile",
    "jenkinsfile": "jenkinsfile",
}


class ArchiveExtensions(NamedTuple):
    zip: tuple[str, ...]
    tar: tuple[str, ...]
    rar: tuple[str, ...]


ARCHIVE_EXTENSIONS = ArchiveExtensions(
    (".zip",),
    (".tar", ".tgz", ".tbz", ".tbz2", ".tar.gz", ".tar.bz2", ".tar.xz"),
    (".rar",),
)
ARCHIVE_EXTENSIONS_FULL = tuple(ext for exts in ARCHIVE_EXTENSIONS for ext in exts)

PIL_EXTENSIONS = (
    # reminder that stuff can also not work, just remove it if it doesn't work
    ".avif",
    ".bmp",
    ".dds",
    ".eps",
    ".ps",
    ".gif",
    ".icns",
    ".ico",
    ".im",
    ".jpg",
    ".jpeg",
    ".jpe",
    ".msp",
    ".pcx",
    ".png",
    ".pbm",
    ".pgm",
    ".ppm",
    ".pnm",
    ".sgi",
    ".rgb",
    ".rgba",
    ".bw",
    ".spi",
    ".tga",
    ".tif",
    ".tiff",
    ".webp",
    ".xbm",
    ".j2k",
    ".jp2",
    ".jpx",
    ".j2c",
    ".jxr",
    ".wdp",
    ".apng",
    ".fit",
    ".fits",
    ".flif",
    ".ftex",
    ".heic",
    ".heif",
    ".mim",
    ".mpo",
    ".psd",
    ".palm",
    ".pxr",
    ".qoi",
    ".tim",
)


TOGGLE_BUTTON_ICONS = {
    "left": " ",
    "right": "",
    "inner": "\ue640",
    "inner_filled": "\uf4a7",
}

ASCII_TOGGLE_BUTTON_ICONS = {
    "left": " ",
    "right": "",
    "inner": "O",
    "inner_filled": "X",
}

BORDER_BOTTOM = {
    "ascii": "-",
    "blank": " ",
    "dashed": "╍",
    "double": "═",
    "heavy": "━",
    "hidden": " ",
    "none": " ",
    "hkey": "▁",
    "inner": "▀",
    "outer": "▄",
    "panel": "▁",
    "round": "─",
    "solid": "─",
    "tall": "▁",
    "thick": "▄",
    "vkey": "▔",
    "wide": "▔",
}

SPINNER = SPINNERS["dots2"]["frames"]
assert isinstance(SPINNER, (str, list))
SPINNER_LENGTH = len(SPINNER)
