import subprocess
import logging
import time
import os, sys

SYNC_MODE_DOWNLOAD = "download"
SYNC_MODE_UPLOAD = "upload"
SYNC_MODE_DOWNLOAD_CONFIG = "download_config"
SYNC_MODE_PUBLIC_S3_SYNC = "public_s3_sync"

class BufferedStreamHandler(logging.StreamHandler):
    def __init__(self, stream):
        logging.StreamHandler.__init__(self, stream)
        self.prev_msg = None

    def emit(self, record):
        msg = self.format(record)
        fs = "%s\n" % msg
        if fs != self.prev_msg:
            self.prev_msg = fs
            logging.StreamHandler.emit(self, record)

class OutputWidgetHandler(logging.Handler):
    def __init__(self, widget):
        logging.Handler.__init__(self)
        self.widget = widget

    def emit(self, record):
        #ct = time.localtime(record.created)
        #date_str = time.strftime("%H:%M:%S", ct)
        #levelname = record.levelname
        msg = self.format(record)
        #msg = str(record.msg)
        self.widget.write(msg + "\n")
        #self.widget.write("%(asctime)s | %(levelname)s :  %(message)s\n" % dict(levelname= levelname, asctime=date_str, message=msg))

class CalledProcessError(Exception):
    """This exception is raised when a process run by check_call() or
    check_output() returns a non-zero exit status.
    The exit status will be stored in the returncode attribute;
    check_output() will also store the output in the output attribute.
    """
    def __init__(self, returncode, cmd, output=None):
        self.returncode = returncode
        self.cmd = cmd
        self.output = output
    def __str__(self):
        return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)

def check_output(*popenargs, **kwargs):
    """
    Backport from python 2.7
    """
    if 'stdout' in kwargs:
        raise ValueError('stdout argument not allowed, it will be overridden.')
    process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
    output, unused_err = process.communicate()
    retcode = process.poll()
    if retcode:
        cmd = kwargs.get("args")
        if cmd is None:
            cmd = popenargs[0]
        raise CalledProcessError(retcode, cmd, output=output)
    return output


def get_subprocess_startup_info():
    startupinfo = subprocess.STARTUPINFO()
    # http://mercurial.808500.n3.nabble.com/PATCH-Issue-3832-STARTF-USESHOWWINDOW-not-available-on-WinNT-Python-2-6-6-td3998732.html
    if hasattr(subprocess, 'STARTF_USESHOWWINDOW'):
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    else:
        startupinfo.dwFlags |= 1
    return startupinfo

def save_geometry(geometry):
    from Qt.QtCore import QSettings
    settings = QSettings("Wizart Animation", "Desktop")
    settings.setValue("geometry", geometry)

def restore_geometry():
    from Qt.QtCore import QSettings
    settings = QSettings("Wizart Animation", "Desktop")
    return settings.value("geometry", False)

def set_sync_path(path):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("sync/w_path", path)

def get_sync_path():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("sync/w_path")

def set_sync_is_s3(state):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("sync/s3", state)

def get_sync_is_s3():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("sync/s3", False, bool)

def set_sync_s3_bucket_name(path):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("sync/s3_bucket_name", path)

def get_sync_s3_bucket_name():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("sync/s3_bucket_name")

def set_sync_s3_bucket_region(path):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("sync/s3_bucket_region", path)

def get_sync_s3_bucket_region():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("sync/s3_bucket_region")

def get_ftp_user():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("ftp/username")

def set_ftp_user(username):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("ftp/username", username)

def get_ftp_password(username):
    import keyring
    return keyring.get_password("wizart_ftp", username)

def set_ftp_password(username, password):
    import keyring
    keyring.set_password("wizart_ftp", username, password)

def get_user():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("username")

def set_user(username):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("username", username)

def get_password(username):
    import keyring
    return keyring.get_password("wizart", username)

def set_password(username, password):
    import keyring
    keyring.set_password("wizart", username, password)

def set_aws_access_key_id(username, aws_access_key_id):
    import keyring
    keyring.set_password("wizart_aws_access_key_id", username, aws_access_key_id)

def get_aws_access_key_id(username):
    import keyring
    return keyring.get_password("wizart_aws_access_key_id", username)

def get_aws_secret_access_key(username):
    import keyring
    return keyring.get_password("wizart_aws_secret_access_key", username)

def set_aws_secret_access_key(username, aws_secret_access_key):
    import keyring
    keyring.set_password("wizart_aws_secret_access_key", username, aws_secret_access_key)

def set_project(project):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("project", project.name)

def clear_project():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("project", None)

def get_project():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("project")

def set_maya_app_dir_var(maya_app_dir):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("maya_app_dir_var", maya_app_dir)

def get_maya_app_dir_var():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("maya_app_dir_var")

def set_override_maya_app_dir_var(state):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("override_maya_app_dir_var", state)

def get_override_maya_app_dir_var():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("override_maya_app_dir_var", False, bool)

def set_show_desktop_notifications(state):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("show_desktop_notifications", state)

def get_maya_scan_malware():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("maya_scan_malware", True, bool)

def set_maya_scan_malware(state):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("maya_scan_malware", state)

def get_show_desktop_notifications():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("show_desktop_notifications", True, bool)


def set_show_dev_projects(state):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("show_dev_projects", state)

def get_show_dev_projects():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("show_dev_projects", False, bool)


def set_show_inactive_projects(state):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    settings.setValue("show_inactive_projects", state)

def get_show_inactive_projects():
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    return settings.value("show_inactive_projects", False, bool)

def get_windows_desktop_executable_path():
    return os.path.abspath(sys.executable)

def create_app_shortcut(destination_full_path, cmd_str, icon_path):
    """
    We dont use windows shortcuts, but rather create custom windows executables in order to:
    - have OS icons
    - allows app to use windows "Open As"
    - do not create console windows

    so we create our templated compiled executable, that support shebang "#!" patching in the end of the file
    and start subprocess using that string.
    """
    import shutil, sys, win_utils
    app_starter_template_executable = os.path.join(os.path.dirname(sys.executable), 'app_starter_template.exe')
    shutil.copy(app_starter_template_executable, destination_full_path)
    cmd_str_escaped = "#!%s\0" % cmd_str
    win_utils.add_icon(unicode(destination_full_path), unicode(icon_path), 0)
    with open(destination_full_path, "ab") as f:
        f.write(cmd_str_escaped)

def open_rez_terminal():
    import wizart.desktop
    _env = os.environ.copy()
    app_directory = os.path.dirname(get_windows_desktop_executable_path())
    _env["PATH"] += ';' + os.path.join(app_directory, 'rez')
    _env["REZ_CONFIG_FILE"] = wizart.desktop.get_rez_config_path()
    _env["PYTHONPATH"] = ';'.join([os.path.join(app_directory, "python27.zip"), os.path.join(app_directory, "modules")])
    subprocess.Popen(['CMD'], env = _env, cwd = app_directory)

def save_rez_modifier(app_name, rez_modifiers, is_used):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    data = {"rez_modifiers": rez_modifiers, "is_used": is_used,}
    if rez_modifiers != []:
        settings.setValue("apps/%s/rez_modifiers" % app_name, data)
    else:
        settings.remove("apps/%s/rez_modifiers" % app_name)

def load_rez_modifier(app_name):
    from Qt import QtCore
    settings = QtCore.QSettings("Wizart Animation", "Desktop")
    data = settings.value("apps/%s/rez_modifiers" % app_name)
    rez_modifiers = []
    is_used = False
    if data is not None:
        for modifier in data["rez_modifiers"]:
            rez_modifiers.append(str(modifier))
        is_used = data["is_used"]
    return rez_modifiers, is_used
