# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import shutil
import subprocess
import sys

from ..helpers import git, log
from .download_plugins import get_installer
from .reindex import IndexType, get_reindexer
from .validate_notedb import NoteDbValidator

LOG = log.get_logger("init")
MNT_PATH = "/var/mnt"


class GerritInit:
    def __init__(self, site, config):
        self.site = site
        self.config = config

        self.plugin_installer = get_installer(self.site, self.config)

        self.gerrit_config = git.GitConfigParser(
            os.path.join(MNT_PATH, "etc/config/gerrit.config")
        )
        self.is_online_reindex = self.gerrit_config.get_boolean(
            "index.onlineUpgrade", True
        )
        self.force_offline_reindex = False
        self.installed_plugins = self._get_installed_plugins()

        self.is_replica = self.gerrit_config.get_boolean("container.replica")
        self.pid_file = f"{self.site}/logs/gerrit.pid"

    def _get_gerrit_version(self, gerrit_war_path):
        command = f"java -jar {gerrit_war_path} version"
        version_process = subprocess.run(
            command.split(), stdout=subprocess.PIPE, check=True
        )
        return version_process.stdout.decode().strip()

    def _get_installed_plugins(self):
        plugin_path = os.path.join(self.site, "plugins")
        installed_plugins = set()

        if os.path.exists(plugin_path):
            for f in os.listdir(plugin_path):
                if os.path.isfile(os.path.join(plugin_path, f)) and f.endswith(".jar"):
                    installed_plugins.add(os.path.splitext(f)[0])

        return installed_plugins

    def _gerrit_war_updated(self):
        installed_war_path = os.path.join(self.site, "bin", "gerrit.war")
        installed_version = self._get_gerrit_version(installed_war_path)
        provided_version = self._get_gerrit_version("/var/war/gerrit.war")
        LOG.info(
            "Installed Gerrit version: %s; Provided Gerrit version: %s). ",
            installed_version,
            provided_version,
        )
        installed_minor_version = installed_version.split(".")[0:2]
        provided_minor_version = provided_version.split(".")[0:2]

        if (
            not self.is_online_reindex
            and installed_minor_version != provided_minor_version
        ):
            self.force_offline_reindex = True
        return installed_version != provided_version

    def _needs_init(self):
        installed_war_path = os.path.join(self.site, "bin", "gerrit.war")
        if not os.path.exists(installed_war_path):
            LOG.info("Gerrit is not yet installed. Initializing new site.")
            return True

        if self._gerrit_war_updated():
            LOG.info("Reinitializing site to perform update.")
            return True

        if self.plugin_installer.plugins_changed:
            LOG.info("Plugins were installed or updated. Initializing.")
            return True

        if self.config.packaged_plugins.difference(self.installed_plugins):
            LOG.info("Reininitializing site to install additional plugins.")
            return True

        LOG.info("No initialization required.")
        return False

    def _ensure_symlink(self, src, target):
        if not os.path.exists(src):
            raise FileNotFoundError(f"Unable to find mounted dir: {src}")

        if os.path.islink(target) and os.path.realpath(target) == src:
            return

        if os.path.exists(target):
            if os.path.isdir(target) and not os.path.islink(target):
                shutil.rmtree(target)
            else:
                os.remove(target)

        os.symlink(src, target)

    def _symlink_mounted_site_components(self):
        self._ensure_symlink(f"{MNT_PATH}/git", f"{self.site}/git")
        self._ensure_symlink(f"{MNT_PATH}/logs", f"{self.site}/logs")

        index_type = self.gerrit_config.get("index.type", default=IndexType.LUCENE.name)
        if IndexType[index_type.upper()] is IndexType.ELASTICSEARCH:
            self._ensure_symlink(f"{MNT_PATH}/index", f"{self.site}/index")

        data_dir = f"{self.site}/data"
        if os.path.exists(data_dir):
            for file_or_dir in os.listdir(data_dir):
                abs_path = os.path.join(data_dir, file_or_dir)
                if (
                    os.path.islink(abs_path)
                    and not os.path.exists(os.path.realpath(abs_path))
                ):
                    os.unlink(abs_path)
        else:
            os.makedirs(data_dir)

        mounted_data_dir = f"{MNT_PATH}/data"
        if os.path.exists(mounted_data_dir):
            for file_or_dir in os.listdir(mounted_data_dir):
                abs_path = os.path.join(data_dir, file_or_dir)
                abs_mounted_path = os.path.join(mounted_data_dir, file_or_dir)
                if os.path.isdir(abs_mounted_path):
                    self._ensure_symlink(abs_mounted_path, abs_path)

    def _symlink_configuration(self):
        etc_dir = f"{self.site}/etc"
        if not os.path.exists(etc_dir):
            os.makedirs(etc_dir)

        for config_type in ["config", "secret"]:
            if os.path.exists(f"{MNT_PATH}/etc/{config_type}"):
                for file_or_dir in os.listdir(f"{MNT_PATH}/etc/{config_type}"):
                    if os.path.isfile(
                        os.path.join(f"{MNT_PATH}/etc/{config_type}", file_or_dir)
                    ):
                        self._ensure_symlink(
                            os.path.join(f"{MNT_PATH}/etc/{config_type}", file_or_dir),
                            os.path.join(etc_dir, file_or_dir),
                        )

    def execute(self):
        if not self.is_replica:
            self._symlink_mounted_site_components()
        elif not NoteDbValidator(MNT_PATH).check():
            LOG.info("NoteDB not ready. Initializing repositories.")
            self._symlink_mounted_site_components()
        self._symlink_configuration()

        if os.path.exists(self.pid_file):
            os.remove(self.pid_file)

        self.plugin_installer.execute()

        if self._needs_init():
            if self.gerrit_config:
                LOG.info("Existing gerrit.config found.")
                dev_option = (
                    "--dev"
                    if self.gerrit_config.get(
                        "auth.type", "development_become_any_account"
                    ).lower()
                    == "development_become_any_account"
                    else ""
                )
            else:
                LOG.info("No gerrit.config found. Initializing default site.")
                dev_option = "--dev"

            flags = f"--no-auto-start --batch {dev_option}"

            command = f"java -jar /var/war/gerrit.war init {flags} -d {self.site}"

            init_process = subprocess.run(
                command.split(), stdout=subprocess.PIPE, check=True
            )

            if init_process.returncode > 0:
                LOG.error(
                    "An error occurred, when initializing Gerrit. Exit code: %d",
                    init_process.returncode,
                )
                sys.exit(1)

            self._symlink_configuration()

            if self.is_replica:
                self._symlink_mounted_site_components()

        get_reindexer(self.site, self.config).start(self.force_offline_reindex)
