# Copyright (C) 2009 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 GitError
from error import RepoExitError
from progress import Progress
from project import Project
from repo_logging import RepoLogger


logger = RepoLogger(__file__)


class CheckoutBranchResult(NamedTuple):
    # Whether the Project is on the branch (i.e. branch exists and no errors)
    result: bool
    project: Project
    error: Exception


class CheckoutCommandError(RepoExitError):
    """Exception thrown when checkout command fails."""


class MissingBranchError(RepoExitError):
    """Exception thrown when no project has specified branch."""


class Checkout(Command):
    COMMON = True
    helpSummary = "Checkout a branch for development"
    helpUsage = """
%prog <branchname> [<project>...]
"""
    helpDescription = """
The '%prog' command checks out an existing branch that was previously
created by 'repo start'.

The command is equivalent to:

  repo forall [<project>...] -c git checkout <branchname>
"""
    PARALLEL_JOBS = DEFAULT_LOCAL_JOBS

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

    def _ExecuteOne(self, nb, project):
        """Checkout one project."""
        error = None
        result = None
        try:
            result = project.CheckoutBranch(nb)
        except GitError as e:
            error = e
        return CheckoutBranchResult(result, project, error)

    def Execute(self, opt, args):
        nb = args[0]
        err = []
        err_projects = []
        success = []
        all_projects = self.GetProjects(
            args[1:], all_manifests=not opt.this_manifest_only
        )

        def _ProcessResults(_pool, pm, results):
            for result in results:
                if result.error is not None:
                    err.append(result.error)
                    err_projects.append(result.project)
                elif result.result:
                    success.append(result.project)
                pm.update(msg="")

        self.ExecuteInParallel(
            opt.jobs,
            functools.partial(self._ExecuteOne, nb),
            all_projects,
            callback=_ProcessResults,
            output=Progress(
                f"Checkout {nb}", len(all_projects), quiet=opt.quiet
            ),
        )

        if err_projects:
            for p in err_projects:
                logger.error("error: %s/: cannot checkout %s", p.relpath, nb)
            raise CheckoutCommandError(aggregate_errors=err)
        elif not success:
            msg = f"error: no project has branch {nb}"
            logger.error(msg)
            raise MissingBranchError(msg)
