import os
from datetime import datetime
from .utils import write_to_file, ensure_dir_exists


class FileGenerator:
    """
    A class for generating the command and alias files.
    """

    def __init__(self, conf_dir):
        self.conf_dir = conf_dir
        self.venv_dir = os.environ.get('VIRTUAL_ENV')
        self.generated_files_dir = os.path.join(self.conf_dir, 'generated')
        self.script_file = os.path.join(self.generated_files_dir, 'turboshell')
        self.definitions_file = os.path.join(self.generated_files_dir, 'definitions')
        self.lines = []

    def generate_alias_file(self, aliases, functions, info_entries):
        ensure_dir_exists(self.generated_files_dir)
        self._build_alias_file(aliases, functions, info_entries)

    def generate_turboshell_script(self):
        """
        Builds the excutable script "turboshell"
        """
        ensure_dir_exists(self.generated_files_dir)
        import stat
        write_to_file(self.script_file, [
            'source {}/bin/activate'.format(self.venv_dir),
            'TURBOSHELL_USER_DIR={} python -m turboshell $*'.format(self.conf_dir)
        ])
        st = os.stat(self.script_file)
        os.chmod(self.script_file, st.st_mode | stat.S_IEXEC)

    @property
    def turboshell_alias_line(self):
        return "alias turboshell='bash {}'".format(self.script_file)

    def _build_alias_file(self, aliases, functions, info_entries):
        self._add_headers()
        self._add_builtins()
        self._add_custom_aliases(aliases)
        self._add_custom_functions(functions)
        self._add_info_function(info_entries)
        write_to_file(self.definitions_file, self.lines)

    def _add_headers(self):
        """
        Add the initial lines for the alias file.
        """
        add = self.lines.append
        add("# This file is generated by turboshell.")
        add("# Changes made here will be overwritten.")
        add(" ")

    def _add_builtins(self):
        """
        Add aliases for built in commands.
        """
        add = self.lines.append
        add("# Built-in aliases:")
        add(" ")
        add(self.turboshell_alias_line)
        add("alias turboshell.rebuild='turboshell rebuild && source {}'".format(self.definitions_file))
        add("alias turboshell.reload='source {}'".format(self.definitions_file))
        add(" ")

    def _add_custom_aliases(self, aliases):
        add = self.lines.append
        add("# Your aliases:")
        add(" ")
        for name, cmd in aliases.items():
            add("alias {}='{}'".format(name, cmd))
        add(" ")

    def _add_custom_functions(self, functions):
        add = self.lines.append
        add("# Your functions:")
        add(" ")
        for name, body in functions.items():
            add("function " + name + " {")
            for line in body:
                add("  " + line)
            add("}")
        add(" ")

    def _add_info_function(self, info_entries):
        add = self.lines.append
        echo = lambda line: add(" echo '  {}'".format(line))
        add("# Info function:")
        add('')
        add("function turboshell.info {")
        echo('')
        echo('Alias file last built: {}'.format(datetime.today().strftime('%Y-%m-%d %H:%M:%S')))
        echo('')
        info_entries.append(('turboshell.info', 'Shows info on commands'))
        info_entries.append(('turboshell.reload', 'Reloads the aliases in current shell'))
        info_entries.append(('turboshell.rebuild', 'Rebuilds and reloads the aliases in current shell'))
        echo('Commands:')
        echo('')
        # Add padded line for each entry
        longest = max(len(e[0]) for e in info_entries)
        for cmd, info in sorted(info_entries, key=lambda x: x[0]):
            space = (longest - len(cmd)) * ' '
            echo("{} {}| {}".format(cmd, space, info))
        echo('')
        add("}")
