import os
import shutil
import zipfile


class ReleaseMaker:
    def __init__(self):
        self.script_dir = os.path.dirname(os.path.abspath(__file__))
        self.base_dir = os.path.join(self.script_dir, "client", "release")
        self.__ensure_directory_exists(self.base_dir)
        self.version = self.__find_latest_version()
        self.release_dir = None

    def __find_latest_version(self):
        versions = [dir_name for dir_name in os.listdir(self.base_dir) if
                    os.path.isdir(os.path.join(self.base_dir, dir_name))]
        return max(versions, key=lambda v: list(map(int, v.split('.'))))

    @staticmethod
    def __ensure_directory_exists(dir_path):
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

    def __unzip_files(self):
        zip_dir = os.path.join(self.base_dir, self.version)
        self.__ensure_directory_exists(zip_dir)
        for item in os.listdir(zip_dir):
            if item.endswith('.zip'):
                with zipfile.ZipFile(os.path.join(zip_dir, item), 'r') as zip_ref:
                    zip_ref.extractall(self.release_dir)

    def __copy_files(self):
        # Copy ./server/dist/server to ./release/PLC_SIM v{version}/server
        server_source = os.path.join(self.script_dir, "server", "dist", "server")
        server_dest = os.path.join(self.release_dir, "server")
        self.__ensure_directory_exists(server_dest)
        shutil.copytree(server_source, server_dest, dirs_exist_ok=True)

        # Copy ./source to ./release/PLC_SIM v{version}/server/source
        source_source = os.path.join(self.script_dir, "source")
        source_dest = os.path.join(self.release_dir, "server", "source")
        self.__ensure_directory_exists(source_dest)
        shutil.copytree(source_source, source_dest, dirs_exist_ok=True)

        # Copy README.md
        shutil.copy2(os.path.join(self.script_dir, "README.md"), self.release_dir)

        # Copy ./instrument_setting.ini
        shutil.copy2(os.path.join(self.script_dir, "instrument_setting.ini"), self.release_dir)

        # Copy everything from ./dist/launcher/ to ./release/PLC_SIM v{version}/
        launcher_source = os.path.join(self.script_dir, "dist", "launcher")
        for item in os.listdir(launcher_source):
            item_path = os.path.join(launcher_source, item)
            if os.path.isdir(item_path):
                shutil.copytree(item_path, os.path.join(self.release_dir, item), dirs_exist_ok=True)
            else:
                shutil.copy2(item_path, self.release_dir)

    def make_release(self):
        self.release_dir = os.path.join(self.script_dir, f"release/PLC_SIM v{self.version}")
        self.__ensure_directory_exists(self.release_dir)

        self.__unzip_files()
        self.__copy_files()

        # Create export directory
        export_dir = os.path.join(self.release_dir, "server", "export")
        self.__ensure_directory_exists(export_dir)

        print(f"Release for PLC_SIM v{self.version} has been successfully created!")


if __name__ == "__main__":
    # Create an instance and run the release process
    maker = ReleaseMaker()
    maker.make_release()
