# 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.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,
        )
        return installed_version != provided_version

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

        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.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):
                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):
                if (
                    os.path.isdir(file_or_dir)
                    and os.path.islink(file_or_dir)
                    and not os.path.exists(os.readlink(file_or_dir))
                ):
                    os.unlink(file_or_dir)
        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):
                if os.path.isdir(file_or_dir):
                    self._ensure_symlink(
                        os.path.join(mounted_data_dir, file_or_dir),
                        os.path.join(data_dir, file_or_dir),
                    )

    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 not self._needs_init():
            return

        if self.gerrit_config:
            LOG.info("Existing gerrit.config found.")
            dev_option = (
                "--dev"
                if self.gerrit_config.get("auth.type").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()
        else:
            get_reindexer(self.site, self.config).start(False)
