#!/usr/bin/env xonsh
import os, sys, argparse, re
from sys import exit

class XxhPackage(object):
    def __init__(self):
        self.local_xxh_home_dir = p'~/.xxh'
        self.build_file_exts = ['xsh', 'zsh', 'fish', 'sh']
        self.quiet = False

        parser = argparse.ArgumentParser(description='xxhp is xxh package manager.',
            usage='xxhp <command>\n\n'
                    + '   install    i   Install xxh package from https://github.com/xxh\n'
                    + '   list       l   List of installed packages\n'
                    + '   remove     r   Remove xxh package\n\n'
                    + '   reinstall  ri  Reinstall xxh package\n\n'
                    + 'Try `./xxhp <command> --help` to get more info.\n')
        parser.add_argument('command', help='Command to run')

        args = parser.parse_args(sys.argv[1:2])
        if not hasattr(self, args.command):
            print('Unrecognized command\n')
            parser.print_help()
            sys.exit(1)

        mkdir -p @(self.local_xxh_home_dir / 'xxh/shells') @(self.local_xxh_home_dir / 'xxh/plugins')
        getattr(self, args.command)()

    def print(self, *args, **kwargs):
        if not self.quiet:
            print(*args, **kwargs)

    def eprint(self, *args, **kwargs):
        if not self.quiet:
            print(*args, file=sys.stderr, **kwargs)

    def eeprint(self, *args, **kwargs):
        if not self.quiet:
            print(*args, file=sys.stderr, **kwargs)
        exit(1)

    def i(self):
        return self.install()

    def install(self):
        parser = argparse.ArgumentParser(description='')
        parser.add_argument('packages', nargs='+', help=f"xxh-package")
        parser.add_argument('-v', '--verbose', action='store_true', help=f"Verbose mode")
        parser.add_argument('-q', '--quiet', action='store_true', help=f"Quiet mode")
        parser.usage = parser.format_usage().replace('usage: xxhp ', 'xxhp install ')
        opt = parser.parse_args(sys.argv[2:])

        self.quiet = opt.quiet
        arg_q = ['-q'] if self.quiet else []

        for package in opt.packages:
            self.print(f'Install {package}')
            if not re.match('^[a-zA-Z0-9-_]+$', package):
                self.eeprint(f'Invalid package name: {package}')

            subdir = self.package_subdir(package) or self.eeprint(f"Unknown package: {package}")

            package_git_url = f'https://github.com/xxh/{package}'

            self.eprint(f"Git clone {package_git_url}")
            package_dir = self.local_xxh_home_dir/'xxh'/subdir/package
            r = ![git clone @(arg_q) --depth 1 -q @(package_git_url) @(package_dir) 1>&2]
            if r.returncode != 0:
                self.eeprint(f'If the package already exists try reinstall: xxhp ri <package>')

            self.eprint(f"Build {package}")
            build_file_found = False
            for ext in self.build_file_exts:
                build_file = package_dir / f'build.{ext}'
                if build_file.exists():
                    @(build_file) @(arg_q) 1>&2
                    build_file_found = True
                    break
            if not build_file_found:
                self.eeprint(f"Build file not found in {package_dir}")

            self.eprint(f"Installed {package_dir}")

    def r(self):
        return self.remove()

    def remove(self):
        parser = argparse.ArgumentParser(description='')
        parser.add_argument('packages', nargs='+', help=f"xxh-package")
        parser.add_argument('-v', '--verbose', action='store_true', help=f"Verbose mode")
        parser.add_argument('-q', '--quiet', action='store_true', help=f"Quiet mode")
        parser.usage = parser.format_usage().replace('usage: xxhp ', 'xxhp remove ')
        opt = parser.parse_args(sys.argv[2:])

        self.quiet = opt.quiet

        for package in opt.packages:
            self.print(f'Remove {package}')
            subdir = self.package_subdir(package) or self.eeprint(f"Unknown package: {package}")
            package_dir = self.local_xxh_home_dir / 'xxh' / subdir / package
            if package_dir.exists():
                rm -rf @(package_dir)
                self.eprint(f"Removed {package_dir}")

    def ri(self):
        return self.reinstall()

    def reinstall(self):
        self.remove()
        return self.install()

    def l(self):
        return self.list()

    def list(self):
        parser = argparse.ArgumentParser(description='')
        parser.add_argument('packages', nargs='*', help=f"xxh-package")
        parser.add_argument('-v', '--verbose', action='store_true', help=f"Verbose mode")
        parser.usage = parser.format_usage().replace('usage: xxhp ', 'xxhp remove ')
        opt = parser.parse_args(sys.argv[2:])

        packages_dir = (self.local_xxh_home_dir / 'xxh').glob('**/xxh-*')
        for p in sorted(packages_dir):
            if opt.packages:
                if p.name in opt.packages:
                    print(p.name)
            else:
                print(p.name)

    def package_subdir(self, name):
        if 'xxh-shell' in name:
            return 'shells'
        elif 'xxh-plugin' in name:
            return 'plugins'
        return None


if __name__ == '__main__':
    XxhPackage()
