#!/usr/bin/env python3

import os
import stat
import sys

import gitignore_parser


paths = sys.argv[1:] or ["."]

colors = dict(
    [
        entry.split("=", maxsplit=1)
        for entry in (
            os.environ.get("_3_COLORS")
            or os.environ.get("TREE_COLORS")
            or os.environ.get("LS_COLORS")
            or ":no=00:rs=0:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.bat=01;32:*.BAT=01;32:*.btm=01;32:*.BTM=01;32:*.cmd=01;32:*.CMD=01;32:*.com=01;32:*.COM=01;32:*.dll=01;32:*.DLL=01;32:*.exe=01;32:*.EXE=01;32:*.arj=01;31:*.bz2=01;31:*.deb=01;31:*.gz=01;31:*.lzh=01;31:*.rpm=01;31:*.tar=01;31:*.taz=01;31:*.tb2=01;31:*.tbz2=01;31:*.tbz=01;31:*.tgz=01;31:*.tz2=01;31:*.z=01;31:*.Z=01;31:*.zip=01;31:*.ZIP=01;31:*.zoo=01;31:*.asf=01;35:*.ASF=01;35:*.avi=01;35:*.AVI=01;35:*.bmp=01;35:*.BMP=01;35:*.flac=01;35:*.FLAC=01;35:*.gif=01;35:*.GIF=01;35:*.jpg=01;35:*.JPG=01;35:*.jpeg=01;35:*.JPEG=01;35:*.m2a=01;35:*.M2a=01;35:*.m2v=01;35:*.M2V=01;35:*.mov=01;35:*.MOV=01;35:*.mp3=01;35:*.MP3=01;35:*.mpeg=01;35:*.MPEG=01;35:*.mpg=01;35:*.MPG=01;35:*.ogg=01;35:*.OGG=01;35:*.ppm=01;35:*.rm=01;35:*.RM=01;35:*.tga=01;35:*.TGA=01;35:*.tif=01;35:*.TIF=01;35:*.wav=01;35:*.WAV=01;35:*.wmv=01;35:*.WMV=01;35:*.xbm=01;35:*.xpm=01;35:"
        ).split(":")[1:-1]
    ]
)


def color(path):
    mode = os.stat(path).st_mode
    type = stat.S_IFMT(mode)

    # TODO mi and or
    if type == stat.S_IFIFO:
        return "fi"
    elif type == stat.S_IFCHR:
        return "cd"
    elif type == stat.S_IFDIR:
        if mode & stat.S_ISVTX:
            return "tw" if mode & stat.S_IWOTH else "st"
        elif mode & stat.S_IWOTH:
            return "ow"
        else:
            return "di"
    elif type == stat.S_IFBLK:
        return "bd"
    elif type == stat.S_IFLNK:
        print(mode, stat.S_IFLNK, mode & stat.S_IFLNK)
        return "ln"
    elif type == stat.S_IFDOOR:
        return "do"
    elif type == stat.S_IFSOCK:
        return "so"
    elif type == stat.S_IFREG:
        ext = f"*{os.path.splitext(path)[1]}"
        if mode & stat.S_ISUID:
            return "su"
        elif mode & stat.S_ISGID:
            return "sg"
        elif mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
            return "ex"
        elif ext in colors:
            return ext
        else:
            return "fi"
    else:
        return "no"


def apply_color(name, path):
    name_color = color(path)
    if name_color in colors:
        return f"\033[{colors[name_color]}m{name}\033[0m"
    else:
        return name


def process_path(path, prefix="", gitignores=[]):
    children = sorted(os.listdir(path))

    if ".gitignore" in children:
        gitignores = gitignores + [gitignore_parser.parse_gitignore(os.path.join(path, ".gitignore"))]

    for i, name in enumerate(children):
        sub_path = os.path.join(path, name)
        if name != ".git" and all((not gitignore(sub_path) for gitignore in gitignores)):
            sticks = "├──" if i != len(children) - 1 else "└──"
            print(f"{prefix}{sticks}", apply_color(name, sub_path))

            if os.path.isdir(sub_path):
                sticks = "│   " if i != len(children) - 1 else "    "
                process_path(os.path.join(path, name), prefix=f"{prefix}{sticks}", gitignores=gitignores)
                statistics["directories"] += 1

            else:
                statistics["files"] += 1


statistics = {"directories": 0, "files": 0}
for path in paths:
    print(apply_color(path, path))
    process_path(path)

print()
print(", ".join((f"{v} {k}" for k, v in statistics.items())))
