import importlib
import logging
import os
from pathlib import Path


class Writer:
    """
    Class used to write output results either on screen and/or in a file
    """
    def __init__(self, credentials, tickets, masterkeys):
        self._credentials = credentials
        self._tickets = tickets
        self._masterkeys = masterkeys

    def get_output(self, out_format, users_only=False, tickets=False, masterkeys=False):
        """
        Get credentials output in given format
        :param out_format: Format from output package
        :param users_only: If set, only returns users account, else returns users and computers accounts
        :return: Output string
        """
        try:
            output_method = importlib.import_module("lsassy.output.{}_output".format(out_format.lower()), "Output").Output(self._credentials, users_only, tickets, masterkeys)
        except ModuleNotFoundError:
            logging.error("Output module '{}' doesn't exist".format(out_format.lower()), exc_info=True)
            return None

        return output_method.get_output()

    def write(self, file_format, out_format="pretty", output_file=None, quiet=False, users_only=False, tickets=False, masterkeys=False, kerberos_dir=None, masterkeys_file=None):

        """
        Displays content to stdout and/or a file
        :param out_format: Output format
        :param output_file: Output file
        :param file_format: File Logs Format
        :param quiet: If set, doesn't display on stdout
        :param users_only: If set, only returns users account, else returns users and computers accounts
        :param kerberos_dir: If set, saves Kerberos ticket to specified directory
        :param masterkeys_file: If set, saves DPAPI masterkeys to specified directory
        :return: Success status
        """
        output = self.get_output(out_format, users_only, tickets, masterkeys)
        
        if file_format is None:
            file_format = out_format
            file_content = output

        else:
            file_content = self.get_output(file_format, users_only, tickets, masterkeys)

        if output is None:
            logging.error("An error occurred while writing credentials", exc_info=True)
            return None

        if not quiet:
            for line in output.split("\n"):
                logging.success(line)

        if output_file is not None:
            path = Path(output_file).parent
            if not os.path.isdir(path):
                logging.error("Directory {} does not exist".format(path))
                return None

            with open(output_file, 'a+') as f:
                f.write(file_content + "\n")
            logging.success("Credentials saved to {}".format(output_file))

        self.write_tickets(kerberos_dir, quiet)
        self.write_masterkeys(masterkeys_file, quiet)

        return True

    def write_tickets(self, kerberos_dir=None, quiet=False):
        """
        Output masterkeys to file
        :param kerberos_dir: Output dir
        :param quiet: If set, doesn't display on stdout
        """
        if kerberos_dir is None:
            if os.name == 'nt':
                abs_dir = '%LocalAppData%\\lsassy\\tickets'
            else:
                abs_dir = os.path.expanduser('~') + '/.config/lsassy/tickets'
        else:
            if len(self._tickets) == 0 and not quiet:
                logging.warning("No kerberos tickets found")
                return True
            abs_dir = os.path.abspath(kerberos_dir)

        if len(self._tickets) > 0:
            if not os.path.exists(abs_dir):
                try:
                    os.makedirs(abs_dir)
                except Exception as e:
                    logging.warning("Cannot create %s for saving kerberos tickets" % abs_dir, exc_info=True)
                    return True
            for ticket in self._tickets:
                ticket.to_kirbi(abs_dir)
            if not quiet:
                if len(self._tickets) > 1:
                    logging.success("%s Kerberos tickets written to %s" % (len(self._tickets),abs_dir))
                else:
                    logging.success("%s Kerberos ticket written to %s" % (len(self._tickets),abs_dir))

        return True
    
    def write_masterkeys(self, masterkeys_file=None, quiet=False):
        """
        Output masterkeys to file
        :param masterkeys_file: Output file
        :param quiet: If set, doesn't display on stdout
        """
        if masterkeys_file is None:
            if os.name == 'nt':
                abs_dir = '%LocalAppData%\\lsassy\\masterkeys.txt'
            else:
                abs_dir = os.path.expanduser('~') + '/.config/lsassy/masterkeys.txt'
        else:
            if len(self._masterkeys) == 0 and not quiet:
                logging.warning("No DPAPI masterkey found")
                return True
            abs_dir = os.path.abspath(masterkeys_file)

        if len(self._masterkeys) == 0:
            if not quiet:
                logging.warning("No masterkey found")
            return True
        with open(abs_dir,'a+') as file:
            for mk in self._masterkeys:
                file.write(mk+'\n')
        if not quiet:
            logging.success("{} masterkeys saved to {}".format(len(self._masterkeys), abs_dir))
        return True
