import sqlite3
import os
import shutil
import stat
import errno

from distutils.dir_util import copy_tree

from systools import sys_parsefilepath


class CommonService(object):
    @staticmethod
    def copy_all_content(source_path, destination_path):
        # type: (str, str) -> None

        copy_tree(source_path, destination_path)

    @staticmethod
    def duplicate_file(source_file, new_file):
        # type: (str, str) -> None

        shutil.copyfile(source_file, new_file)

    @staticmethod
    def remove_file(file_path):
        # type: (str) -> None
        has_file = os.path.exists(file_path)
        if has_file:
            os.remove(file_path)

    @staticmethod
    def create_dir(path, delete_if_exists=True):
        # type: (str, bool) -> None

        if os.path.exists(path):
            if not delete_if_exists:
                return

            CommonService.delete_directory(path)

        os.makedirs(path)

    @staticmethod
    def delete_directory(path):
        # type: (str) -> None

        if os.path.exists(path):
            shutil.rmtree(path, ignore_errors=False, onerror=CommonService.handle_remove_read_only)

    @staticmethod
    def delete_file_or_directory(path):
        # type: (str) -> None

        if os.path.exists(path):
            if os.path.isfile(path):
                os.remove(path)
            else:
                shutil.rmtree(path, ignore_errors=False, onerror=CommonService.handle_remove_read_only)

    @staticmethod
    def handle_remove_read_only(func, path, exc):
        exc_value = exc[1]
        if func in (os.rmdir, os.remove) and exc_value.errno == errno.EACCES:
            os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
            func(path)
        else:
            raise exc_value

    @staticmethod
    def execute_scripts_commands(database, script_path, logger):
        # type: (str, str, Logger) -> None

        conn = sqlite3.connect(database)
        try:
            cur = conn.cursor()
            with open(script_path, 'r') as f:
                commands_list = f.readlines()
                for command in commands_list:
                    logger.info("Executing script: {} for databases {}".format(command, database))
                    cur.execute(command)
            conn.commit()
        except (Exception,):
            conn.rollback()
            raise
        finally:
            conn.close()

    @staticmethod
    def check_is_dev():
        # type: (...) -> bool

        component_path = sys_parsefilepath("{BUNDLEDIR}")
        dev_file = os.path.join(component_path, "devFile.txt")
        return os.path.exists(dev_file)
