"""Install hyperglass."""

# Standard Library
import os
import shutil
from filecmp import dircmp
from pathlib import Path

# Third Party
import inquirer

# Local
from .echo import error, success, warning
from .util import create_dir

USER_PATH = Path.home() / "hyperglass"
ROOT_PATH = Path("/etc/hyperglass/")
ASSET_DIR = Path(__file__).parent.parent / "images"
IGNORED_FILES = [".DS_Store"]

INSTALL_PATHS = [
    inquirer.List(
        "install_path",
        message="Choose a directory for hyperglass",
        choices=[USER_PATH, ROOT_PATH],
    )
]


def prompt_for_path() -> str:
    """Recursively prompt the user for an app path until one is provided."""

    answer = inquirer.prompt(INSTALL_PATHS)

    if answer is None:
        warning("A directory for hyperglass is required")
        answer = prompt_for_path()

    return answer["install_path"]


class Installer:
    """Install hyperglass."""

    def __init__(self, unattended: bool):
        """Initialize installer."""

        self.unattended = unattended

    def install(self) -> None:
        """Complete the installation."""

        self.app_path = self._get_app_path()
        self._scaffold()
        self._migrate_static_assets()

    def _get_app_path(self) -> Path:
        """Find the app path from env variables or a prompt."""

        if self.unattended:
            return USER_PATH

        app_path = os.environ.get("HYPERGLASS_PATH", None)

        if app_path is None:
            app_path = prompt_for_path()

        return app_path

    def _scaffold(self) -> None:
        """Create the file structure necessary for hyperglass to run."""

        ui_dir = self.app_path / "static" / "ui"
        images_dir = self.app_path / "static" / "images"
        favicon_dir = images_dir / "favicons"
        custom_dir = self.app_path / "static" / "custom"

        create_dir(self.app_path)

        for path in (ui_dir, images_dir, favicon_dir, custom_dir):
            create_dir(path, parents=True)

    def _migrate_static_assets(self) -> bool:
        """Synchronize the project assets with the installation assets."""

        target_dir = self.app_path / "static" / "images"

        if not target_dir.exists():
            shutil.copytree(ASSET_DIR, target_dir)

        # Compare the contents of the project's asset directory (considered
        # the source of truth) with the installation directory. If they do
        # not match, delete the installation directory's asset directory and
        # re-copy it.
        compare_initial = dircmp(ASSET_DIR, target_dir, ignore=IGNORED_FILES)

        if not compare_initial.left_list == compare_initial.right_list:
            shutil.rmtree(target_dir)
            shutil.copytree(ASSET_DIR, target_dir)

            # Re-compare the source and destination directory contents to
            # ensure they match.
            compare_post = dircmp(ASSET_DIR, target_dir, ignore=IGNORED_FILES)

            if not compare_post.left_list == compare_post.right_list:
                error(
                    "Files in {a} do not match files in {b}",
                    a=str(ASSET_DIR),
                    b=str(target_dir),
                )
                return False

        success("Migrated assets from {a} to {b}", a=str(ASSET_DIR), b=str(target_dir))
        return True

"""Install hyperglass."""

# Standard Library
import os
import shutil
from filecmp import dircmp
from pathlib import Path

# Third Party
import inquirer

# Local
from .echo import error, success, warning
from .util import create_dir

USER_PATH = Path.home() / "hyperglass"
ROOT_PATH = Path("/etc/hyperglass/")
ASSET_DIR = Path(__file__).parent.parent / "images"
IGNORED_FILES = [".DS_Store"]

INSTALL_PATHS = [
    inquirer.List(
        "install_path",
        message="Choose a directory for hyperglass",
        choices=[USER_PATH, ROOT_PATH],
    )
]


def prompt_for_path() -> str:
    """Recursively prompt the user for an app path until one is provided."""

    answer = inquirer.prompt(INSTALL_PATHS)

    if answer is None:
        warning("A directory for hyperglass is required")
        answer = prompt_for_path()

    return answer["install_path"]


class Installer:
    """Install hyperglass."""

    def __init__(self, unattended: bool):
        """Initialize installer."""

        self.unattended = unattended

    def install(self) -> None:
        """Complete the installation."""

        self.app_path = self._get_app_path()
        self._scaffold()
        self._migrate_static_assets()

    def _get_app_path(self) -> Path:
        """Find the app path from env variables or a prompt."""

        if self.unattended:
            return USER_PATH

        app_path = os.environ.get("HYPERGLASS_PATH", None)

        if app_path is None:
            app_path = prompt_for_path()

        return app_path

    def _scaffold(self) -> None:
        """Create the file structure necessary for hyperglass to run."""

        ui_dir = self.app_path / "static" / "ui"
        images_dir = self.app_path / "static" / "images"
        favicon_dir = images_dir / "favicons"
        custom_dir = self.app_path / "static" / "custom"

        create_dir(self.app_path)

        for path in (ui_dir, images_dir, favicon_dir, custom_dir):
            create_dir(path, parents=True)

    def _migrate_static_assets(self) -> bool:
        """Synchronize the project assets with the installation assets."""

        target_dir = self.app_path / "static" / "images"

        if not target_dir.exists():
            shutil.copytree(ASSET_DIR, target_dir)

        # Compare the contents of the project's asset directory (considered
        # the source of truth) with the installation directory. If they do
        # not match, delete the installation directory's asset directory and
        # re-copy it.
        compare_initial = dircmp(ASSET_DIR, target_dir, ignore=IGNORED_FILES)

        if not compare_initial.left_list == compare_initial.right_list:
            shutil.rmtree(target_dir)
            shutil.copytree(ASSET_DIR, target_dir)

            # Re-compare the source and destination directory contents to
            # ensure they match.
            compare_post = dircmp(ASSET_DIR, target_dir, ignore=IGNORED_FILES)

            if not compare_post.left_list == compare_post.right_list:
                error(
                    "Files in {a} do not match files in {b}",
                    a=str(ASSET_DIR),
                    b=str(target_dir),
                )
                return False

        success("Migrated assets from {a} to {b}", a=str(ASSET_DIR), b=str(target_dir))
        return True

Install hyperglass. # Standard Library # Third Party # Local Recursively prompt the user for an app path until one is provided. Install hyperglass. Initialize installer. Complete the installation. Find the app path from env variables or a prompt. Create the file structure necessary for hyperglass to run. Synchronize the project assets with the installation assets. # Compare the contents of the project's asset directory (considered # the source of truth) with the installation directory. If they do # not match, delete the installation directory's asset directory and # re-copy it. # Re-compare the source and destination directory contents to # ensure they match.