/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {SpecialFilePath, FileInfoStatus} from '../constants/constants';
import {FileInfo} from '../types/common';
import {hasOwnProperty} from './common-util';

export function specialFilePathCompare(a: string, b: string) {
  // The commit message always goes first.
  if (a === SpecialFilePath.COMMIT_MESSAGE) {
    return -1;
  }
  if (b === SpecialFilePath.COMMIT_MESSAGE) {
    return 1;
  }

  // The merge list always comes next.
  if (a === SpecialFilePath.MERGE_LIST) {
    return -1;
  }
  if (b === SpecialFilePath.MERGE_LIST) {
    return 1;
  }

  const aLastDotIndex = a.lastIndexOf('.');
  const aExt = a.substr(aLastDotIndex + 1);
  const aFile = a.substr(0, aLastDotIndex) || a;

  const bLastDotIndex = b.lastIndexOf('.');
  const bExt = b.substr(bLastDotIndex + 1);
  const bFile = b.substr(0, bLastDotIndex) || b;

  // Sort header files above others with the same base name.
  const headerExts = ['h', 'hh', 'hxx', 'hpp'];
  if (aFile.length > 0 && aFile === bFile) {
    if (headerExts.includes(aExt) && headerExts.includes(bExt)) {
      return a.localeCompare(b);
    }
    if (headerExts.includes(aExt)) {
      return -1;
    }
    if (headerExts.includes(bExt)) {
      return 1;
    }
  }
  return aFile.localeCompare(bFile) || a.localeCompare(b);
}

export function shouldHideFile(file: string) {
  return file === SpecialFilePath.PATCHSET_LEVEL_COMMENTS;
}

// In case there are files with comments on them but they are unchanged, then
// we explicitly displays the file to render the comments with Unchanged status
export function addUnmodifiedFiles(
  files: {[filename: string]: FileInfo},
  commentedPaths: {[fileName: string]: boolean}
) {
  if (!commentedPaths) return;
  Object.keys(commentedPaths).forEach(commentedPath => {
    if (hasOwnProperty(files, commentedPath) || shouldHideFile(commentedPath)) {
      return;
    }

    // if file is Renamed but has comments, then do not show the entry for the
    // old file path name
    if (
      Object.values(files).some(
        file =>
          file.status === FileInfoStatus.RENAMED &&
          file.old_path === commentedPath
      )
    ) {
      return;
    }
    // TODO(TS): either change FileInfo to mark delta and size optional
    // or fill in 0 here
    files[commentedPath] = {
      status: FileInfoStatus.UNMODIFIED,
    } as FileInfo;
  });
}

export function computeDisplayPath(path?: string) {
  if (path === SpecialFilePath.COMMIT_MESSAGE) {
    return 'Commit message';
  } else if (path === SpecialFilePath.MERGE_LIST) {
    return 'Merge list';
  }
  return path ?? '';
}

export function isMagicPath(path?: string) {
  return (
    !!path &&
    (path === SpecialFilePath.COMMIT_MESSAGE ||
      path === SpecialFilePath.MERGE_LIST)
  );
}

export function computeTruncatedPath(path?: string) {
  return truncatePath(computeDisplayPath(path));
}

/**
 * Truncates URLs to display filename only
 * Example
 * // returns '.../text.html'
 * util.truncatePath.('dir/text.html');
 * Example
 * // returns 'text.html'
 * util.truncatePath.('text.html');
 *
 */
export function truncatePath(path: string, threshold = 1) {
  const pathPieces = path.split('/');

  if (pathPieces.length <= threshold) {
    return path;
  }

  const index = pathPieces.length - threshold;
  // Character is an ellipsis.
  return `\u2026/${pathPieces.slice(index).join('/')}`;
}
