from importlib import import_module
import os
import string
from flask.globals import current_app
from jinja2 import Template

from .helper import copy_template, get_import_name, search_model


def g_project(name: str, import_name: str):
    """
    Functions for creating projects.

    :param name: project name.

    """

    print("Creating %r project... " % name, end="")
    copy_template("project", name)
    main_app = True if import_name == "wsgi" else False
    for root, _, files in os.walk(name):
        for f in files:
            if not f.endswith((".py", ".rst")):
                continue

            f = os.path.join(root, f)
            with open(f) as fp:
                data = fp.read()
                t = Template(data)
                new = t.render(import_name=import_name, main_app=main_app, name=name)

            with open(f, "w") as fp:
                fp.write(new)

    print("(done)")


def g_api(name: str):
    """
    Functions for creating APIs.

    :param name: REST API name.

    """

    print("Creating API %r... " % name, end="")
    api_dir = os.path.join(current_app.root_path, "api")
    copy_template("api", api_dir)
    old_filename = os.path.join(api_dir, "name.py")
    with open(old_filename) as fp:
        old_data = fp.read()
        py_t = string.Template(old_data)
        new_data = py_t.safe_substitute(name=name, url_prefix=name.lower())

    os.remove(old_filename)
    new_filename = os.path.join(api_dir, name.lower() + ".py")
    with open(new_filename, "w") as fp:
        fp.write(new_data)

    print("(done)")


def g_api_crud(name: str):
    """
    Function for creating REST API.

    :param name: REST API name.

    """

    src_model = search_model(name)
    import_name = get_import_name(current_app)
    main_app = True
    if import_name:
        main_app = False
        idx = len(import_name)
        src_model = src_model[idx:]

    src_schema = src_model.replace("models", "schema", 1)
    api_dir = os.path.join(current_app.root_path, "api")
    print("Creating REST API %r... " % name, end="")
    copy_template("crud", api_dir)
    old_filename = os.path.join(api_dir, "name.py")
    with open(old_filename) as fp:
        old_data = fp.read()
        py_t = Template(old_data)
        new_data = py_t.render(
            name=name,
            url_prefix=name.lower(),
            src_model=src_model,
            src_schema=src_schema,
            main_app=main_app,
        )

    os.remove(old_filename)
    new_filename = os.path.join(api_dir, name.lower() + ".py")
    with open(new_filename, "w") as fp:
        fp.write(new_data)

    print("(done)")


def g_blueprint(name: str):
    """
    Function for creating blueprints.

    :param name: blueprint name.

    """

    print("Creating blueprint %r... " % name, end="")
    bp_dir = os.path.join(current_app.root_path, name.lower())
    copy_template("blueprint", bp_dir)
    for fname in ("routes", "urls"):
        filename = os.path.join(bp_dir, fname + ".py")
        with open(filename) as fp:
            old_data = fp.read()
            py_t = string.Template(old_data)
            new_data = py_t.safe_substitute(name=name)

        with open(filename, "w") as fp:
            fp.write(new_data)

    print("(done)")


def g_middleware(name: str):
    """
    Function for creating middleware.

    :param str name: middleware name.

    """

    print("Creating middleware %r... " % name, end="")
    middleware_dir = os.path.join(current_app.root_path, "middlewares")
    copy_template("middleware", middleware_dir)
    old_filename = os.path.join(middleware_dir, "name.py")
    new_filename = os.path.join(middleware_dir, name.lower() + ".py")
    os.rename(old_filename, new_filename)
    print("(done)")


def g_command(name: str):
    """
    Function to create boilerplate command.

    :param name: command name.

    """

    print("Creating command %r..." % name, end="")
    cmd_dir = os.path.join(current_app.root_path, "commands")
    copy_template("command", cmd_dir)
    old_filename = os.path.join(cmd_dir, "name.py")
    with open(old_filename) as fp:
        old_data = fp.read()
        py_t = string.Template(old_data)
        new_data = py_t.safe_substitute(name=name)

    os.remove(old_filename)
    new_filename = os.path.join(cmd_dir, name.lower() + ".py")
    with open(new_filename, "w") as fp:
        fp.write(new_data)

    print("(done)")
