import logging
import os
import subprocess
import sys

import psutil
import utils
from Qt import QtCore

log = logging.getLogger("wizart_desktop")


class SyncJobThread(QtCore.QThread):
    def __init__(self):
        super(SyncJobThread, self).__init__()
        self.proc = None
        self.returncode = None
        self.mode = utils.SYNC_MODE_DOWNLOAD
        self.output_widget = None

    def run(self):
        username = utils.get_ftp_user()
        ftp_password = utils.get_ftp_password(username)
        sync_path = utils.get_sync_path()
        env = os.environ.copy()

        args = ['--user', username, '--mode', self.mode, '--sync_path', sync_path]
        is_public_s3_sync_mode = self.mode == utils.SYNC_MODE_PUBLIC_S3_SYNC
        args += ['--remote_type', "s3" if utils.get_sync_is_s3() or is_public_s3_sync_mode else "ftp"]

        if is_public_s3_sync_mode:
            for project_name in os.listdir(sync_path +"/projects"):
                root_path = "/projects/" + project_name
                project_path = sync_path + root_path
                s3_nodes = get_s3_nodes(project_name, project_path)

                for s3_node in s3_nodes:
                    s3_args = [
                        "--s3_sync_path", s3_node["fullpath"].replace("$root", root_path),
                        "--s3_bucket_region", s3_node["schema_attrs"]["s3_region"],
                        "--s3_bucket_name", s3_node["schema_attrs"]["s3_bucket"],
                    ]
                    self.run_sync_script(args + s3_args, env)
            return

        if utils.get_sync_is_s3():
            s3_bucket_name = utils.get_sync_s3_bucket_name()
            s3_bucket_region = utils.get_sync_s3_bucket_region()
            if s3_bucket_name:
                args += ['--s3_bucket_name', s3_bucket_name]
            if s3_bucket_region:
                args += ['--s3_bucket_region', s3_bucket_region]
            env["AWS_ACCESS_KEY_ID"] = str(utils.get_aws_access_key_id(username))
            env["AWS_SECRET_ACCESS_KEY"] = str(utils.get_aws_secret_access_key(username))
        else:
            env["WIZART_DESKTOP_FTP_PASSWORD"] = str(ftp_password)

        self.run_sync_script(args, env)

    def run_sync_script(self, args, env):
        script_path = os.path.join(
            os.path.dirname(os.path.abspath(sys.executable)),
            "sync.exe",
        )
        cmd = [script_path] + args
        log.info("Start Sync Job:'%s'" % " ".join(cmd))

        self.proc = subprocess.Popen(
            cmd,
            startupinfo = utils.get_subprocess_startup_info(),
            stderr = subprocess.STDOUT,
            stdout = subprocess.PIPE,
            bufsize = 0,
            env = env
        )

        while self.proc.poll() is None:
            line = self.proc.stdout.readline()
            self.output_widget.write(line)
        else:
            self.returncode = self.proc.poll()
            self.proc = None

    def kill_job(self):
        if self.proc:
            log.info("Canceled Sync Job")
            try:
                process = psutil.Process(self.proc.pid)
                process.kill()
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        self.returncode = None

def find_s3_nodes(nodes):
    from wizart.fs_ctrl.fs_schema import Folder

    s3_nodes = []

    for node in nodes:
        if isinstance(node, Folder):
            json_node = node.to_json()

            if "s3" in json_node["schema_attrs"]:
                json_node["fullpath"] = node.get_fullpath()
                s3_nodes.append(json_node)
            else:
                finded_nodes = find_s3_nodes(node.children)
                if finded_nodes:
                    s3_nodes = s3_nodes + finded_nodes

    return s3_nodes

def get_s3_nodes(project_name, project_path):
    from wizart.fs_ctrl.fs_schema import ProjectFileSchema
    config_path = os.path.join(project_path, ".config")
    if os.path.exists(config_path):
        project_fs_schema = ProjectFileSchema(project_name, project_path)
        return find_s3_nodes(project_fs_schema.root_node.children)
    return []