#!/usr/bin/env python3
"""
quickdel - delete any file matching a query

Dependencies
============
* fd
* python-termcolor

Command-Line Arguments
======================
* -d, --directories-only
* -D, --directory       TODO: implement this
* -e, --empty-only
* -E, --extension
* -f, --files-only
* -F, --force-directory-delete
* -i, --no-ignore
* -I, --no-ignore-vcs
* -l, --links-only
"""

import argparse
import os
import os.path
import re
import shutil
import file_scripts.error as error
import file_scripts.search as search

from termcolor import colored

# ========== Constants ==========
fd_opts = ["--hidden"]
# Matches 'y' or 'yes' only, ignoring case
USER_RESPONSE_YES = r"^[Yy]{1}([Ee]{1}[Ss]{1})?$"


# ========== Functions ==========
def color_file(filename):
    """Return correct color code for filetype of filename.

    Example
    -------
    >>> color_file('Test File', 'red')
    '\x1b[31mTest String\x1b[0m'

    :param filename: file to determine color output for
    :type filename: str
    :return: filename with ANSII escape codes for color
    :rtype: str
    """
    if os.path.isdir(filename):
        return colored(filename, "blue")
    elif os.path.islink(filename):
        return colored(filename, "green")
    else:
        return filename


# ========== Main Script ==========
if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-d",
        "--directories-only",
        action="store_const",
        const=["--type", "directory"],
        dest="fd_extra_opts",
        help="filter results to directories",
    )
    parser.add_argument(
        "-e",
        "--empty-only",
        action="store_const",
        const=["--type", "empty"],
        dest="fd_extra_opts",
        help="filter results to empty files and directories",
    )
    parser.add_argument(
        "-E",
        "--extension",
        action="append",
        dest="extensions",
        help="file extension",
        metavar="ext",
    )
    parser.add_argument(
        "-f",
        "--files-only",
        action="store_const",
        const=["--type", "file"],
        dest="fd_extra_opts",
        help="filter results to files",
    )
    parser.add_argument(
        "-F",
        "--force-directory-delete",
        action="store_true",
        help="do not ignore non-empty directories, delete anyways",
    )
    parser.add_argument(
        "-I",
        "--no-ignore-vcs",
        action="store_const",
        const="--no-ignore-vcs",
        dest="fd_extra_opts",
        help="do not ignore .gitignore",
    )
    parser.add_argument(
        "-i",
        "--no-ignore",
        action="store_const",
        const="--no-ignore",
        dest="fd_extra_opts",
        help="do not ignore .gitignore and .fdignore",
    )
    parser.add_argument(
        "-l",
        "--links-only",
        action="store_const",
        const=["--type", "symlink"],
        dest="fd_extra_opts",
        help="filter results to symlinks",
    )
    parser.add_argument("patterns", nargs="+", help="file matching patterns")

    args = parser.parse_args()

    if args.fd_extra_opts is not None:
        fd_opts.extend(args.fd_extra_opts)
    if args.extensions is not None:
        for ext in args.extensions:
            fd_opts.extend(["--extension", ext])

    files = set()
    for p in args.patterns:
        files.update(
            search.find_files(opts=fd_opts, capture_text=True, pattern=p).splitlines()
        )
    files = sorted(files)

    if files == []:
        print("No results found, exiting")
        exit(error.E_NO_RESULTS)

    # Pretty print all filenames
    for index, filename in enumerate([color_file(f) for f in files], 1):
        print(f"{index}. {filename}")
    # Padding line
    print()

    try:
        user_response = input("Would you like to delete these files? [y/N]: ")
    except KeyboardInterrupt:
        exit(error.E_INTERRUPT)

    if re.match(USER_RESPONSE_YES, user_response) is None:
        print("Operation cancelled")
        exit(error.E_USER_RESPONSE_NO)

    # Remove files first
    for f in [fi for fi in files if os.path.isfile(fi)]:
        os.remove(f)

    # Check -f, --force-directory-delete option
    # shutil.rmtree forcibly removes directories
    # os.rmdir removes directories only if they are empty
    rmdir_func = shutil.rmtree if args.force_directory_delete else os.rmdir

    for d in filter(os.path.isdir, files):
        try:
            rmdir_func(d)
        except OSError:
            print(
                f"{colored('Warning', 'yellow')}: {colored(d, 'blue')} is not empty, not deleting directory"
            )

    print(colored("\nDeletions complete", "green"))