/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  ChangeInfo,
  isQuickLabelInfo,
  SubmitRequirementResultInfo,
  SubmitRequirementStatus,
  LabelNameToValuesMap,
} from '../api/rest-api';
import {
  AccountInfo,
  ApprovalInfo,
  DetailedLabelInfo,
  isDetailedLabelInfo,
  LabelInfo,
  LabelNameToInfoMap,
  VotingRangeInfo,
} from '../types/common';
import {ParsedChangeInfo} from '../types/types';
import {assertNever, unique, hasOwnProperty} from './common-util';

export interface Label {
  name: string;
  value: string | null;
}

// Name of the standard Code-Review label.
export enum StandardLabels {
  CODE_REVIEW = 'Code-Review',
  CODE_OWNERS = 'Code Owners',
  PRESUBMIT_VERIFIED = 'Presubmit-Verified',
}

export enum LabelStatus {
  APPROVED = 'APPROVED',
  REJECTED = 'REJECTED',
  RECOMMENDED = 'RECOMMENDED',
  DISLIKED = 'DISLIKED',
  NEUTRAL = 'NEUTRAL',
}

export function getVotingRange(label?: LabelInfo): VotingRangeInfo | undefined {
  if (!label || !isDetailedLabelInfo(label) || !label.values) return undefined;
  const values = Object.keys(label.values).map(v => Number(v));
  values.sort((a, b) => a - b);
  if (!values.length) return undefined;
  return {min: values[0], max: values[values.length - 1]};
}

export function getVotingRangeOrDefault(label?: LabelInfo): VotingRangeInfo {
  const range = getVotingRange(label);
  return range ? range : {min: 0, max: 0};
}

/**
 * If we don't know the label config, then we still need some way to decide
 * which vote value is the most important one, so we apply the standard rule
 * of a Code-Review label, where -2 blocks. So the most negative vote is
 * regarded as representative, if its absolute value is greater than or equal
 * to the most positive vote.
 */
export function getRepresentativeValue(label?: DetailedLabelInfo): number {
  if (!label?.all) return 0;
  const allValues = label.all.map(approvalInfo => approvalInfo.value ?? 0);
  if (allValues.length === 0) return 0;
  const max = Math.max(...allValues);
  const min = Math.min(...allValues);
  return max > -min ? max : min;
}

export function getLabelStatus(label?: LabelInfo, vote?: number): LabelStatus {
  if (!label) return LabelStatus.NEUTRAL;
  if (isDetailedLabelInfo(label)) {
    const value = vote ?? getRepresentativeValue(label);
    const range = getVotingRangeOrDefault(label);
    if (value < 0) {
      return value === range.min ? LabelStatus.REJECTED : LabelStatus.DISLIKED;
    }
    if (value > 0) {
      return value === range.max
        ? LabelStatus.APPROVED
        : LabelStatus.RECOMMENDED;
    }
  } else if (isQuickLabelInfo(label)) {
    if (label.approved) return LabelStatus.APPROVED;
    if (label.rejected) return LabelStatus.REJECTED;
    if (label.disliked) return LabelStatus.DISLIKED;
    if (label.recommended) return LabelStatus.RECOMMENDED;
  }
  return LabelStatus.NEUTRAL;
}

export function hasNeutralStatus(
  label: DetailedLabelInfo,
  approvalInfo?: ApprovalInfo
) {
  if (approvalInfo?.value === undefined) return true;
  return getLabelStatus(label, approvalInfo.value) === LabelStatus.NEUTRAL;
}

export function classForLabelStatus(status: LabelStatus) {
  switch (status) {
    case LabelStatus.APPROVED:
      return 'max';
    case LabelStatus.RECOMMENDED:
      return 'positive';
    case LabelStatus.DISLIKED:
      return 'negative';
    case LabelStatus.REJECTED:
      return 'min';
    case LabelStatus.NEUTRAL:
      return 'neutral';
    default:
      assertNever(status, `Unsupported status: ${status}`);
  }
}

/**
 * Returns string representation of QuickLabelInfo value or ApprovalInfo value
 */
export function valueString(value?: number): string {
  if (!value) return ' 0';
  let s = `${value}`;
  if (value > 0) s = `+${s}`;
  return s;
}

export function getMaxAccounts(label?: LabelInfo): ApprovalInfo[] {
  if (!label || !isDetailedLabelInfo(label) || !label.all) return [];
  const votingRange = getVotingRangeOrDefault(label);
  return label.all.filter(account => account.value === votingRange.max);
}

export function getApprovalInfo(
  label: DetailedLabelInfo,
  account: AccountInfo
): ApprovalInfo | undefined {
  return label.all?.filter(x => x._account_id === account._account_id)[0];
}

export function hasVoted(label: LabelInfo, account: AccountInfo) {
  if (isDetailedLabelInfo(label)) {
    return !hasNeutralStatus(label, getApprovalInfo(label, account));
  } else if (isQuickLabelInfo(label)) {
    return (
      label.approved?._account_id === account._account_id ||
      label.rejected?._account_id === account._account_id
    );
  }
  return false;
}

// This method is checking labels.all from change detail,
// that shows only permitted voting for reviewers or CC.
// It doesn't have permitted votes for owner. You
// can see permitted labels for logged in user in change.permitted_labels
export function canReviewerVote(
  label: DetailedLabelInfo,
  account: AccountInfo
) {
  const approvalInfo = getApprovalInfo(label, account);
  if (!approvalInfo) return false;
  if (approvalInfo.permitted_voting_range) {
    return approvalInfo.permitted_voting_range.max > 0;
  }
  // If value present, user can vote on the label.
  return approvalInfo.value !== undefined;
}

export function getAllUniqueApprovals(labelInfo?: LabelInfo) {
  if (!labelInfo || !isDetailedLabelInfo(labelInfo)) return [];
  const uniqueApprovals = (labelInfo.all ?? [])
    .filter(
      (approvalInfo, index, array) =>
        index === array.findIndex(other => other.value === approvalInfo.value)
    )
    .sort((a, b) => -(a.value ?? 0) + (b.value ?? 0));
  return uniqueApprovals;
}

export function hasVotes(labelInfo: LabelInfo): boolean {
  if (isDetailedLabelInfo(labelInfo)) {
    return (labelInfo.all ?? []).some(
      approval => !hasNeutralStatus(labelInfo, approval)
    );
  }
  if (isQuickLabelInfo(labelInfo)) {
    return (
      !!labelInfo.rejected ||
      !!labelInfo.approved ||
      !!labelInfo.recommended ||
      !!labelInfo.disliked
    );
  }
  return false;
}

export function labelCompare(labelName1: string, labelName2: string) {
  if (
    labelName1 === StandardLabels.CODE_REVIEW &&
    labelName2 === StandardLabels.CODE_REVIEW
  )
    return 0;
  if (labelName1 === StandardLabels.CODE_REVIEW) return -1;
  if (labelName2 === StandardLabels.CODE_REVIEW) return 1;

  return labelName1.localeCompare(labelName2);
}

export function getCodeReviewLabel(
  labels: LabelNameToInfoMap
): LabelInfo | undefined {
  for (const label of Object.keys(labels)) {
    if (label === StandardLabels.CODE_REVIEW) {
      return labels[label];
    }
  }
  return;
}

function extractLabelsFrom(expression: string) {
  const pattern = new RegExp('label[0-9]*:([\\w-]+)', 'g');
  const labels = [];
  let match;
  while ((match = pattern.exec(expression)) !== null) {
    labels.push(match[1]);
  }
  return labels;
}

export function extractAssociatedLabels(
  requirement: SubmitRequirementResultInfo,
  type: 'all' | 'onlyOverride' | 'onlySubmittability' = 'all'
): string[] {
  let labels: string[] = [];
  if (requirement.submittability_expression_result && type !== 'onlyOverride') {
    labels = labels.concat(
      extractLabelsFrom(requirement.submittability_expression_result.expression)
    );
  }
  if (requirement.override_expression_result && type !== 'onlySubmittability') {
    labels = labels.concat(
      extractLabelsFrom(requirement.override_expression_result.expression)
    );
  }
  return labels.filter(unique);
}
export interface SubmitRequirementsIcon {
  // The material icon name.
  icon: string;
  // Whether the gr-icon need to be filled.
  filled?: boolean;
}

export function iconForRequirement(
  requirement: SubmitRequirementResultInfo
): SubmitRequirementsIcon {
  if (isBlockingCondition(requirement)) {
    return {icon: 'cancel', filled: true};
  }
  return iconForStatus(requirement.status);
}

export function iconForStatus(
  status: SubmitRequirementStatus
): SubmitRequirementsIcon {
  switch (status) {
    case SubmitRequirementStatus.SATISFIED:
      return {icon: 'check_circle', filled: true};
    case SubmitRequirementStatus.UNSATISFIED:
      return {icon: 'block'};
    case SubmitRequirementStatus.OVERRIDDEN:
      return {icon: 'published_with_changes'};
    case SubmitRequirementStatus.NOT_APPLICABLE:
      return {icon: 'info', filled: true};
    case SubmitRequirementStatus.ERROR:
      return {icon: 'error', filled: true};
    case SubmitRequirementStatus.FORCED:
      return {icon: 'check_circle', filled: true};
    default:
      assertNever(status, `Unsupported status: ${status}`);
  }
}

/**
 * Show only applicable.
 */
export function getRequirements(change?: ParsedChangeInfo | ChangeInfo) {
  return (change?.submit_requirements ?? []).filter(
    req => req.status !== SubmitRequirementStatus.NOT_APPLICABLE
  );
}

// TODO(milutin): This may be temporary for demo purposes
export const PRIORITY_REQUIREMENTS_ORDER: string[] = [
  StandardLabels.CODE_REVIEW,
  StandardLabels.CODE_OWNERS,
  StandardLabels.PRESUBMIT_VERIFIED,
];
export function orderSubmitRequirements(
  requirements: SubmitRequirementResultInfo[]
) {
  let priorityRequirementList: SubmitRequirementResultInfo[] = [];
  for (const label of PRIORITY_REQUIREMENTS_ORDER) {
    const priorityRequirement = requirements.filter(r => r.name === label);
    priorityRequirementList =
      priorityRequirementList.concat(priorityRequirement);
  }
  const nonPriorityRequirements = requirements.filter(
    r => !PRIORITY_REQUIREMENTS_ORDER.includes(r.name)
  );
  return priorityRequirementList.concat(nonPriorityRequirements);
}

function getStringLabelValue(
  labels: LabelNameToInfoMap,
  labelName: string,
  numberValue?: number
): string {
  const detailedInfo = labels[labelName] as DetailedLabelInfo;
  if (detailedInfo.values) {
    for (const labelValue of Object.keys(detailedInfo.values)) {
      if (Number(labelValue) === numberValue) {
        return labelValue;
      }
    }
  }
  // TODO: This code is sometimes executed with numberValue taking the
  // values 0 and undefined.
  // For now it is unclear how this is happening, ideally this code should
  // never be executed.
  return `${numberValue}`;
}

export function getDefaultValue(
  labels?: LabelNameToInfoMap,
  labelName?: string
) {
  if (!labelName || !labels?.[labelName]) return undefined;
  const labelInfo = labels[labelName] as DetailedLabelInfo;
  return labelInfo.default_value;
}

export function getVoteForAccount(
  labelName: string,
  account?: AccountInfo,
  change?: ParsedChangeInfo | ChangeInfo
): string | null {
  const labels = change?.labels;
  if (!account || !labels) return null;
  const votes = labels[labelName] as DetailedLabelInfo;
  if (!votes.all?.length) return null;
  for (let i = 0; i < votes.all.length; i++) {
    if (votes.all[i]._account_id === account._account_id) {
      return getStringLabelValue(labels, labelName, votes.all[i].value);
    }
  }
  return null;
}

export function computeOrderedLabelValues(
  permittedLabels?: LabelNameToValuesMap
) {
  if (!permittedLabels) return [];
  const labels = Object.keys(permittedLabels);
  const values: Set<number> = new Set();
  for (const label of labels) {
    for (const value of permittedLabels[label]) {
      values.add(Number(value));
    }
  }

  return Array.from(values.values()).sort((a, b) => a - b);
}

export function mergeLabelInfoMaps(
  a?: LabelNameToInfoMap,
  b?: LabelNameToInfoMap
): LabelNameToInfoMap {
  if (!a || !b) return {};
  const mergedMap: LabelNameToInfoMap = {};
  for (const key of Object.keys(a)) {
    if (!hasOwnProperty(b, key)) continue;
    mergedMap[key] = a[key];
  }
  return mergedMap;
}

export function mergeLabelMaps(
  a?: LabelNameToValuesMap,
  b?: LabelNameToValuesMap
): LabelNameToValuesMap {
  if (!a || !b) return {};
  const mergedMap: LabelNameToValuesMap = {};
  for (const key of Object.keys(a)) {
    if (!hasOwnProperty(b, key)) continue;
    mergedMap[key] = mergeLabelValues(a[key], b[key]);
  }
  return mergedMap;
}

export function mergeLabelValues(a: string[], b: string[]) {
  return a.filter(value => b.includes(value));
}

export function computeLabels(
  account?: AccountInfo,
  change?: ParsedChangeInfo | ChangeInfo
): Label[] {
  if (!account) return [];
  const labelsObj = change?.labels;
  if (!labelsObj) return [];
  return Object.keys(labelsObj)
    .sort(labelCompare)
    .map(key => {
      return {
        name: key,
        value: getVoteForAccount(key, account, change),
      };
    });
}

export function getTriggerVotes(change?: ParsedChangeInfo | ChangeInfo) {
  const allLabels = Object.keys(change?.labels ?? {});
  // Normally there is utility method getRequirements, which filter out
  // not_applicable requirements. In this case we don't want to filter out them,
  // because trigger votes are labels not associated with any requirement.
  const submitReqs = change?.submit_requirements ?? [];
  const labelAssociatedWithSubmitReqs = submitReqs
    .flatMap(req => extractAssociatedLabels(req))
    .filter(unique);
  return allLabels.filter(
    label => !labelAssociatedWithSubmitReqs.includes(label)
  );
}

export function getApplicableLabels(change?: ParsedChangeInfo | ChangeInfo) {
  const submitReqs = change?.submit_requirements ?? [];
  const notApplicableLabels = submitReqs
    .filter(sr => sr.status === SubmitRequirementStatus.NOT_APPLICABLE)
    .flatMap(req => extractAssociatedLabels(req))
    .filter(unique);

  const applicableLabels = submitReqs
    .filter(sr => sr.status !== SubmitRequirementStatus.NOT_APPLICABLE)
    .flatMap(req => extractAssociatedLabels(req))
    .filter(unique);

  const onlyInNotApplicableLabels = notApplicableLabels.filter(
    label => !applicableLabels.includes(label)
  );

  return applicableLabels.filter(
    label => !onlyInNotApplicableLabels.includes(label)
  );
}

export function isBlockingCondition(
  requirement: SubmitRequirementResultInfo
): boolean {
  if (requirement.status !== SubmitRequirementStatus.UNSATISFIED) return false;

  return !!requirement.submittability_expression_result.passing_atoms?.some(
    atom => atom.match(/^label[0-9]*:[\w-]+=MIN$/)
  );
}
