# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

from google.protobuf import empty_pb2

from api import resource_name_converters as rnc
from api.v3 import api_constants
from api.v3 import monorail_servicer
from api.v3 import paginator
from api.v3.api_proto import projects_pb2
from api.v3.api_proto import projects_prpc_pb2
from businesslogic import work_env


class ProjectsServicer(monorail_servicer.MonorailServicer):
  """Handle API requests related to Project objects.
  Each API request is implemented with a method as defined in the
  .proto file. Each method does any request-specific validation, uses work_env
  to safely operate on business objects, and returns a response proto.
  """

  DESCRIPTION = projects_prpc_pb2.ProjectsServiceDescription

  @monorail_servicer.PRPCMethod
  def ListIssueTemplates(self, mc, request):
    # type: (MonorailContext, ListIssueTemplatesRequest) ->
    #   ListIssueTemplatesResponse
    """pRPC API method that implements ListIssueTemplates.

      Raises:
        InputException if the request.parent is invalid.
        NoSuchProjectException if no project exists with the given name.
    """
    project_id = rnc.IngestProjectName(mc.cnxn, request.parent, self.services)

    with work_env.WorkEnv(mc, self.services) as we:
      # TODO(crbug/monorail/7614): Eliminate the need to do this lookup.
      project = we.GetProject(project_id)
      mc.LookupLoggedInUserPerms(project)
      templates = we.ListProjectTemplates(project_id)

    return projects_pb2.ListIssueTemplatesResponse(
        templates=self.converter.ConvertIssueTemplates(project_id, templates))

  @monorail_servicer.PRPCMethod
  def ListComponentDefs(self, mc, request):
    # type: (MonorailContext, ListComponentDefsRequest) ->
    #   ListComponentDefsResponse
    """pRPC API method that implements ListComponentDefs.

      Raises:
        InputException if the request.parent is invalid.
        NoSuchProjectException if the parent project is not found.
    """
    project_id = rnc.IngestProjectName(mc.cnxn, request.parent, self.services)

    with work_env.WorkEnv(mc, self.services) as we:
      # TODO(crbug/monorail/7614): Eliminate the need to do this lookup.
      project = we.GetProject(project_id)
      mc.LookupLoggedInUserPerms(project)

      page_size = paginator.CoercePageSize(
        request.page_size, api_constants.MAX_COMPONENTS_PER_PAGE)
      pager = paginator.Paginator(
          parent=request.parent, page_size=page_size)
      list_result = we.ListComponentDefs(
          project_id, page_size, pager.GetStart(request.page_token))

      api_component_defs = self.converter.ConvertComponentDefs(
          list_result.items, project_id)

    return projects_pb2.ListComponentDefsResponse(
        component_defs=api_component_defs,
        next_page_token=pager.GenerateNextPageToken(list_result.next_start))

  @monorail_servicer.PRPCMethod
  def CreateComponentDef(self, mc, request):
    # type: (MonorailContext, CreateComponentDefRequest) ->
    #   ComponentDef
    """pRPC API method that implements CreateComponentDef.

      Raises:
        InputException if the request is invalid.
        NoSuchUserException if any given component admins or ccs do not exist.
        NoSuchProjectException if the parent project does not exist.
        PermissionException if the requester is not allowed to create
          this component.
    """
    project_id = rnc.IngestProjectName(mc.cnxn, request.parent, self.services)
    admin_ids = rnc.IngestUserNames(
        mc.cnxn, request.component_def.admins, self.services)
    cc_ids = rnc.IngestUserNames(
        mc.cnxn, request.component_def.ccs, self.services)

    with work_env.WorkEnv(mc, self.services) as we:
      component_def = we.CreateComponentDef(
          project_id, request.component_def.value,
          request.component_def.docstring, admin_ids, cc_ids,
          request.component_def.labels)

    return self.converter.ConvertComponentDef(component_def)

  @monorail_servicer.PRPCMethod
  def DeleteComponentDef(self, mc, request):
    # type: (MonorailContext, DeleteComponentDefRequest) -> Empty
    """pRPC API method that implements DeleteComponentDef.

      Raises:
        InputException if the request in invalid.
        NoSuchComponentException if the component does not exist.
        PermissionException if the requester is not allowed to delete
          this component.
        NoSuchProjectException if the parent project does not exist.
    """
    project_id, component_id = rnc.IngestComponentDefNames(
        mc.cnxn, [request.name], self.services)[0]

    with work_env.WorkEnv(mc, self.services) as we:
      we.DeleteComponentDef(project_id, component_id)

    return empty_pb2.Empty()

  @monorail_servicer.PRPCMethod
  def ListProjects(self, mc, _):
    # type: (MonorailContext, ListProjectsRequest) -> ListProjectsResponse
    """pRPC API method that implements ListProjects.

      Raises:
        InputException if the request.page_token is invalid or the request does
          not match the previous request that provided the given page_token.
    """
    with work_env.WorkEnv(mc, self.services) as we:
      # NOTE(crbug/monorail/7614): Until the referenced cleanup is complete,
      # all servicer methods that are scoped to a single Project need to call
      # mc.LookupLoggedInUserPerms.
      #  This method does not because it may be scoped to multiple projects.
      allowed_project_ids = we.ListProjects()
      projects_dict = we.GetProjects(allowed_project_ids)
      projects = [projects_dict[proj_id] for proj_id in allowed_project_ids]

    # TODO(crbug.com/monorail/7505): Add pagination logic.
    return projects_pb2.ListProjectsResponse(
        projects=self.converter.ConvertProjects(projects))
