import sys
from io import StringIO
from typing import Dict

from tests.support.run.cmd_result import CmdResult
from trashcli.fstab.volumes import Volumes
from trashcli.lib.my_input import HardCodedInput
from trashcli.restore.file_system import FakeReadCwd, FileReader, \
    RestoreReadFileSystem, \
    RestoreWriteFileSystem, ListingFileSystem
from trashcli.restore.info_dir_searcher import InfoDirSearcher
from trashcli.restore.info_files import InfoFiles
from trashcli.restore.restore_cmd import RestoreCmd
from trashcli.restore.trash_directories import TrashDirectoriesImpl
from trashcli.restore.trashed_files import TrashedFiles


class MemoLogger:
    def __init__(self):
        self.messages = []

    def warning(self, msg):
        self.messages.append("warning: " + msg)


class RestoreUser:
    def __init__(self,
                 environ,  # type: Dict[str, str]
                 uid,  # type: int
                 file_reader,  # type: FileReader
                 read_fs,  # type: RestoreReadFileSystem
                 write_fs,  # type: RestoreWriteFileSystem
                 listing_file_system,  # type: ListingFileSystem
                 version,  # type: str
                 volumes,  # type: Volumes
                 ):
        self.environ = environ
        self.uid = uid
        self.file_reader = file_reader
        self.read_fs = read_fs
        self.write_fs = write_fs
        self.listing_file_system = listing_file_system
        self.version = version
        self.volumes = volumes

    no_args = object()

    def run_restore(self, args=no_args, reply='', from_dir=None):
        args = [] if args is self.no_args else args
        stdout = StringIO()
        stderr = StringIO()
        read_cwd = FakeReadCwd(from_dir)
        logger = MemoLogger()
        trash_directories = TrashDirectoriesImpl(self.volumes,
                                                 self.uid,
                                                 self.environ)
        searcher = InfoDirSearcher(trash_directories,
                                   InfoFiles(self.listing_file_system))
        trashed_files = TrashedFiles(logger,
                                     self.file_reader,
                                     searcher)
        cmd = RestoreCmd.make(stdout=stdout,
                              stderr=stderr,
                              exit=sys.exit,
                              input=HardCodedInput(reply),
                              version=self.version,
                              trashed_files=trashed_files,
                              read_fs=self.read_fs,
                              write_fs=self.write_fs,
                              read_cwd=read_cwd)

        try:
            exit_code = cmd.run(args)
        except SystemExit as e:
            exit_code = e.code

        return CmdResult(stdout.getvalue(),
                         stderr.getvalue(), exit_code)
