/**
 * @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 hasApprovedVote(labelInfo: LabelInfo) {
  if (isDetailedLabelInfo(labelInfo)) {
    return getAllUniqueApprovals(labelInfo).some(
      approval =>
        getLabelStatus(labelInfo, approval.value) === LabelStatus.APPROVED
    );
  } else if (isQuickLabelInfo(labelInfo)) {
    return getLabelStatus(labelInfo) === LabelStatus.APPROVED;
  } else {
    return false;
  }
}

export function hasRejectedVote(labelInfo: LabelInfo) {
  if (isDetailedLabelInfo(labelInfo)) {
    return getAllUniqueApprovals(labelInfo).some(
      approval =>
        getLabelStatus(labelInfo, approval.value) === LabelStatus.REJECTED
    );
  } else if (isQuickLabelInfo(labelInfo)) {
    return getLabelStatus(labelInfo) === LabelStatus.REJECTED;
  } else {
    return false;
  }
}

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;
}

export function extractLabelsWithCountFrom(expression: string) {
  const pattern = new RegExp(
    'label[0-9]*:([\\w-]+)[^,]*,count>?=?([0-9])',
    'g'
  );
  const labels = [];
  let match;
  while ((match = pattern.exec(expression)) !== null) {
    if (match[2] && !isNaN(Number(match[2]))) {
      labels.push({label: match[1], count: Number(match[2])});
    }
  }
  return labels;
}

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
  );
}

// Gerrit is overriding order for standard requirements on change view.
// Other requirements are ordered as defined in project configuration.
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);
}

export function orderSubmitRequirementNames(names: string[]) {
  const result = PRIORITY_REQUIREMENTS_ORDER.filter(label =>
    names.includes(label)
  );
  const nonPriorityRequirements = names
    .filter(name => !PRIORITY_REQUIREMENTS_ORDER.includes(name))
    .sort();
  return result.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$/)
  );
}
