# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Classes and functions for displaying lists of project artifacts.

This file exports classes TableRow and TableCell that help
represent HTML table rows and cells.  These classes make rendering
HTML tables that list project artifacts much easier to do with EZT.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import itertools
import logging

from functools import total_ordering

import ezt

from framework import framework_constants
from framework import template_helpers
from framework import timestr
from mrproto import tracker_pb2
from tracker import tracker_bizobj
from tracker import tracker_constants


def ComputeUnshownColumns(results, shown_columns, config, built_in_cols):
  """Return a list of unshown columns that the user could add.

  Args:
    results: list of search result PBs. Each must have labels.
    shown_columns: list of column names to be used in results table.
    config: harmonized config for the issue search, including all
        well known labels and custom fields.
    built_in_cols: list of other column names that are built into the tool.
      E.g., star count, or creation date.

  Returns:
    List of column names to append to the "..." menu.
  """
  unshown_set = set()  # lowercases column names
  unshown_list = []  # original-case column names
  shown_set = {col.lower() for col in shown_columns}
  labels_already_seen = set()  # whole labels, original case

  def _MaybeAddLabel(label_name):
    """Add the key part of the given label if needed."""
    if label_name.lower() in labels_already_seen:
      return
    labels_already_seen.add(label_name.lower())
    if '-' in label_name:
      col, _value = label_name.split('-', 1)
      _MaybeAddCol(col)

  def _MaybeAddCol(col):
    if col.lower() not in shown_set and col.lower() not in unshown_set:
      unshown_list.append(col)
      unshown_set.add(col.lower())

  # The user can always add any of the default columns.
  for col in config.default_col_spec.split():
    _MaybeAddCol(col)

  # The user can always add any of the built-in columns.
  for col in built_in_cols:
    _MaybeAddCol(col)

  # The user can add a column for any well-known labels
  for wkl in config.well_known_labels:
    _MaybeAddLabel(wkl.label)

  phase_names = set(itertools.chain.from_iterable(
      (phase.name.lower() for phase in result.phases) for result in results))
  # The user can add a column for any custom field
  field_ids_alread_seen = set()
  for fd in config.field_defs:
    field_lower = fd.field_name.lower()
    field_ids_alread_seen.add(fd.field_id)
    if fd.is_phase_field:
      for name in phase_names:
        phase_field_col = name + '.' + field_lower
        if (phase_field_col not in shown_set and
            phase_field_col not in unshown_set):
          unshown_list.append(phase_field_col)
          unshown_set.add(phase_field_col)
    elif field_lower not in shown_set and field_lower not in unshown_set:
      unshown_list.append(fd.field_name)
      unshown_set.add(field_lower)

    if fd.field_type == tracker_pb2.FieldTypes.APPROVAL_TYPE:
      approval_lower_approver = (
          field_lower + tracker_constants.APPROVER_COL_SUFFIX)
      if (approval_lower_approver not in shown_set and
          approval_lower_approver not in unshown_set):
        unshown_list.append(
            fd.field_name + tracker_constants.APPROVER_COL_SUFFIX)
        unshown_set.add(approval_lower_approver)

  # The user can add a column for any key-value label or field in the results.
  for r in results:
    for label_name in tracker_bizobj.GetLabels(r):
      _MaybeAddLabel(label_name)
    for field_value in r.field_values:
      if field_value.field_id not in field_ids_alread_seen:
        field_ids_alread_seen.add(field_value.field_id)
        fd = tracker_bizobj.FindFieldDefByID(field_value.field_id, config)
        if fd:  # could be None for a foreign field, which we don't display.
          field_lower = fd.field_name.lower()
          if field_lower not in shown_set and field_lower not in unshown_set:
            unshown_list.append(fd.field_name)
            unshown_set.add(field_lower)

  return sorted(unshown_list)


def ExtractUniqueValues(columns, artifact_list, users_by_id,
                        config, related_issues, hotlist_context_dict=None):
  """Build a nested list of unique values so the user can auto-filter.

  Args:
    columns: a list of lowercase column name strings, which may contain
        combined columns like "priority/pri".
    artifact_list: a list of artifacts in the complete set of search results.
    users_by_id: dict mapping user_ids to UserViews.
    config: ProjectIssueConfig PB for the current project.
    related_issues: dict {issue_id: issue} of pre-fetched related issues.
    hotlist_context_dict: dict for building a hotlist grid table

  Returns:
    [EZTItem(col1, colname1, [val11, val12,...]), ...]
    A list of EZTItems, each of which has a col_index, column_name,
    and a list of unique values that appear in that column.
  """
  column_values = {col_name: {} for col_name in columns}

  # For each combined column "a/b/c", add entries that point from "a" back
  # to "a/b/c", from "b" back to "a/b/c", and from "c" back to "a/b/c".
  combined_column_parts = collections.defaultdict(list)
  for col in columns:
    if '/' in col:
      for col_part in col.split('/'):
        combined_column_parts[col_part].append(col)

  unique_labels = set()
  for art in artifact_list:
    unique_labels.update(tracker_bizobj.GetLabels(art))

  for label in unique_labels:
    if '-' in label:
      col, val = label.split('-', 1)
      col = col.lower()
      if col in column_values:
        column_values[col][val.lower()] = val
      if col in combined_column_parts:
        for combined_column in combined_column_parts[col]:
          column_values[combined_column][val.lower()] = val
    else:
      if 'summary' in column_values:
        column_values['summary'][label.lower()] = label

  # TODO(jrobbins): Consider refacting some of this to tracker_bizobj
  # or a new builtins.py to reduce duplication.
  if 'reporter' in column_values:
    for art in artifact_list:
      reporter_id = art.reporter_id
      if reporter_id and reporter_id in users_by_id:
        reporter_username = users_by_id[reporter_id].display_name
        column_values['reporter'][reporter_username] = reporter_username

  if 'owner' in column_values:
    for art in artifact_list:
      owner_id = tracker_bizobj.GetOwnerId(art)
      if owner_id and owner_id in users_by_id:
        owner_username = users_by_id[owner_id].display_name
        column_values['owner'][owner_username] = owner_username

  if 'cc' in column_values:
    for art in artifact_list:
      cc_ids = tracker_bizobj.GetCcIds(art)
      for cc_id in cc_ids:
        if cc_id and cc_id in users_by_id:
          cc_username = users_by_id[cc_id].display_name
          column_values['cc'][cc_username] = cc_username

  if 'component' in column_values:
    for art in artifact_list:
      all_comp_ids = list(art.component_ids) + list(art.derived_component_ids)
      for component_id in all_comp_ids:
        cd = tracker_bizobj.FindComponentDefByID(component_id, config)
        if cd:
          column_values['component'][cd.path] = cd.path

  if 'stars' in column_values:
    for art in artifact_list:
      star_count = art.star_count
      column_values['stars'][star_count] = star_count

  if 'status' in column_values:
    for art in artifact_list:
      status = tracker_bizobj.GetStatus(art)
      if status:
        column_values['status'][status.lower()] = status

  if 'project' in column_values:
    for art in artifact_list:
      project_name = art.project_name
      column_values['project'][project_name] = project_name

  if 'mergedinto' in column_values:
    for art in artifact_list:
      if art.merged_into and art.merged_into != 0:
        merged_issue = related_issues[art.merged_into]
        merged_issue_ref = tracker_bizobj.FormatIssueRef((
            merged_issue.project_name, merged_issue.local_id))
        column_values['mergedinto'][merged_issue_ref] = merged_issue_ref

  if 'blocked' in column_values:
    for art in artifact_list:
      if art.blocked_on_iids:
        column_values['blocked']['is_blocked'] = 'Yes'
      else:
        column_values['blocked']['is_not_blocked'] = 'No'

  if 'blockedon' in column_values:
    for art in artifact_list:
      if art.blocked_on_iids:
        for blocked_on_iid in art.blocked_on_iids:
          blocked_on_issue = related_issues[blocked_on_iid]
          blocked_on_ref = tracker_bizobj.FormatIssueRef((
              blocked_on_issue.project_name, blocked_on_issue.local_id))
          column_values['blockedon'][blocked_on_ref] = blocked_on_ref

  if 'blocking' in column_values:
    for art in artifact_list:
      if art.blocking_iids:
        for blocking_iid in art.blocking_iids:
          blocking_issue = related_issues[blocking_iid]
          blocking_ref = tracker_bizobj.FormatIssueRef((
              blocking_issue.project_name, blocking_issue.local_id))
          column_values['blocking'][blocking_ref] = blocking_ref

  if 'added' in column_values:
    for art in artifact_list:
      if hotlist_context_dict and hotlist_context_dict[art.issue_id]:
        issue_dict = hotlist_context_dict[art.issue_id]
        date_added = issue_dict['date_added']
        column_values['added'][date_added] = date_added

  if 'adder' in column_values:
    for art in artifact_list:
      if hotlist_context_dict and hotlist_context_dict[art.issue_id]:
        issue_dict = hotlist_context_dict[art.issue_id]
        adder_id = issue_dict['adder_id']
        adder = users_by_id[adder_id].display_name
        column_values['adder'][adder] = adder

  if 'note' in column_values:
    for art in artifact_list:
      if hotlist_context_dict and hotlist_context_dict[art.issue_id]:
        issue_dict = hotlist_context_dict[art.issue_id]
        note = issue_dict['note']
        if issue_dict['note']:
          column_values['note'][note] = note

  if 'attachments' in column_values:
    for art in artifact_list:
      attachment_count = art.attachment_count
      column_values['attachments'][attachment_count] = attachment_count

  # Add all custom field values if the custom field name is a shown column.
  field_id_to_col = {}
  for art in artifact_list:
    for fv in art.field_values:
      field_col, field_type = field_id_to_col.get(fv.field_id, (None, None))
      if field_col == 'NOT_SHOWN':
        continue
      if field_col is None:
        fd = tracker_bizobj.FindFieldDefByID(fv.field_id, config)
        if not fd:
          field_id_to_col[fv.field_id] = 'NOT_SHOWN', None
          continue
        field_col = fd.field_name.lower()
        field_type = fd.field_type
        if field_col not in column_values:
          field_id_to_col[fv.field_id] = 'NOT_SHOWN', None
          continue
        field_id_to_col[fv.field_id] = field_col, field_type

      if field_type == tracker_pb2.FieldTypes.ENUM_TYPE:
        continue  # Already handled by label parsing
      elif field_type == tracker_pb2.FieldTypes.INT_TYPE:
        val = fv.int_value
      elif field_type == tracker_pb2.FieldTypes.STR_TYPE:
        val = fv.str_value
      elif field_type == tracker_pb2.FieldTypes.USER_TYPE:
        user = users_by_id.get(fv.user_id)
        val = user.email if user else framework_constants.NO_USER_NAME
      elif field_type == tracker_pb2.FieldTypes.DATE_TYPE:
        val = fv.int_value  # TODO(jrobbins): convert to date
      elif field_type == tracker_pb2.FieldTypes.BOOL_TYPE:
        val = 'Yes' if fv.int_value else 'No'

      column_values[field_col][val] = val

  # TODO(jrobbins): make the capitalization of well-known unique label and
  # status values match the way it is written in the issue config.

  # Return EZTItems for each column in left-to-right display order.
  result = []
  for i, col_name in enumerate(columns):
    # TODO(jrobbins): sort each set of column values top-to-bottom, by the
    # order specified in the project artifact config. For now, just sort
    # lexicographically to make expected output defined.
    sorted_col_values = sorted(column_values[col_name].values())
    result.append(template_helpers.EZTItem(
        col_index=i, column_name=col_name, filter_values=sorted_col_values))

  return result


def MakeTableData(
    visible_results, starred_items, lower_columns, lower_group_by,
    users_by_id, cell_factories, id_accessor, related_issues,
    viewable_iids_set, config, context_for_all_issues=None):
  """Return a list of list row objects for display by EZT.

  Args:
    visible_results: list of artifacts to display on one pagination page.
    starred_items: list of IDs/names of items in the current project
        that the signed in user has starred.
    lower_columns: list of column names to display, all lowercase.  These can
        be combined column names, e.g., 'priority/pri'.
    lower_group_by: list of column names that define row groups, all lowercase.
    users_by_id: dict mapping user IDs to UserViews.
    cell_factories: dict of functions that each create TableCell objects.
    id_accessor: function that maps from an artifact to the ID/name that might
        be in the starred items list.
    related_issues: dict {issue_id: issue} of pre-fetched related issues.
    viewable_iids_set: set of issue ids that can be viewed by the user.
    config: ProjectIssueConfig PB for the current project.
    context_for_all_issues: A dictionary of dictionaries containing values
        passed in to cell factory functions to create TableCells. Dictionary
        form: {issue_id: {'rank': issue_rank, 'issue_info': info_value, ..},
        issue_id: {'rank': issue_rank}, ..}

  Returns:
    A list of TableRow objects, one for each visible result.
  """
  table_data = []

  group_cell_factories = [
      ChooseCellFactory(group.strip('-'), cell_factories, config)
      for group in lower_group_by]

  # Make a list of cell factories, one for each column.
  factories_to_use = [
      ChooseCellFactory(col, cell_factories, config) for col in lower_columns]

  current_group = None
  for idx, art in enumerate(visible_results):
    row = MakeRowData(
        art, lower_columns, users_by_id, factories_to_use, related_issues,
        viewable_iids_set, config, context_for_all_issues)
    row.starred = ezt.boolean(id_accessor(art) in starred_items)
    row.idx = idx  # EZT does not have loop counters, so add idx.
    table_data.append(row)
    row.group = None

    # Also include group information for the first row in each group.
    # TODO(jrobbins): This seems like more overhead than we need for the
    # common case where no new group heading row is to be inserted.
    group = MakeRowData(
        art, [group_name.strip('-') for group_name in lower_group_by],
        users_by_id, group_cell_factories, related_issues, viewable_iids_set,
        config, context_for_all_issues)
    for cell, group_name in zip(group.cells, lower_group_by):
      cell.group_name = group_name
    if group == current_group:
      current_group.rows_in_group += 1
    else:
      row.group = group
      current_group = group
      current_group.rows_in_group = 1

  return table_data


def MakeRowData(
    art, columns, users_by_id, cell_factory_list, related_issues,
    viewable_iids_set, config, context_for_all_issues):
  """Make a TableRow for use by EZT when rendering HTML table of results.

  Args:
    art: a project artifact PB
    columns: list of lower-case column names
    users_by_id: dictionary {user_id: UserView} with each UserView having
        a "display_name" member.
    cell_factory_list: list of functions that each create TableCell
        objects for a given column.
    related_issues: dict {issue_id: issue} of pre-fetched related issues.
    viewable_iids_set: set of issue ids that can be viewed by the user.
    config: ProjectIssueConfig PB for the current project.
    context_for_all_issues: A dictionary of dictionaries containing values
        passed in to cell factory functions to create TableCells. Dictionary
        form: {issue_id: {'rank': issue_rank, 'issue_info': info_value, ..},
        issue_id: {'rank': issue_rank}, ..}

  Returns:
    A TableRow object for use by EZT to render a table of results.
  """
  if context_for_all_issues is None:
    context_for_all_issues = {}
  ordered_row_data = []
  non_col_labels = []
  label_values = collections.defaultdict(list)

  flattened_columns = set()
  for col in columns:
    if '/' in col:
      flattened_columns.update(col.split('/'))
    else:
      flattened_columns.add(col)

  # Group all "Key-Value" labels by key, and separate the "OneWord" labels.
  _AccumulateLabelValues(
      art.labels, flattened_columns, label_values, non_col_labels)

  _AccumulateLabelValues(
      art.derived_labels, flattened_columns, label_values,
      non_col_labels, is_derived=True)

  # Build up a list of TableCell objects for this row.
  for i, col in enumerate(columns):
    factory = cell_factory_list[i]
    kw = {
        'col': col,
        'users_by_id': users_by_id,
        'non_col_labels': non_col_labels,
        'label_values': label_values,
        'related_issues': related_issues,
        'viewable_iids_set': viewable_iids_set,
        'config': config,
        }
    kw.update(context_for_all_issues.get(art.issue_id, {}))
    new_cell = factory(art, **kw)
    new_cell.col_index = i
    ordered_row_data.append(new_cell)

  return TableRow(ordered_row_data)


def _AccumulateLabelValues(
    labels, columns, label_values, non_col_labels, is_derived=False):
  """Parse OneWord and Key-Value labels for display in a list page.

  Args:
    labels: a list of label strings.
    columns: a list of column names.
    label_values: mutable dictionary {key: [value, ...]} of label values
        seen so far.
    non_col_labels: mutable list of OneWord labels seen so far.
    is_derived: true if these labels were derived via rules.

  Returns:
    Nothing.  But, the given label_values dictionary will grow to hold
    the values of the key-value labels passed in, and the non_col_labels
    list will grow to hold the OneWord labels passed in.  These are shown
    in label columns, and in the summary column, respectively
  """
  for label_name in labels:
    if '-' in label_name:
      parts = label_name.split('-')
      for pivot in range(1, len(parts)):
        column_name = '-'.join(parts[:pivot])
        value = '-'.join(parts[pivot:])
        column_name = column_name.lower()
        if column_name in columns:
          label_values[column_name].append((value, is_derived))
    else:
      non_col_labels.append((label_name, is_derived))


@total_ordering
class TableRow(object):
  """A tiny auxiliary class to represent a row in an HTML table."""

  def __init__(self, cells):
    """Initialize the table row with the given data."""
    self.cells = cells
    # Used by MakeTableData for layout.
    self.idx = None
    self.group = None
    self.rows_in_group = None
    self.starred = None

  def __eq__(self, other):
    """A row is == if each cell is == to the cells in the other row."""
    return other and self.cells == other.cells

  def __ne__(self, other):
    return not other and self.cells != other.cells

  def __lt__(self, other):
    return other and self.cells < other.cells

  def DebugString(self):
    """Return a string that is useful for on-page debugging."""
    return 'TR(%s)' % self.cells


# TODO(jrobbins): also add unsortable... or change this to a list of operations
# that can be done.
CELL_TYPE_ID = 'ID'
CELL_TYPE_SUMMARY = 'summary'
CELL_TYPE_ATTR = 'attr'
CELL_TYPE_UNFILTERABLE = 'unfilterable'
CELL_TYPE_NOTE = 'note'
CELL_TYPE_PROJECT = 'project'
CELL_TYPE_URL = 'url'
CELL_TYPE_ISSUES = 'issues'


@total_ordering
class TableCell(object):
  """Helper class to represent a table cell when rendering using EZT."""

  # Should instances of this class be rendered with whitespace:nowrap?
  # Subclasses can override this constant.
  NOWRAP = ezt.boolean(True)

  def __init__(self, cell_type, explicit_values,
               derived_values=None, non_column_labels=None, align='',
               sort_values=True):
    """Store all the given data for later access by EZT."""
    self.type = cell_type
    self.align = align
    self.col_index = 0  # Is set afterward
    self.values = []
    if non_column_labels:
      self.non_column_labels = [
          template_helpers.EZTItem(value=v, is_derived=ezt.boolean(d))
          for v, d in non_column_labels]
    else:
      self.non_column_labels = []

    for v in (sorted(explicit_values) if sort_values else explicit_values):
      self.values.append(CellItem(v))

    if derived_values:
      for v in (sorted(derived_values) if sort_values else derived_values):
        self.values.append(CellItem(v, is_derived=True))

  def __eq__(self, other):
    """A row is == if each cell is == to the cells in the other row."""
    return other and self.values == other.values

  def __ne__(self, other):
    return not other and self.values != other.values

  def __lt__(self, other):
    return other and self.values < other.values

  def DebugString(self):
    return 'TC(%r, %r, %r)' % (
        self.type,
        [v.DebugString() for v in self.values],
        self.non_column_labels)


def CompositeFactoryTableCell(factory_col_list_arg):
  """Cell factory that combines multiple cells in a combined column."""

  class FactoryClass(TableCell):
    factory_col_list = factory_col_list_arg

    def __init__(self, art, **kw):
      TableCell.__init__(self, CELL_TYPE_UNFILTERABLE, [])

      for sub_factory, sub_col in self.factory_col_list:
        kw['col'] = sub_col
        sub_cell = sub_factory(art, **kw)
        self.non_column_labels.extend(sub_cell.non_column_labels)
        self.values.extend(sub_cell.values)
  return FactoryClass


def CompositeColTableCell(columns_to_combine, cell_factories, config):
  """Cell factory that combines multiple cells in a combined column."""
  factory_col_list = []
  for sub_col in columns_to_combine:
    sub_factory = ChooseCellFactory(sub_col, cell_factories, config)
    factory_col_list.append((sub_factory, sub_col))
  return CompositeFactoryTableCell(factory_col_list)


@total_ordering
class CellItem(object):
  """Simple class to display one part of a table cell's value, with style."""

  def __init__(self, item, is_derived=False):
    self.item = item
    self.is_derived = ezt.boolean(is_derived)

  def __eq__(self, other):
    """A row is == if each cell is == to the item in the other row."""
    return other and self.item == other.item

  def __ne__(self, other):
    return not other and self.item != other.item

  def __lt__(self, other):
    return other and self.item < other.item

  def DebugString(self):
    if self.is_derived:
      return 'CI(derived: %r)' % self.item
    else:
      return 'CI(%r)' % self.item


class TableCellKeyLabels(TableCell):
  """TableCell subclass specifically for showing user-defined label values."""

  def __init__(self, _art, col=None, label_values=None,  **_kw):
    label_value_pairs = label_values.get(col, [])
    explicit_values = [value for value, is_derived in label_value_pairs
                       if not is_derived]
    derived_values = [value for value, is_derived in label_value_pairs
                      if is_derived]
    TableCell.__init__(self, CELL_TYPE_ATTR, explicit_values,
                       derived_values=derived_values)


class TableCellProject(TableCell):
  """TableCell subclass for showing an artifact's project name."""

  def __init__(self, art, **_kw):
    TableCell.__init__(
        self, CELL_TYPE_PROJECT, [art.project_name])


class TableCellStars(TableCell):
  """TableCell subclass for showing an artifact's star count."""

  def __init__(self, art, **_kw):
    TableCell.__init__(
        self, CELL_TYPE_ATTR, [art.star_count], align='right')


class TableCellSummary(TableCell):
  """TableCell subclass for showing an artifact's summary."""

  def __init__(self, art, non_col_labels=None, **_kw):
    TableCell.__init__(
        self, CELL_TYPE_SUMMARY, [art.summary],
        non_column_labels=non_col_labels)


class TableCellDate(TableCell):
  """TableCell subclass for showing any kind of date timestamp."""

  # Make instances of this class render with whitespace:nowrap.
  NOWRAP = ezt.boolean(True)

  def __init__(self, timestamp, days_only=False):
    values = []
    if timestamp:
      date_str = timestr.FormatRelativeDate(timestamp, days_only=days_only)
      if not date_str:
        date_str = timestr.FormatAbsoluteDate(timestamp)
      values = [date_str]

    TableCell.__init__(self, CELL_TYPE_UNFILTERABLE, values)


class TableCellCustom(TableCell):
  """Abstract TableCell subclass specifically for showing custom fields."""

  def __init__(self, art, col=None, users_by_id=None, config=None, **_kw):
    explicit_values = []
    derived_values = []
    cell_type = CELL_TYPE_ATTR
    phase_names_by_id = {
        phase.phase_id: phase.name.lower() for phase in art.phases}
    phase_name = None
    # Check if col represents a phase field value in the form <phase>.<field>
    if '.' in col:
      phase_name, col = col.split('.', 1)
    for fv in art.field_values:
      # TODO(jrobbins): for cross-project search this could be a list.
      fd = tracker_bizobj.FindFieldDefByID(fv.field_id, config)
      if not fd:
        # TODO(jrobbins): This can happen if an issue with a custom
        # field value is moved to a different project.
        logging.warning(
            'Issue ID %r has undefined field value %r', art.issue_id, fv)
      elif fd.field_name.lower() == col and (
          phase_names_by_id.get(fv.phase_id) == phase_name):
        if fd.field_type == tracker_pb2.FieldTypes.URL_TYPE:
          cell_type = CELL_TYPE_URL
        if fd.field_type == tracker_pb2.FieldTypes.STR_TYPE:
          self.NOWRAP = ezt.boolean(False)
        val = tracker_bizobj.GetFieldValue(fv, users_by_id)
        if fv.derived:
          derived_values.append(val)
        else:
          explicit_values.append(val)

    TableCell.__init__(self, cell_type, explicit_values,
                       derived_values=derived_values)

  def ExtractValue(self, fv, _users_by_id):
    return 'field-id-%d-not-implemented-yet' % fv.field_id

class TableCellApprovalStatus(TableCell):
  """Abstract TableCell subclass specifically for showing approval fields."""

  def __init__(self, art, col=None, config=None, **_kw):
    explicit_values = []
    for av in art.approval_values:
      fd = tracker_bizobj.FindFieldDef(col, config)
      ad = tracker_bizobj.FindApprovalDef(col, config)
      if not (ad and fd):
        logging.warning(
            'Issue ID %r has undefined field value %r', art.issue_id, av)
      elif av.approval_id == fd.field_id:
        explicit_values.append(av.status.name)
        break

    TableCell.__init__(self, CELL_TYPE_ATTR, explicit_values)


class TableCellApprovalApprover(TableCell):
  """TableCell subclass specifically for showing approval approvers."""

  def __init__(self, art, col=None, config=None, users_by_id=None, **_kw):
    explicit_values = []
    approval_name = col[:-len(tracker_constants.APPROVER_COL_SUFFIX)]
    for av in art.approval_values:
      fd = tracker_bizobj.FindFieldDef(approval_name, config)
      ad = tracker_bizobj.FindApprovalDef(approval_name, config)
      if not (ad and fd):
        logging.warning(
            'Issue ID %r has undefined field value %r', art.issue_id, av)
      elif av.approval_id == fd.field_id:
        explicit_values = [users_by_id.get(approver_id).display_name
                           for approver_id in av.approver_ids
                           if users_by_id.get(approver_id)]
        break

    TableCell.__init__(self, CELL_TYPE_ATTR, explicit_values)

def ChooseCellFactory(col, cell_factories, config):
  """Return the CellFactory to use for the given column."""
  if col in cell_factories:
    return cell_factories[col]

  if '/' in col:
    return CompositeColTableCell(col.split('/'), cell_factories, config)

  is_approver_col = False
  possible_field_name = col
  if col.endswith(tracker_constants.APPROVER_COL_SUFFIX):
    possible_field_name = col[:-len(tracker_constants.APPROVER_COL_SUFFIX)]
    is_approver_col = True
  # Check if col represents a phase field value in the form <phase>.<field>
  elif '.' in possible_field_name:
    possible_field_name = possible_field_name.split('.')[-1]

  fd = tracker_bizobj.FindFieldDef(possible_field_name, config)
  if fd:
    # We cannot assume that non-enum_type field defs do not share their
    # names with label prefixes. So we need to group them with
    # TableCellKeyLabels to make sure we catch appropriate labels values.
    if fd.field_type == tracker_pb2.FieldTypes.APPROVAL_TYPE:
      if is_approver_col:
        # Combined cell for 'FieldName-approver' to hold approvers
        # belonging to FieldName and values belonging to labels with
        # 'FieldName-approver' as the key.
        return CompositeFactoryTableCell(
          [(TableCellApprovalApprover, col), (TableCellKeyLabels, col)])
      return CompositeFactoryTableCell(
          [(TableCellApprovalStatus, col), (TableCellKeyLabels, col)])
    elif fd.field_type != tracker_pb2.FieldTypes.ENUM_TYPE:
      return CompositeFactoryTableCell(
          [(TableCellCustom, col), (TableCellKeyLabels, col)])

  return TableCellKeyLabels
