# Copyright 2016 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

"""Servlet to export a project's config in JSON format.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

import ezt

from framework import permissions
from framework import jsonfeed
from framework import servlet
from project import project_helpers
from tracker import tracker_bizobj


class ProjectExport(servlet.Servlet):
  """Only site admins can export a project"""

  _PAGE_TEMPLATE = 'project/project-export-page.ezt'
  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ADMIN

  def AssertBasePermission(self, mr):
    """Make sure that the logged in user has permission to view this page."""
    super(ProjectExport, self).AssertBasePermission(mr)
    if not mr.auth.user_pb.is_site_admin:
      raise permissions.PermissionException(
          'Only site admins may export project configuration')

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""

    return {
        'admin_tab_mode': None,
        'page_perms': self.MakePagePerms(mr, None, permissions.CREATE_ISSUE),
    }


class ProjectExportJSON(jsonfeed.JsonFeed):
  """ProjectExportJSON shows all configuration for a Project in JSON form."""

  # Pretty-print the JSON output.
  JSON_INDENT = 4

  def AssertBasePermission(self, mr):
    """Make sure that the logged in user has permission to view this page."""
    super(ProjectExportJSON, self).AssertBasePermission(mr)
    if not mr.auth.user_pb.is_site_admin:
      raise permissions.PermissionException(
          'Only site admins may export project configuration')

  def HandleRequest(self, mr):
    """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """
    project = self.services.project.GetProject(mr.cnxn, mr.project.project_id)
    user_id_set = project_helpers.UsersInvolvedInProject(project)

    config = self.services.config.GetProjectConfig(
        mr.cnxn, mr.project.project_id)
    templates = self.services.template.GetProjectTemplates(
        mr.cnxn, config.project_id)
    involved_users = self.services.config.UsersInvolvedInConfig(
        config, templates)
    user_id_set.update(involved_users)

    # The value 0 indicates "no user", e.g., that an issue has no owner.
    # We don't need to create a User row to represent that.
    user_id_set.discard(0)
    email_dict = self.services.user.LookupUserEmails(mr.cnxn, user_id_set)

    project_json = self._MakeProjectJSON(project, email_dict)
    config_json = self._MakeConfigJSON(config, email_dict, templates)

    json_data = {
        'metadata': {
            'version': 1,
            'when': int(time.time()),
            'who': mr.auth.email,
        },
        'project': project_json,
        'config': config_json,
        # This list could be derived from the others, but we provide it for
        # ease of processing.
        'emails': list(email_dict.values()),
    }
    return json_data

  def _MakeProjectJSON(self, project, email_dict):
    project_json = {
      'name': project.project_name,
      'summary': project.summary,
      'description': project.description,
      'state': project.state.name,
      'access': project.access.name,
      'owners': [email_dict.get(user) for user in project.owner_ids],
      'committers': [email_dict.get(user) for user in project.committer_ids],
      'contributors': [
          email_dict.get(user) for user in project.contributor_ids],
      'perms': [self._MakePermJSON(perm, email_dict)
                for perm in project.extra_perms],
      'issue_notify_address': project.issue_notify_address,
      'attachment_bytes': project.attachment_bytes_used,
      'attachment_quota': project.attachment_quota,
      'recent_activity': project.recent_activity,
      'process_inbound_email': project.process_inbound_email,
      'only_owners_remove_restrictions':
          project.only_owners_remove_restrictions,
      'only_owners_see_contributors': project.only_owners_see_contributors,
      'revision_url_format': project.revision_url_format,
      'read_only_reason': project.read_only_reason,
    }
    return project_json

  def _MakePermJSON(self, perm, email_dict):
    perm_json = {
      'member': email_dict.get(perm.member_id),
      'perms': [p for p in perm.perms],
    }
    return perm_json

  def _MakeConfigJSON(self, config, email_dict, project_templates):
    config_json = {
      'statuses':
          [self._MakeStatusJSON(status)
           for status in config.well_known_statuses],
      'statuses_offer_merge':
          [status for status in config.statuses_offer_merge],
      'labels':
          [self._MakeLabelJSON(label) for label in config.well_known_labels],
      'exclusive_label_prefixes':
          [label for label in config.exclusive_label_prefixes],
      # TODO(http://crbug.com/monorail/7217): Export the project's FieldDefs.
      'components':
          [self._MakeComponentJSON(component, email_dict)
           for component in config.component_defs],
      'templates':
          [self._MakeTemplateJSON(template, email_dict)
           for template in project_templates],
      'developer_template': config.default_template_for_developers,
      'user_template': config.default_template_for_users,
      'list_cols': config.default_col_spec,
      'list_spec': config.default_sort_spec,
      'grid_x': config.default_x_attr,
      'grid_y': config.default_y_attr,
      'only_known_values': config.restrict_to_known,
    }
    if config.custom_issue_entry_url:
      config_json.update({'issue_entry_url': config.custom_issue_entry_url})
    return config_json

  def _MakeTemplateJSON(self, template, email_dict):
    template_json = {
      'name': template.name,
      'summary': template.summary,
      'content': template.content,
      'summary_must_be_edited': template.summary_must_be_edited,
      'owner': email_dict.get(template.owner_id),
      'status': template.status,
      'labels': [label for label in template.labels],
      # TODO(http://crbug.com/monorail/7217): Export the template's Fields.
      'members_only': template.members_only,
      'owner_defaults_to_member': template.owner_defaults_to_member,
      'component_required': template.component_required,
      'admins': [email_dict(user) for user in template.admin_ids],
    }
    return template_json

  def _MakeStatusJSON(self, status):
    status_json = {
      'status': status.status,
      'open': status.means_open,
      'docstring': status.status_docstring,
    }
    return status_json

  def _MakeLabelJSON(self, label):
    label_json = {
      'label': label.label,
      'docstring': label.label_docstring,
    }
    return label_json

  def _MakeComponentJSON(self, component, email_dict):
    component_json = {
      'path': component.path,
      'docstring': component.docstring,
      'admins': [email_dict.get(user) for user in component.admin_ids],
      'ccs': [email_dict.get(user) for user in component.cc_ids],
    }
    return component_json
