/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  AccountDetailInfo,
  AccountInfo,
  BasePatchSetNum,
  ChangeMessage,
  Comment,
  CommentIdToCommentThreadMap,
  CommentInfo,
  CommentInput,
  CommentRange,
  CommentThread,
  ContextLine,
  DraftInfo,
  FixId,
  FixReplacementInfo,
  FixSuggestionInfo,
  isDraft,
  isNew,
  NewDraftInfo,
  PARENT,
  PatchRange,
  PatchSetNum,
  PatchSetNumber,
  RevisionPatchSetNum,
  SavingState,
  UrlEncodedCommentId,
  VotingRangeInfo,
} from '../types/common';
import {CommentSide, SpecialFilePath} from '../constants/constants';
import {parseDate} from './date-util';
import {specialFilePathCompare} from './path-list-util';
import {getParentIndex, isMergeParent} from './patch-set-util';
import {DiffInfo} from '../types/diff';
import {FormattedReviewerUpdateInfo} from '../types/types';
import {extractMentionedUsers} from './account-util';
import {assertIsDefined, uuid} from './common-util';
import {FILE} from '../api/diff';

export function isFormattedReviewerUpdate(
  message: ChangeMessage
): message is ChangeMessage & FormattedReviewerUpdateInfo {
  return message.type === 'REVIEWER_UPDATE';
}

export type LabelExtreme = {[labelName: string]: VotingRangeInfo};

export const NEWLINE_PATTERN = /\n/g;

export const PATCH_SET_PREFIX_PATTERN =
  /^(?:Uploaded\s*)?[Pp]atch [Ss]et \d+:\s*(.*)/;

/**
 * We need a way to uniquely identify drafts. That is easy for all drafts that
 * were already known to the backend at the time of change page load: They will
 * have an `id` that we can use.
 *
 * For newly created drafts we start by setting a `client_id`, so that we can
 * identify the draft even, if no `id` is available yet.
 *
 * If a comment with a `client_id` gets saved, then id gets an `id`, but we have
 * to keep using the `client_id`, because that is what the UI is already using,
 * e.g. in `repeat()` directives.
 */
export function id(comment: Comment): UrlEncodedCommentId {
  if (isDraft(comment)) {
    if (isNew(comment)) {
      assertIsDefined(comment.client_id);
      return comment.client_id;
    }
    if (comment.client_id) {
      return comment.client_id;
    }
  }
  assertIsDefined(comment.id);
  return comment.id;
}

export function sortComments<T extends Comment>(comments: T[]): T[] {
  return comments.slice(0).sort(compareComments);
}

/**
 * Sorts comments in this order by:
 * - file path
 * - patchset
 * - line/range
 * - created/updated timestamp
 * - id
 */
export function compareComments(c1: Comment, c2: Comment) {
  const path1 = c1.path ?? '';
  const path2 = c2.path ?? '';
  if (path1 !== path2) {
    return specialFilePathCompare(path1, path2);
  }

  const ps1 = typeof c1.patch_set === 'number' ? c1.patch_set : undefined;
  const ps2 = typeof c2.patch_set === 'number' ? c2.patch_set : undefined;
  const psComp = compareNumber(ps1, ps2);
  if (psComp !== 0) return psComp;

  const line1 = c1.line ?? c1?.range?.end_line;
  const line2 = c2.line ?? c2?.range?.end_line;
  const lineComp = compareNumber(line1, line2);
  if (lineComp !== 0) return lineComp;

  const startLine = compareNumber(c1.range?.start_line, c2.range?.start_line);
  if (startLine !== 0) return startLine;
  const endCharComp = compareNumber(
    c1.range?.end_character,
    c2.range?.end_character
  );
  if (endCharComp !== 0) return endCharComp;
  const startCharComp = compareNumber(
    c1.range?.start_character,
    c2.range?.start_character
  );
  if (startCharComp !== 0) return startCharComp;

  // At this point we know that the comment is about the exact same location:
  // Same file, same patchset, same range.

  // Drafts after published comments.
  if (isDraft(c1) !== isDraft(c2)) return isDraft(c1) ? 1 : -1;
  const draft = isDraft(c1);

  // For drafts we have to be careful that saving a draft multiple times does
  // not affect the sorting. So instead of `updated` we are inspecting the
  // creation time for newly created drafts in this session. Or alternatively
  // just use the comment id.
  if (draft) {
    const created1 = isNew(c1) ? c1.client_created_ms : undefined;
    const created2 = isNew(c2) ? c2.client_created_ms : undefined;
    const createdComp = compareNumber(created1, created2);
    if (createdComp !== 0) return createdComp;
  } else {
    const updated1 =
      c1.updated !== undefined ? parseDate(c1.updated).getTime() : undefined;
    const updated2 =
      c2.updated !== undefined ? parseDate(c2.updated).getTime() : undefined;
    const updatedComp = compareNumber(updated1, updated2);
    if (updatedComp !== 0) return updatedComp;
  }

  const id1 = id(c1);
  const id2 = id(c2);
  return id1.localeCompare(id2);
}

export function compareNumber(n1?: number, n2?: number): number {
  if (n1 === n2) return 0;
  if (n1 === undefined) return -1;
  if (n2 === undefined) return 1;
  if (Number.isNaN(n1)) return -1;
  if (Number.isNaN(n2)) return 1;
  return n1 < n2 ? -1 : 1;
}

export function createNew(
  message?: string,
  unresolved?: boolean
): NewDraftInfo {
  const newDraft: NewDraftInfo = {
    savingState: SavingState.OK,
    client_id: uuid() as UrlEncodedCommentId,
    client_created_ms: Date.now(),
    id: undefined,
    updated: undefined,
  };
  if (message !== undefined) newDraft.message = message;
  if (unresolved !== undefined) newDraft.unresolved = unresolved;
  return newDraft;
}

export function createNewPatchsetLevel(
  patchNum?: PatchSetNumber,
  message?: string,
  unresolved?: boolean
): DraftInfo {
  return {
    ...createNew(message, unresolved),
    patch_set: patchNum,
    path: SpecialFilePath.PATCHSET_LEVEL_COMMENTS,
  };
}

export function createNewReply(
  replyingTo: Pick<
    CommentInfo,
    'id' | 'path' | 'patch_set' | 'line' | 'range' | 'side' | 'parent'
  >,
  message: string,
  unresolved: boolean
): DraftInfo {
  return {
    ...createNew(message, unresolved),
    path: replyingTo.path,
    patch_set: replyingTo.patch_set,
    side: replyingTo.side,
    line: replyingTo.range ? replyingTo.range.end_line : replyingTo.line,
    range: replyingTo.range,
    parent: replyingTo.parent,
    in_reply_to: replyingTo.id,
  };
}

/**
 * Ensures that all comments that are replies have the same range as their
 * parent.
 * sortComments requires the location (range, line, side, parent) of all
 * comments in a thread to match. It's possible to create a reply via REST API
 * without the range, line, side, or parent being set, hence ensure these are
 * properly derived from the parent comment before forming threads.
 */
export function sanitiseRanges(comments: Comment[]) {
  const idToComment = new Map<string, Comment>();
  for (const comment of comments) {
    if (comment.id) {
      idToComment.set(comment.id, comment);
    }
  }

  const visited = new Set<Comment>();
  function inheritFromParent(comment: Comment) {
    if (visited.has(comment)) {
      return;
    }
    visited.add(comment);
    if (!comment.in_reply_to) {
      return;
    }
    const parent = idToComment.get(comment.in_reply_to);
    if (!parent) {
      return;
    }
    inheritFromParent(parent);
    if (parent.line !== undefined && comment.line === undefined) {
      comment.line = parent.line;
    }
    if (parent.range && !comment.range && comment.line === parent.line) {
      comment.range = {...parent.range};
    }
    if (parent.side !== undefined && comment.side === undefined) {
      comment.side = parent.side;
    }
    if (parent.parent !== undefined && comment.parent === undefined) {
      comment.parent = parent.parent;
    }
  }

  for (const comment of comments) {
    inheritFromParent(comment);
  }
}

export function createCommentThreads(comments: Comment[]) {
  sanitiseRanges(comments);
  const sortedComments = sortComments(comments);
  const threads: CommentThread[] = [];
  const idThreadMap: CommentIdToCommentThreadMap = {};
  for (const comment of sortedComments) {
    // thread and append to it.
    if (comment.in_reply_to) {
      const thread = idThreadMap[comment.in_reply_to];
      if (thread) {
        thread.comments.push(comment);
        if (id(comment)) idThreadMap[id(comment)] = thread;
        continue;
      }
    }

    // Otherwise, this comment starts its own thread.
    if (!comment.path) {
      throw new Error('Comment missing required "path".');
    }
    const newThread: CommentThread = {
      comments: [comment],
      patchNum: comment.patch_set,
      commentSide: comment.side ?? CommentSide.REVISION,
      mergeParentNum: comment.parent,
      path: comment.path,
      line: comment.line,
      range: comment.range,
      rootId: id(comment),
    };
    if (isFileLevelComment(comment)) {
      newThread.line = FILE;
    }
    threads.push(newThread);
    if (id(comment)) idThreadMap[id(comment)] = newThread;
  }
  return threads;
}

export function rangeId(r: CommentRange) {
  return `${r.start_line ?? 0}-${r.start_character ?? 0}-${r.end_line ?? 0}-${
    r.end_character ?? 0
  }`;
}

export function equalLocation(t1?: CommentThread, t2?: CommentThread) {
  if (t1 === t2) return true;
  if (t1 === undefined || t2 === undefined) return false;
  return (
    t1.path === t2.path &&
    t1.patchNum === t2.patchNum &&
    t1.commentSide === t2.commentSide &&
    t1.line === t2.line &&
    t1.range?.start_line === t2.range?.start_line &&
    t1.range?.start_character === t2.range?.start_character &&
    t1.range?.end_line === t2.range?.end_line &&
    t1.range?.end_character === t2.range?.end_character
  );
}

export function getLastComment(
  thread: CommentThread
): CommentInfo | DraftInfo | undefined {
  const len = thread.comments.length;
  return thread.comments[len - 1];
}

export function getLastPublishedComment(
  thread: CommentThread
): CommentInfo | DraftInfo | undefined {
  const publishedComments = thread.comments.filter(c => !isDraft(c));
  const len = publishedComments.length;
  return publishedComments[len - 1];
}

export function getFirstComment(
  thread: CommentThread
): CommentInfo | DraftInfo | undefined {
  return thread.comments[0];
}

export function countComments(thread: CommentThread) {
  return thread.comments.length;
}

export function isPatchsetLevel(thread: CommentThread): boolean {
  return thread.path === SpecialFilePath.PATCHSET_LEVEL_COMMENTS;
}

export function isUnresolved(thread: CommentThread): boolean {
  return !isResolved(thread);
}

export function isResolved(thread: CommentThread): boolean {
  const lastComment = getLastComment(thread);
  return lastComment !== undefined ? !lastComment.unresolved : true;
}

export function isDraftThread(thread: CommentThread): boolean {
  return isDraft(getLastComment(thread));
}

/**
 * Returns true, if the thread consists only of one comment that has not yet
 * been saved to the backend.
 */
export function isNewThread(thread: CommentThread): boolean {
  return isNew(getFirstComment(thread));
}

export function isMentionedThread(
  thread: CommentThread,
  account?: AccountInfo
) {
  if (!account?.email) return false;
  return getMentionedUsers(thread)
    .map(v => v.email)
    .includes(account.email);
}

export function hasSuggestion(thread: CommentThread): boolean {
  const firstComment = getFirstComment(thread);
  if (!firstComment) return false;
  return (
    hasUserSuggestion(firstComment) ||
    firstComment.fix_suggestions?.[0] !== undefined
  );
}

export function lastUpdated(thread: CommentThread): Date | undefined {
  // We don't want to re-sort comments when you save a draft reply, so
  // we stick to the timestampe of the last *published* comment.
  const lastUpdated =
    getLastPublishedComment(thread)?.updated ?? getLastComment(thread)?.updated;
  return lastUpdated !== undefined ? parseDate(lastUpdated) : undefined;
}
/**
 * Whether the given comment should be included in the base side of the
 * given patch range.
 */
export function isInBaseOfPatchRange(
  comment: {
    patch_set?: PatchSetNum;
    side?: CommentSide;
    parent?: number;
  },
  range: PatchRange
) {
  // If the base of the patch range is a parent of a merge, and the comment
  // appears on a specific parent then only show the comment if the parent
  // index of the comment matches that of the range.
  if (comment.parent && comment.side === CommentSide.PARENT) {
    return (
      isMergeParent(range.basePatchNum) &&
      comment.parent === getParentIndex(range.basePatchNum)
    );
  }

  // If the base of the range is the parent of the patch:
  if (
    range.basePatchNum === PARENT &&
    comment.side === CommentSide.PARENT &&
    comment.patch_set === range.patchNum
  ) {
    return true;
  }
  // If the base of the range is not the parent of the patch:
  return (
    range.basePatchNum !== PARENT &&
    comment.side !== CommentSide.PARENT &&
    comment.patch_set === range.basePatchNum
  );
}

/**
 * Whether the given comment should be included in the revision side of the
 * given patch range.
 */
export function isInRevisionOfPatchRange(
  comment: {
    patch_set?: PatchSetNum;
    side?: CommentSide;
  },
  range: PatchRange
) {
  return (
    comment.side !== CommentSide.PARENT && comment.patch_set === range.patchNum
  );
}

/**
 * Whether the given comment should be included in the given patch range.
 */
export function isInPatchRange(comment: Comment, range: PatchRange): boolean {
  return (
    isInBaseOfPatchRange(comment, range) ||
    isInRevisionOfPatchRange(comment, range)
  );
}

export function getPatchRangeForCommentUrl(
  comment: Comment,
  latestPatchNum: RevisionPatchSetNum
) {
  if (!comment.patch_set) throw new Error('Missing comment.patch_set');

  // TODO(dhruvsri): Add handling for comment left on parents of merge commits
  if (comment.side === CommentSide.PARENT) {
    return {
      patchNum: comment.patch_set,
      basePatchNum: PARENT,
    };
  } else if (latestPatchNum === comment.patch_set) {
    return {
      patchNum: latestPatchNum,
      basePatchNum: PARENT,
    };
  } else {
    return {
      patchNum: latestPatchNum,
      basePatchNum: comment.patch_set as BasePatchSetNum,
    };
  }
}

export function computeDiffFromContext(
  context: ContextLine[],
  path: string,
  content_type?: string
) {
  // do not render more than 20 lines of context
  context = context.slice(0, 20);
  const diff: DiffInfo = {
    meta_a: {
      name: '',
      content_type: '',
      lines: 0,
      web_links: [],
    },
    meta_b: {
      name: path,
      content_type: content_type || '',
      lines: context.length + context?.[0].line_number,
      web_links: [],
    },
    change_type: 'MODIFIED',
    intraline_status: 'OK',
    diff_header: [],
    content: [
      {
        skip: context[0].line_number - 1,
      },
      {
        b: context.map(line => line.context_line),
      },
    ],
  };
  return diff;
}

export function getCommentAuthors(
  threads?: CommentThread[],
  user?: AccountDetailInfo
) {
  if (!threads || !user) return [];
  const ids = new Set();
  const authors: AccountInfo[] = [];
  threads.forEach(t =>
    t.comments.forEach(c => {
      if (isDraft(c) && !ids.has(user._account_id)) {
        ids.add(user._account_id);
        authors.push(user);
        return;
      }
      if (c.author && !ids.has(c.author._account_id)) {
        ids.add(c.author._account_id);
        authors.push(c.author);
      }
    })
  );
  return authors;
}

/**
 * Add path info to every comment as CommentInfo returned from server does not
 * have that.
 */
export function addPath<T>(comments: {[path: string]: T[]} = {}): {
  [path: string]: Array<T & {path: string}>;
} {
  const updatedComments: {[path: string]: Array<T & {path: string}>} = {};
  for (const filePath of Object.keys(comments)) {
    updatedComments[filePath] = (comments[filePath] || []).map(comment => {
      return {...comment, path: filePath};
    });
  }
  return updatedComments;
}

/**
 * Add `savingState: SavingState.OK` to all drafts returned from server so that
 * they can be told apart from published comments easily.
 */
export function addDraftProp(
  draftsByPath: {[path: string]: CommentInfo[]} = {}
) {
  const updated: {[path: string]: DraftInfo[]} = {};
  for (const filePath of Object.keys(draftsByPath)) {
    updated[filePath] = (draftsByPath[filePath] ?? []).map(draft => {
      return {...draft, savingState: SavingState.OK};
    });
  }
  return updated;
}

export function reportingDetails(comment: Comment) {
  return {
    id: comment?.id,
    message_length: comment?.message?.trim().length,
    in_reply_to: comment?.in_reply_to,
    unresolved: comment?.unresolved,
    path_length: comment?.path?.length,
    line: comment?.range?.start_line ?? comment?.line,
    unsaved: isNew(comment),
  };
}

export const USER_SUGGESTION_INFO_STRING = 'suggestion';
export const USER_SUGGESTION_START_PATTERN = `\`\`\`${USER_SUGGESTION_INFO_STRING}\n`;

// This can either mean a user or a checks provided fix.
// "Provided" means that the fix is sent along with the request
// when previewing and applying the fix.
export const PROVIDED_FIX_ID = 'provided_fix' as FixId;

export function hasUserSuggestion(comment: Comment) {
  return comment.message?.includes(USER_SUGGESTION_START_PATTERN) ?? false;
}

export function getUserSuggestionFromString(
  content: string,
  suggestionIndex = 0
) {
  const suggestions = content.split(USER_SUGGESTION_START_PATTERN).slice(1);
  if (suggestions.length === 0) return '';

  const targetIndex = Math.min(suggestionIndex, suggestions.length - 1);
  const targetSuggestion = suggestions[targetIndex];
  const end = targetSuggestion.indexOf('\n```');
  return end !== -1 ? targetSuggestion.substring(0, end) : targetSuggestion;
}

export function getUserSuggestion(comment: Comment) {
  if (!comment.message) return;
  return getUserSuggestionFromString(comment.message);
}

export function getContentInCommentRange(
  fileContent: string,
  comment: Comment
) {
  if (comment.path === SpecialFilePath.COMMIT_MESSAGE) {
    // We need to add 6 lines, because commit message diff is
    // showing 6 lines of header that are not part of file content.
    fileContent = '\n'.repeat(6) + fileContent;
  }
  const lines = fileContent.split('\n');
  if (comment.range) {
    const range = comment.range;
    return lines.slice(range.start_line - 1, range.end_line).join('\n');
  }
  return lines[comment.line! - 1];
}

export function createUserFixSuggestion(
  comment: Comment,
  line: string,
  replacement: string
): FixSuggestionInfo[] {
  const lastLine = line.split('\n').pop();
  return [
    {
      fix_id: PROVIDED_FIX_ID,
      description: 'User suggestion',
      replacements: [
        {
          path: comment.path!,
          range: {
            start_line: comment.range?.start_line ?? comment.line!,
            start_character: 0,
            end_line: comment.range?.end_line ?? comment.line!,
            end_character: lastLine!.length,
          },
          replacement,
        },
      ],
    },
  ];
}

function getMentionedUsers(thread: CommentThread) {
  return thread.comments.map(c => extractMentionedUsers(c.message)).flat();
}

export function getMentionedThreads(
  threads: CommentThread[],
  account: AccountInfo
) {
  if (!account.email) return [];
  return threads.filter(t =>
    getMentionedUsers(t)
      .map(v => v.email)
      .includes(account.email)
  );
}

export function findComment(
  comments: {
    [path: string]: (CommentInfo | DraftInfo)[];
  },
  commentId: UrlEncodedCommentId
) {
  if (!commentId) return undefined;
  let comment;
  for (const path of Object.keys(comments)) {
    comment = comment || comments[path].find(c => c.id === commentId);
  }
  return comment;
}

export function convertToCommentInput(comment: Comment): CommentInput {
  const output: CommentInput = {
    message: comment.message,
    unresolved: comment.unresolved,
  };

  if (comment.id) {
    output.id = comment.id;
  }
  if (comment.path) {
    output.path = comment.path;
  }
  if (comment.side) {
    output.side = comment.side;
  }
  if (comment.line) {
    output.line = comment.line;
  }
  if (comment.range) {
    output.range = comment.range;
  }
  if (comment.in_reply_to) {
    output.in_reply_to = comment.in_reply_to;
  }
  if (comment.updated) {
    output.updated = comment.updated;
  }
  if (comment.tag) {
    output.tag = comment.tag;
  }
  if (comment.fix_suggestions) {
    output.fix_suggestions = comment.fix_suggestions;
  }
  return output;
}

export function computeDisplayLine(excludePath: {
  line?: number | string;
  range?: CommentRange;
  path?: string;
}) {
  if (excludePath.path === SpecialFilePath.PATCHSET_LEVEL_COMMENTS) return '';
  if (excludePath.line === FILE) return FILE;
  if (excludePath.line) return `#${excludePath.line}`;
  if (excludePath.range) {
    // If the range is wrong, we display the start line. Happens to AI generated comments.
    if (excludePath.range.end_line < excludePath.range.start_line)
      return `#${excludePath.range.start_line}`;
    return `#${excludePath.range.end_line}`;
  }
  return '';
}

export function isFileLevelComment(comment: Comment) {
  return !comment.line && !comment.range;
}

const START_REPLACEMENT_DELIMITER = '--- START REPLACEMENT';
const END_REPLACEMENT_DELIMITER = '--- END REPLACEMENT ---';

export function replacementsToString(
  replacements: FixReplacementInfo[]
): string {
  return replacements
    .map(r => {
      const range = `${r.range.start_line}-${r.range.end_line}`;
      return `${START_REPLACEMENT_DELIMITER} path=${r.path} range=${range}
${r.replacement}
${END_REPLACEMENT_DELIMITER}`;
    })
    .join('\n\n');
}

/**
 * Parses a string containing one or more replacement blocks into an array of
 * `FixReplacementInfo` objects.
 *
 * Each replacement block in the string is expected to be in the format:
 * --- START REPLACEMENT path=[file_path] range=[start_line]-[end_line]
 * [replacement_code]
 * --- END REPLACEMENT ---
 *
 * This function assumes `start_character` and `end_character` for the range
 * are always 0.
 *
 * @param text The raw string containing one or more replacement blocks.
 * @return An array of `FixReplacementInfo` objects.
 * @throws An error if the input string cannot be parsed into at least one
 *     replacement.
 *
 * @example
 * const text = `
 * --- START REPLACEMENT path=src/main.js range=10-12
 *   console.log("Hello, world!");
 * --- END REPLACEMENT ---
 * `;
 * const replacements = stringToReplacements(text);
 * // replacements would be:
 * // [
 * //   {
 * //     path: 'src/main.js',
 * //     range: { start_line: 10, end_line: 12, start_character: 0, end_character: 0 },
 * //     replacement: '  console.log("Hello, world!");'
 * //   }
 * // ]
 */
export function stringToReplacements(text: string): FixReplacementInfo[] {
  const regex =
    /--- START REPLACEMENT path=(.*?) range=(\d+)-(\d+)\n([\s\S]*?)\n--- END REPLACEMENT ---/g;
  const replacements: FixReplacementInfo[] = [];
  let match;
  while ((match = regex.exec(text)) !== null) {
    const path = match[1].trim();
    const start_line = Number(match[2]);
    const end_line = Number(match[3]);
    const replacement = match[4];
    replacements.push({
      path,
      range: {start_line, end_line, start_character: 0, end_character: 0},
      replacement,
    });
  }
  if (replacements.length === 0) {
    throw new Error('Could not parse replacements from text');
  }
  return replacements;
}
