# 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 IsValidBranchName
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 IsValidBranchName(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)
