/**
 * @license
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {
  ChangeInfo,
  isQuickLabelInfo,
  SubmitRequirementResultInfo,
  SubmitRequirementStatus,
  LabelNameToValuesMap,
} from '../api/rest-api';
import {FlagsService, KnownExperimentId} from '../services/flags/flags';
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}`);
  }
}

export function valueString(value?: number) {
  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;
}

export function canVote(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 function iconForStatus(status: SubmitRequirementStatus) {
  switch (status) {
    case SubmitRequirementStatus.SATISFIED:
      return 'check-circle-filled';
    case SubmitRequirementStatus.UNSATISFIED:
      return 'block';
    case SubmitRequirementStatus.OVERRIDDEN:
      return 'overridden';
    case SubmitRequirementStatus.NOT_APPLICABLE:
      return 'info';
    case SubmitRequirementStatus.ERROR:
      return 'error';
    case SubmitRequirementStatus.FORCED:
      return 'check-circle-filled';
    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 showNewSubmitRequirements(
  flagsService: FlagsService,
  change?: ParsedChangeInfo | ChangeInfo
) {
  const isSubmitRequirementsUiEnabled = flagsService.isEnabled(
    KnownExperimentId.SUBMIT_REQUIREMENTS_UI
  );
  if (!isSubmitRequirementsUiEnabled) return false;
  if ((getRequirements(change) ?? []).length === 0) return false;

  return true;
}
