# Copyright (C) 2008 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 functools
from typing import NamedTuple

from command import Command
from command import DEFAULT_LOCAL_JOBS
from error import RepoExitError
from git_command import git
from git_config import IsImmutable
from progress import Progress
from repo_logging import RepoLogger


logger = RepoLogger(__file__)


class ExecuteOneResult(NamedTuple):
    project_idx: int
    error: Exception


class StartError(RepoExitError):
    """Exit error for failed start command."""


class Start(Command):
    COMMON = True
    helpSummary = "Start a new branch for development"
    helpUsage = """
%prog <newbranchname> [--all | <project>...]
"""
    helpDescription = """
'%prog' begins a new branch of development, starting from the
revision specified in the manifest.
"""
    PARALLEL_JOBS = DEFAULT_LOCAL_JOBS

    def _Options(self, p):
        p.add_option(
            "--all",
            action="store_true",
            help="begin branch in all projects",
        )
        p.add_option(
            "-r",
            "--rev",
            "--revision",
            dest="revision",
            help="point branch at this revision instead of upstream",
        )
        p.add_option(
            "--head",
            "--HEAD",
            dest="revision",
            action="store_const",
            const="HEAD",
            help="abbreviation for --rev HEAD",
        )

    def ValidateOptions(self, opt, args):
        if not args:
            self.Usage()

        nb = args[0]
        if not git.check_ref_format("heads/%s" % nb):
            self.OptionParser.error("'%s' is not a valid name" % nb)

    @classmethod
    def _ExecuteOne(cls, revision, nb, default_revisionExpr, project_idx):
        """Start one project."""
        # If the current revision is immutable, such as a SHA1, a tag or
        # a change, then we can't push back to it. Substitute with
        # dest_branch, if defined; or with manifest default revision instead.
        branch_merge = ""
        error = None
        project = cls.get_parallel_context()["projects"][project_idx]
        if IsImmutable(project.revisionExpr):
            if project.dest_branch:
                branch_merge = project.dest_branch
            else:
                branch_merge = default_revisionExpr

        try:
            project.StartBranch(
                nb, branch_merge=branch_merge, revision=revision
            )
        except Exception as e:
            logger.error("error: unable to checkout %s: %s", project.name, e)
            error = e
        return ExecuteOneResult(project_idx, error)

    def Execute(self, opt, args):
        nb = args[0]
        err_projects = []
        err = []
        projects = []
        if not opt.all:
            projects = args[1:]
            if len(projects) < 1:
                projects = ["."]  # start it in the local project by default

        all_projects = self.GetProjects(
            projects,
            all_manifests=not opt.this_manifest_only,
        )

        def _ProcessResults(_pool, pm, results):
            for result in results:
                if result.error:
                    project = all_projects[result.project_idx]
                    err_projects.append(project)
                    err.append(result.error)
                pm.update(msg="")

        with self.ParallelContext():
            self.get_parallel_context()["projects"] = all_projects
            self.ExecuteInParallel(
                opt.jobs,
                functools.partial(
                    self._ExecuteOne,
                    opt.revision,
                    nb,
                    self.manifest.default.revisionExpr,
                ),
                range(len(all_projects)),
                callback=_ProcessResults,
                output=Progress(
                    f"Starting {nb}", len(all_projects), quiet=opt.quiet
                ),
                chunksize=1,
            )

        if err_projects:
            for p in err_projects:
                logger.error(
                    "error: %s/: cannot start %s",
                    p.RelPath(local=opt.this_manifest_only),
                    nb,
                )
            msg_fmt = "cannot start %d project(s)"
            self.git_event_log.ErrorEvent(
                msg_fmt % (len(err_projects)), msg_fmt
            )
            raise StartError(aggregate_errors=err)
