// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {PluginApi} from '@gerritcodereview/typescript-api/plugin';
import {
  Action,
  Category,
  ChangeData,
  CheckResult,
  CheckRun,
  FetchResponse,
  LinkIcon,
  ResponseCode,
  RunStatus,
} from '@gerritcodereview/typescript-api/checks';
import {
  ChangeInfo,
  ChangeStatus,
  RevisionInfo,
  RevisionKind,
} from '@gerritcodereview/typescript-api/rest-api';
import {DATA_SYMBOL} from './checks-result.js';
import {
  Build,
  BuildbucketV2Client,
  ScheduleBuildRequest,
  SearchBuildsRequest,
} from './buildbucket-client.js';

// TODO(gavinmak): Fix linter issues.

export declare interface ChromiumBinarySizeConfig {
  tryBuilder: string;
  tryBucket: string;
  tryProject: string;
  gerritHost: string;
}

export declare interface ChromiumBinarySizeInfo {
  loaded: boolean;
  listings: ChromiumBinarySizeListing[];
  extras: ChromiumBinarySizeExtra[];
}

declare interface ChromiumBinarySizeExtra {
  url: string;
  text: string;
}

export declare interface ChromiumBinarySizeListing {
  name: string;
  delta: string;
  limit: string;
  log_name: string;
  allowed: boolean;
  large_improvement: string;

  url?: string;
  css_class?: string;
}

declare interface PatchPredicate {
  host: string;
  change: number;
  patchset: number;
}

export class ChecksFetcher {
  public pluginConfig: ChromiumBinarySizeConfig = {
    tryBuilder: '',
    tryBucket: '',
    tryProject: '',
    gerritHost: '',
  };

  private enabledCache: Map<string, ChromiumBinarySizeConfig> = new Map();

  constructor(public plugin: PluginApi, private buildbucketHost: string) {}

  async isEnabled(project: string): Promise<boolean> {
    const path =
      `/projects/${encodeURIComponent(project)}/` +
      `${encodeURIComponent(this.plugin.getPluginName())}~config`;
    if (!this.enabledCache.has(path)) {
      let config = {} as ChromiumBinarySizeConfig;
      try {
        config = await this.plugin.restApi().get(path);
      } catch (e) {
        console.log(
          `The chromium-binary-size plugin is not enabled on ${project}`
        );
      }
      this.enabledCache.set(path, config);
    }
    this.pluginConfig = this.enabledCache.get(path)!;
    return Object.keys(this.pluginConfig).length > 0;
  }

  /**
   * Compares build IDs by creation time.
   *
   * Build IDs are monotonically decreasing.
   *
   * A Buildbucket build ID is a positive int64. This is too large for
   * JavaScript numbers; we cannot just parse them as integers, so we
   * keep them as strings.
   *
   * @return Negative if `a` should go before `b`,
   *     0 if they're equal, and positive if `a` should go after `b`.
   */
  compareBuildIds(a: string, b: string): number {
    const d = b.length - a.length;
    if (d != 0) {
      return d;
    }
    if (a > b) {
      return -1;
    }
    if (a < b) {
      return 1;
    }
    return 0;
  }

  /**
   * Returns a CheckRun and CheckResult which contain binary size information.
   *
   * For more information on the Checks API:
   *   https://gerrit.googlesource.com/gerrit/+/refs/heads/master/polygerrit-ui/app/api/checks.ts
   */
  async fetchChecks(changeData: ChangeData): Promise<FetchResponse> {
    const {changeNumber, patchsetNumber, repo, changeInfo} = changeData;
    // When switching between changes on different repos, Checks can display
    // Chromium Binary Size Checks results on repos that don't have the plugin
    // enabled. This double-checks that a change has the plugin enabled.
    if (!(await this.isEnabled(repo))) {
      return {responseCode: ResponseCode.OK};
    }

    const patchsets = this.computeValidPatchNums(changeInfo, patchsetNumber);
    const builds =
      (await this.tryGetNewBinarySizeBuilds(changeInfo, patchsets)) || [];
    builds.sort((a, b) => -this.compareBuildIds(a.id, b.id));
    const binarySizeInfo = this.processBinarySizeBuilds(builds) || {};
    const {
      extras = [],
      listings = [],
      build = builds[0] || {},
    } = binarySizeInfo;

    const runId = `//${this.buildbucketHost}/chromium-binary-size-plugin`;
    const resultId = `${runId}/result`;
    const category = this.getCheckResultCategory(build, listings);
    const results: CheckResult[] = [];
    let delta_summary = '(unknown)';
    // Create a CheckResult from binarySizeInfo if possible. Otherwise, create
    // one based on builder status if applicable.
    if (binarySizeInfo?.loaded && (listings.length || extras.length)) {
      const links = extras.map((e: ChromiumBinarySizeExtra) => {
        const isApkBreakdown = e.text === 'APK Breakdown';
        return {
          url: e.url,
          tooltip: e.text,
          primary: isApkBreakdown,
          icon: isApkBreakdown ? LinkIcon.FILE_PRESENT : LinkIcon.EXTERNAL,
        };
      });

      // Build summary and message based off listings.
      //
      //   Passing example:
      //     Summary: Android Binary Size changed by +10 bytes. All checks passed.
      //     Message: Expand to view more.
      //
      //   Failing example:
      //     Summary: Android Binary Size changed by +18,954 bytes. 2 of 3 checks failed.
      //     Message: Failing checks: foo, bar. Expand to view more.
      let summary = '';
      let message = '';
      const unallowed = [];
      for (const l of listings) {
        if (l.name === 'Android Binary Size') {
          summary = `Android Binary Size changed by ${l.delta}. `;
          delta_summary = this.getHumanReadableDelta(l.delta);
        }
        if (!l.allowed) {
          unallowed.push(l.name);
        }
      }

      if (unallowed.length > 0) {
        summary += `${unallowed.length} of ${listings.length} checks failed.`;
        message += `Failing checks: ${unallowed.join(', ')}. `;
      } else {
        summary += 'All checks passed.';
      }
      message += 'Expand to view more.';

      results.push({
        externalId: resultId,
        category,
        summary,
        message,
        links,
        [DATA_SYMBOL]: {listings},
      } as CheckResult);
    } else if (['SCHEDULED', 'STARTED', 'CANCELED'].includes(build.status)) {
      let summary = '';
      const builder = this.pluginConfig.tryBuilder;
      if (build.status === 'CANCELED') {
        summary =
          `Run the ${builder} trybot on the latest patchset to see ` +
          'your binary size impact.';
      } else if (build.status === 'SCHEDULED') {
        summary = `Scheduling the ${builder} tryjob.`;
      } else if (build.status === 'STARTED') {
        summary = `Waiting for ${builder} trybot run to complete.`;
      }
      delta_summary = '(pending)';

      results.push({
        externalId: resultId,
        category,
        summary,
        [DATA_SYMBOL]: {listings},
      } as CheckResult);
    }

    if (build?.status && ['FAILED', 'INFRA_FAILED'].includes(build.status)) {
      delta_summary = '(failed)';
    }

    const actions: Action[] = [];
    if (!build?.status || build.status === 'CANCELED') {
      actions.push({
        name: 'Run',
        tooltip:
          `Start a new ${this.pluginConfig.tryBuilder} run on the ` +
          'latest patchset.',
        primary: true,
        callback: async () => {
          // TODO(gavinmak): Fix error handling.
          await this.scheduleBuild(
            changeNumber,
            Object.keys(changeInfo.revisions || {}).length,
            repo
          );
          return {shouldReload: true};
        },
      });
    }

    return {
      responseCode: ResponseCode.OK,
      runs: [
        {
          change: changeNumber,
          patchset: patchsetNumber,
          attempt: builds.length || undefined,
          externalId: runId,
          checkName: 'APK Size ' + delta_summary,
          checkDescription:
            'This run shows how your change and patchset ' +
            'affect the normalized APK size and other checks',
          checkLink:
            'https://chromium.googlesource.com/chromium/src/+/HEAD/' +
            'docs/speed/binary_size/android_binary_size_trybot.md',
          status: this.getCheckRunStatus(build),
          statusDescription: this.getCheckRunStatusDesc(build),
          results,
          actions,
        } as CheckRun,
      ],
    };
  }

  /**
   * Returns a short string with the binary size delta.
   */
  getHumanReadableDelta(delta_string: string | null): string {
    if (delta_string == null) {
      return '(unknown)';
    } else {
      // The delta gets sent to us as a string, we need to parse the number.
      const delta = parseInt(
        delta_string.replace('bytes', '').replace(/,/g, '')
      );
      const abs_delta = Math.abs(delta);
      const maybePlus = delta > 0 ? '+' : '';
      const fmtr = Intl.NumberFormat('en-US', { maximumFractionDigits: 1});
      if (abs_delta < 1024) {
        return '(' + maybePlus + delta + ' B)';
      } else if (abs_delta < 1024 * 1024) {
        return '(' + maybePlus + fmtr.format(delta / 1024) + ' KiB)';
      } else {
        return '(' + maybePlus + fmtr.format(delta / (1024 * 1024)) + ' MiB)';
      }
    }
  }

  /**
   * Returns the CheckRun status based on the build.
   */
  getCheckRunStatus(build: Build): RunStatus {
    switch (build?.status) {
      case undefined:
        return RunStatus.RUNNABLE;
      case 'SCHEDULED':
        // TODO(gavinmak): Replace with RunStatus.SCHEDULED once
        //   @gerritcodereview/typescript-api is updated.
        return 'SCHEDULED' as RunStatus;
      case 'STARTED':
        return RunStatus.RUNNING;
      default:
        return RunStatus.COMPLETED;
    }
  }

  /**
   * Returns the CheckRun statusDescription based on the build.
   */
  getCheckRunStatusDesc(build: Build): string {
    const builder = this.pluginConfig.tryBuilder;
    if (!build?.status) {
      return `Run the ${builder} trybot`;
    }
    if (build.status === 'SCHEDULED') {
      return `Scheduling the ${builder} tryjob`;
    }
    if (build.status === 'STARTED') {
      return `Waiting for the ${builder} trybot run to complete`;
    }
    return '';
  }

  /**
   * Returns the CheckResult category based on the build and listings.
   */
  getCheckResultCategory(
    build: Build,
    listings: ChromiumBinarySizeListing[]
  ): Category {
    if (listings?.every(l => l.allowed)) {
      return Category.INFO;
    }
    if (build?.status === 'SUCCESS') {
      return Category.WARNING;
    }
    return Category.ERROR;
  }

  /**
   * Post process binary size info json so as to help the template display
   * code.
   */
  private processBinarySizeBuilds(builds: Build[]) {
    const build = this.selectRelevantBuild(builds);
    if (!build) {
      return null;
    }

    const binarySizeInfo = {
      build,
      loaded: true,
      ...(build.output as any)?.properties?.binary_size_plugin,
    };

    for (const listing of binarySizeInfo.listings) {
      if (!listing['allowed']) {
        listing.css_class = 'red';
      } else if (listing['large_improvement']) {
        listing.css_class = 'green';
      }
    }
    return binarySizeInfo;
  }

  /**
   * Fetch builds from Buildbucket and return information about binary size,
   * or null in case of failure.
   */
  private async tryGetNewBinarySizeBuilds(
    change: ChangeInfo,
    patchsets: number[]
  ): Promise<Build[] | null> {
    try {
      return await this.getBuilds(
        this.tryjobPatchPredicates(change, patchsets)
      );
    } catch (e) {
      console.warn('Buildbucket search failed', e);
      return null;
    }
  }

  /**
   * Return the Buildbucket search predicates corresponding to the provided
   * patchset numbers.
   */
  tryjobPatchPredicates(
    change: ChangeInfo,
    validPatchNums: number[]
  ): PatchPredicate[] {
    return validPatchNums.map((patchNum: number) => {
      return {
        host: this.pluginConfig.gerritHost,
        change: change._number,
        patchset: patchNum,
      };
    });
  }

  /**
   * Get builds for the |bucket| that match any of the |patchPredictates|.
   */
  async getBuilds(patchPredicates: PatchPredicate[]): Promise<Build[]> {
    if (!patchPredicates?.length) {
      return [];
    }

    const bb = new BuildbucketV2Client(
      this.buildbucketHost,
      String(patchPredicates[0].change)
    );
    const fields = [
      'id',
      'status',
      'startTime',
      'endTime',
      'output.properties.fields.binarySizePlugin',
    ]
      .map(f => `builds.*.${f}`)
      .join(',');

    const searchResponses = await Promise.all(
      patchPredicates.map(patchPredicate =>
        bb.searchBuilds({
          predicate: {
            gerritChanges: [patchPredicate],
            builder: {
              builder: this.pluginConfig.tryBuilder,
              bucket: this.pluginConfig.tryBucket,
              project: this.pluginConfig.tryProject,
            },
          },
          fields,
        } as unknown as SearchBuildsRequest)
      )
    );
    const builds = searchResponses
      .map(response => response.builds)
      .filter(Boolean); // filter out undefineds

    // Concatenate builds in all responses. Assume that the builds in the
    // response for each tag entry in tags are mutually exclusive, because
    // each predicate represents one patchset of the CL.
    return Array.prototype.concat.apply([], builds);
  }

  /**
   * Return the latest build that has finished and has the properties needed
   * to display binary size information, or null.
   */
  selectRelevantBuild(builds: Build[]) {
    return (
      builds.find(
        build =>
          build.endTime && (build.output as any)?.properties?.binary_size_plugin
      ) || null
    );
  }

  /**
   * List numbers of patchsets (revisions) that are applicable.
   *
   * The reason why this is not just the current patchset number is because
   * there may have been a succession of 'trivial' changes before the current
   * patchset.
   *
   * @param change A Gerrit ChangeInfo object.
   * @param patchNum Revision number of currently displayed patch.
   * @return Revision numbers for the displayed builds.
   */
  computeValidPatchNums(change: ChangeInfo, patchNum: number): number[] {
    if (!change || !patchNum) {
      return [];
    }
    const validKinds = [
      RevisionKind.TRIVIAL_REBASE,
      RevisionKind.NO_CHANGE,
      RevisionKind.NO_CODE_CHANGE,
    ];
    const revisions: RevisionInfo[] = [];
    for (const revision in change.revisions) {
      if (change.revisions.hasOwnProperty(revision)) {
        revisions.push(change.revisions[revision]);
      }
    }
    revisions.sort(
      (a, b) =>
        // Reverse sort.
        (b._number as number) - (a._number as number)
    );
    const patchNums: number[] = [];
    for (let i = 0; i < revisions.length; i++) {
      if (i === 0 && change.status === ChangeStatus.MERGED) {
        // Skip past the most recent patch on submitted CLs because the last
        // patchset is always the autogenerated one, which may or may not
        // count as a trivial change depending on the submit strategy.
        continue;
      }
      if ((revisions[i]._number as number) > patchNum) {
        // Patches after the one we're displaying don't count.
        continue;
      }
      patchNums.push(revisions[i]._number as number);
      if (validKinds.indexOf(revisions[i].kind) === -1) {
        // If this revision was a non-trivial change,
        // don't consider patchsets prior to it.
        break;
      }
    }
    return patchNums;
  }

  private async scheduleBuild(
    change: number,
    patchset: number,
    project: string
  ) {
    try {
      const bb = new BuildbucketV2Client(this.buildbucketHost, String(change));

      await bb.scheduleBuild({
        builder: {
          builder: this.pluginConfig.tryBuilder,
          bucket: this.pluginConfig.tryBucket,
          project: this.pluginConfig.tryProject,
        },
        gerritChanges: [
          {
            host: this.pluginConfig.gerritHost,
            change,
            project,
            patchset,
          },
        ],
      } as unknown as ScheduleBuildRequest);
    } catch (err) {
      console.warn('Buildbucket scheduleBuild failed', err);
    }
  }
}
