#!/usr/bin/python3

import re
from pathlib import Path
import subprocess
import json
from distutils.util import strtobool

from colorama import init, Fore, Style

# init colors for all plateforms
init()


def set_default_readme(folder, module_name, description, url):
    """write a default README.md file and overwrite the existing one"""

    print("Write a default README.md file")

    license = f"{url}/blob/master/LICENSE"

    file = folder / "README.md"
    # write_text cannot handle append
    with file.open("w") as readme:
        readme.writelines(
            [
                f"# {module_name}\n",
                "\n",
                f"[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)]({license})\n",
                "[![Black badge](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n",
                "\n",
                "# About\n",
                "\n",
                f"{description}\n",
            ]
        )

    return


def set_default_about(folder, description):
    """write a default ABOUT.md file and overwrite the existing one"""

    print("Write a default ABOUT.md file")

    file = folder / "utils" / "ABOUT.md"
    with file.open("w") as about:

        about.write(f"{description}  \n")

    return


def set_module_name(folder, module_name):
    """use the module name in the different translation dictionaries"""

    print("Update the module name in the json translation dictionaries")

    # loop in the available languages
    languages = ["en", "fr"]
    for lang in languages:

        file = folder / "component" / "message" / f"{lang}.json"

        with file.open("r") as f:
            data = json.load(f)

        data["app"]["title"] = module_name

        with file.open("w") as f:
            json.dump(data, f, indent=4)

    return


def set_contribute_file(folder, url, module_name):
    """complete the contributing file with the appropriate informations"""

    print("Update the module name in the contribute file")

    contrib = folder / "CONTRIBUTE.md"

    with contrib.open() as f:
        data = f.read()

    data = data.replace("SEPAL_UI_TEMPLATE", module_name)
    data = data.replace("https://github.com/12rambau/sepal_ui_template.git", url)

    with contrib.open("w") as f:
        f.write(data)

    return


def set_module_name_doc(folder, url, module_name):
    """set the module name in each documentation file and set the appropriate repository in the link"""

    # loop in the available languages
    languages = ["fr", "en", "es"]
    for lang in languages:

        file = folder / "doc" / f"{lang}.rst"

        with file.open() as f:
            text = f.read()

        text = text.replace("Module_name", module_name)
        text = text.replace("===========", "=" * len(module_name))
        text = text.replace("https://github.com/12rambau/sepal_ui_template", url)

        with file.open("w") as f:
            f.write(text)
    return


def set_drawer_link(folder, url):
    """replace the reference to the default repository to the one provided by the use"""

    print("Update the drawers link with the new repository one")

    # get the ui file
    ui = folder / "ui.ipynb"

    # read the file
    with ui.open() as f:
        ui_content = f.read()

    # replace the target strings
    ui_content = ui_content.replace(
        "https://github.com/12rambau/sepal_ui_template", url
    )

    # write everything down again
    with ui.open("w") as f:
        f.write(ui_content)

    return


if __name__ == "__main__":

    # welcome the user
    print(Fore.YELLOW)
    print("##################################")
    print("#                                #")
    print("#      SEPAL MODULE FACTORY      #")
    print("#                                #")
    print("##################################")
    print(Fore.RESET)
    print(f"Welcome in the {Style.BRIGHT}module factory{Style.NORMAL} interface.")
    print(
        "This interface will help you building a dashboard app based on the sepal_ui library"
    )
    print("Please read the documentation of the library before launching this script")
    print()
    print()
    print()
    print("Initializing module creation by setting up your module parameters")
    print("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾")
    print()

    # ask the name of the module
    module_name = input(f"{Fore.CYAN}Provide a module name: \n{Fore.RESET}")
    if not module_name:
        raise Exception(f"{Fore.RED}A module name should be set")

    # set the module github URL
    github_url = input(
        f"{Fore.CYAN}Provide the URL of an empty github repository: \n{Fore.RESET}"
    )
    if not github_url:
        raise Exception(
            f"{Fore.RED}A module name should be set with an asociated github repository"
        )

    # ask for a short description
    description = input(
        f"{Fore.CYAN}Provide a short description for your module(optional): \n{Fore.RESET}"
    )

    # default to the default branch (obviously)
    branch = "default"

    # ask if the user need the default function
    default = input(
        f"{Fore.CYAN}Do you need to use the default function as a template [y]? \n{Fore.RESET}"
    )
    if not strtobool(default):
        branch = "no_default"

        # ask if the user need the aoi
        aoi = input(
            f"{Fore.CYAN}Do you need an AOI selector in your module (it will still be possible to add one afterward) [y]? \n{Fore.RESET}"
        )
        if not strtobool(aoi):
            branch = "no_aoi"

        else:

            gee = input(
                f"{Fore.CYAN}Do you need a connection to GEE in your module (it will still be possible to add one afterward) [y]? \n{Fore.RESET}"
            )
            if not strtobool(gee):
                branch = "no_gee"

    # adapt the name of the module to remove any special characters and spaces
    normalized_name = re.sub("[^a-zA-Z\d\-\_]", "_", module_name)

    print()
    print("Build the module init configuration")
    print("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾")
    print()

    # clone the repository in a folder that has the normalized module name
    folder = Path.cwd() / normalized_name
    template_url = "https://github.com/12rambau/sepal_ui_template.git"
    command = [
        "git",
        "clone",
        "--single-branch",
        "--branch",
        branch,
        template_url,
        str(folder),
    ]
    res = subprocess.run(command, cwd=Path.cwd())

    # remove the .git folder
    command = ["rm", "-rf", str(folder / ".git")]
    res = subprocess.run(command, cwd=Path.cwd())

    # replace the placeholders
    url = github_url.replace(".git", "").replace(
        "git@github.com:", "https://github.com/"
    )

    set_default_readme(folder, module_name, description, url)
    set_default_about(folder, description)
    set_module_name(folder, module_name)
    set_drawer_link(folder, url)
    set_module_name_doc(folder, url, module_name)
    set_contribute_file(folder, url, module_name)

    # init the new git repository
    command = ["git", "init"]
    res = subprocess.run(command, cwd=folder)

    # add the configuration of the git repository
    command = ["pre-commit", "install"]
    res = subprocess.run(command, cwd=folder)

    # The dev version of black is used in sepal_ui_template so we cannot autoupdate yet
    # command = ["pre-commit", "autoupdate"]
    # res = subprocess.run(command, cwd=folder)

    # add all the files in the git repo
    command = ["git", "add", "."]
    res = subprocess.run(command, cwd=folder)

    # first commit
    command = ["git", "commit", "-m", "first commit"]
    res = subprocess.run(command, cwd=folder)

    # create a branch
    command = ["git", "branch", "-M", "master"]
    res = subprocess.run(command, cwd=folder)

    # add the remote
    command = ["git", "remote", "add", "origin", github_url]
    res = subprocess.run(command, cwd=folder)

    # make the first push
    command = ["git", "push", "-u", "origin", "master"]
    res = subprocess.run(command, cwd=folder)

    # create a release branch and push it to the server
    command = ["git", "checkout", "-b", "release"]
    res = subprocess.run(command, cwd=folder)

    command = ["git", "push", "--set-upstream", "origin", "release"]
    res = subprocess.run(command, cwd=folder)

    # checkout to master
    command = ["git", "checkout", "master"]
    res = subprocess.run(command, cwd=folder)

    # exit message
    print(Fore.YELLOW)
    print(
        f"{Style.BRIGHT}WARNING{Style.NORMAL}: have a look to the git command executed in the process. if any of them is displaying an error, the final folder may not have been created"
    )
    print(
        "If that's the case, delete the folder in your sepal instance (if there is any) and start the process again or contact us via github issues"
    )
    print(Fore.GREEN)
    print(
        f"{Style.BRIGHT}CONGRATULATION{Style.NORMAL}: You created a new module named: {Style.BRIGHT}{module_name}{Style.NORMAL}"
    )
    print(
        f"You can find its code in {Style.BRIGHT}{folder}{Style.NORMAL} inside your sepal environment."
    )
    print(
        "To go further in the development of your application you can have a look at the sepalizing documentation."
    )
    print()
    print("Let's code !")
    print(Fore.RESET)
