"""CLI utility functions."""
# Standard Library
from pathlib import Path

# Third Party
import click

# Project
from hyperglass.cli.echo import info, error, status, success
from hyperglass.cli.static import CL, NL, WS, VALUE, SUCCESS, E

PROJECT_ROOT = Path(__file__).parent.parent


def async_command(func):
    """Decororator for to make async functions runable from syncronous code."""
    import asyncio
    from functools import update_wrapper

    func = asyncio.coroutine(func)

    def wrapper(*args, **kwargs):
        loop = asyncio.get_event_loop()
        return loop.run_until_complete(func(*args, **kwargs))

    return update_wrapper(wrapper, func)


def fix_ownership(user, group, directory):
    """Make user & group the owner of the directory."""
    import grp
    import pwd
    import os

    uid = pwd.getpwnam(user).pw_uid
    gid = grp.getgrnam(group).gr_gid
    try:
        for root, dirs, files in os.walk(directory):
            for d in dirs:
                full_path = os.path.join(root, d)
                os.chown(full_path, uid, gid)
            for f in files:
                full_path = os.path.join(root, f)
                os.chown(full_path, uid, gid)
            os.chown(root, uid, gid)
    except Exception as e:
        error("Failed to change 'hyperglass/' ownership", e)

    success("Successfully changed 'hyperglass/' ownership")


def fix_permissions(directory):
    """Make directory readable by public."""
    import os

    try:
        for root, dirs, files in os.walk(directory):
            for d in dirs:
                full_path = os.path.join(root, d)
                os.chmod(full_path, 0o744)
            for f in files:
                full_path = os.path.join(root, f)
                os.chmod(full_path, 0o744)
            os.chmod(root, 0o744)
    except Exception as e:
        error("Failed to change 'hyperglass/' permissions", e)

    success("Successfully changed 'hyperglass/' permissions")


def start_web_server(start, params):
    """Start web server."""
    msg_start = "Starting hyperglass web server on"
    msg_uri = "http://"
    msg_host = str(params["host"])
    msg_port = str(params["port"])
    msg_len = len("".join([msg_start, WS[1], msg_uri, msg_host, CL[1], msg_port]))
    try:
        click.echo(
            NL[1]
            + WS[msg_len + 8]
            + E.ROCKET
            + NL[1]
            + E.CHECK
            + click.style(msg_start, fg="green", bold=True)
            + WS[1]
            + click.style(msg_uri, fg="white")
            + click.style(msg_host, fg="blue", bold=True)
            + click.style(CL[1], fg="white")
            + click.style(msg_port, fg="magenta", bold=True)
            + WS[1]
            + E.ROCKET
            + NL[1]
            + WS[1]
            + NL[1]
        )
        start()

    except Exception as e:
        error("Failed to start test server", e)


def migrate_config(config_dir):
    """Copy example config files and remove .example extensions."""
    status("Migrating example config files...")

    import shutil

    examples = Path(PROJECT_ROOT / "examples").glob("*.yaml.example")

    if not isinstance(config_dir, Path):
        config_dir = Path(config_dir)

    if not config_dir.exists():
        error(f"{str(config_dir)} does not exist")

    migrated = 0
    for file in examples:
        target_file = config_dir / file.with_suffix("").name
        try:
            if target_file.exists():
                info(f"{str(target_file)} already exists")
            else:
                shutil.copyfile(file, target_file)
                migrated += 1
                info(f"Migrated {str(target_file)}")
        except Exception as e:
            error(f"Failed to migrate {str(target_file)}", e)

    if migrated == 0:
        info(f"Migrated {migrated} example config files")
    elif migrated > 0:
        success(f"Successfully migrated {migrated} example config files")


def migrate_systemd(source, destination):
    """Copy example systemd service file to /etc/systemd/system/."""
    import os
    import shutil

    basefile, extension = os.path.splitext(source)
    newfile = os.path.join(destination, basefile)

    try:
        status("Migrating example systemd service...")

        if os.path.exists(newfile):
            info(f"{newfile} already exists")
        else:
            shutil.copyfile(source, newfile)

    except Exception as e:
        error("Error migrating example systemd service", e)

    success(f"Successfully migrated systemd service to: {newfile}")


def build_ui():
    """Create a new UI build.

    Raises:
        click.ClickException: Raised on any errors.
    """
    try:
        import asyncio
        from hyperglass.configuration import params, frontend_params
        from hyperglass.util import build_frontend
    except ImportError as e:
        error("Error importing UI builder", e)

    status("Starting new UI build...")

    if params.developer_mode:
        dev_mode = "production"
    else:
        dev_mode = "development"

    try:
        success = asyncio.run(
            build_frontend(
                dev_mode=params.developer_mode,
                dev_url=f"http://localhost:{str(params.listen_port)}/api/",
                prod_url="/api/",
                params=frontend_params,
                force=True,
            )
        )
        if success:
            click.echo(
                NL[1]
                + E.CHECK
                + click.style("Completed UI build in", **SUCCESS)
                + WS[1]
                + click.style(dev_mode, **VALUE)
                + WS[1]
                + click.style("mode", **SUCCESS)
                + NL[1]
            )
    except Exception as e:
        error("Error building UI", e)

    return True
