# 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

"""Class that implements the reranking on the hotlistissues table page."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging

from features import features_bizobj
from features import hotlist_helpers
from framework import jsonfeed
from framework import permissions
from framework import sorting
from services import features_svc
from tracker import rerank_helpers


# TODO: convert to FLaskJsonFeed while conver to flask
class RerankHotlistIssue(jsonfeed.JsonFeed):
  """Rerank an issue in a hotlist."""

  def AssertBasePermission(self, mr):
    super(RerankHotlistIssue, self).AssertBasePermission(mr)
    if mr.target_id and mr.moved_ids and mr.split_above:
      try:
        hotlist = self._GetHotlist(mr)
      except features_svc.NoSuchHotlistException:
        return
      edit_perm = permissions.CanEditHotlist(
          mr.auth.effective_ids, mr.perms, hotlist)
      if not edit_perm:
        raise permissions.PermissionException(
            'User is not allowed to re-rank this hotlist')

  def HandleRequest(self, mr):
    changed_ranks = self._GetNewRankings(mr)

    if changed_ranks:
      relations_to_change = dict(
          (issue_id, rank) for issue_id, rank in changed_ranks)

      self.services.features.UpdateHotlistItemsFields(
          mr.cnxn, mr.hotlist_id, new_ranks=relations_to_change)

      hotlist_items = self.services.features.GetHotlist(
          mr.cnxn, mr.hotlist_id).items

      # Note: Cannot use mr.hotlist because hotlist_issues
      # of mr.hotlist is not updated

      sorting.InvalidateArtValuesKeys(
          mr.cnxn, [hotlist_item.issue_id for hotlist_item in hotlist_items])
      (table_data, _) = hotlist_helpers.CreateHotlistTableData(
          mr, hotlist_items, self.services)

      json_table_data = [{
          'cells': [{
              'type': cell.type,
              'values': [{
                  'item': value.item,
                  'isDerived': value.is_derived,
              } for value in cell.values],
              'colIndex': cell.col_index,
              'align': cell.align,
              'noWrap': cell.NOWRAP,
              'nonColLabels': [{
                  'value': label.value,
                  'isDerived': label.is_derived,
              } for label in cell.non_column_labels],
          } for cell in table_row.cells],
          'issueRef': table_row.issue_ref,
          'idx': table_row.idx,
          'projectName': table_row.project_name,
          'projectURL': table_row.project_url,
          'localID': table_row.local_id,
          'issueID': table_row.issue_id,
          'isStarred': table_row.starred,
          'issueCleanURL': table_row.issue_clean_url,
          'issueContextURL': table_row.issue_ctx_url,
      } for table_row in table_data]

      for row, json_row in zip(
          [table_row for table_row in table_data], json_table_data):
        if (row.group and row.group.cells):
          json_row.update({'group': {
              'rowsInGroup': row.group.rows_in_group,
              'cells': [{'groupName': cell.group_name,
                         'values': [{
                          # TODO(jojwang): check if this gives error when there
                          # is no value.item
                             'item': value.item if value.item else 'None',
                         } for value in cell.values],
              } for cell in row.group.cells],
          }})
        else:
          json_row['group'] = 'no'

      return {'table_data': json_table_data}
    else:
      return {'table_data': ''}

  def _GetHotlist(self, mr):
    """Retrieve the current hotlist."""
    if mr.hotlist_id is None:
      return None
    try:
      hotlist = self.services.features.GetHotlist( mr.cnxn, mr.hotlist_id)
    except features_svc.NoSuchHotlistException:
      self.abort(404, 'hotlist not found')
    return hotlist

  def _GetNewRankings(self, mr):
    """Compute new issue reference rankings."""
    missing = False
    if not (mr.target_id):
      logging.info('No target_id.')
      missing = True
    if not (mr.moved_ids):
      logging.info('No moved_ids.')
      missing = True
    if mr.split_above is None:
      logging.info('No split_above.')
      missing = True
    if missing:
      return

    untouched_items = [
        (item.issue_id, item.rank) for item in
        mr.hotlist.items if item.issue_id not in mr.moved_ids]

    lower, higher = features_bizobj.SplitHotlistIssueRanks(
        mr.target_id, mr.split_above, untouched_items)
    return rerank_helpers.GetInsertRankings(lower, higher, mr.moved_ids)

  # def GetRerankHotlistIssuePage(self, **kwargs):
  #   return self.handler(**kwargs)

  # def PostRerankHotlistIssuePage(self, **kwargs):
  #   return self.handler(**kwargs)
