// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file contains javascript which gets deployed to scripts.google.com, in
// order to power custom logic for the internal RFC tracker.

const TITLE_COL = 'Title';
const CL_COL = 'CL';
const CHANGE_ID_COL = 'Change Id';
const AUTHORS_COL = 'Author(s)';
const SUBMITTED_COL = 'Submitted';
const STATUS_COL = 'Status';
const NEEDS_SYNC_COL = 'Needs Sync';
const CL_UPDATED_COL = 'CL Updated';

const WIP_STATUS = 'Socialization';
const DEFAULT_STATUS = 'Draft';
const ABANDONED_STATUS = 'Withdrawn';

const RFCS_DIR = 'docs/contribute/governance/rfcs';
const SUBJECT_TAG = '[rfc]';

// Run _fetchRfcs() on the main 'prod' tracker.
function fetchRfcs() {
  _fetchRfcs('bbfvcDiuyZ08S5ZJ7vN4ZI');
}

// Run _fetchRfcs() on a test copy of the tracker.
function fetchRfcsTest() {
  // Put your personal test Table's ID here:
  _fetchRfcs('');
}

// Gets the list of open RFC CLs from gerrit and compares that to the set of
// RFCs in the tracker. For any CLs missing from the tracker, creates stub rows
// with just the change_id filled in.
function _fetchRfcs(tableId) {
  const gerritCls = _fetchOpenRfcsCls();
  const trackerCls = _getExistingRfcs(tableId);

  // Accumulate create requests so that requests can be batched.
  let createRows = [];
  for (const changeId of gerritCls) {
    if (!(changeId in trackerCls)) {
      createRows.push({
        row: {
          values: {
            [CHANGE_ID_COL]: changeId,
          }
        }
      });
    }
  }

  if (createRows.length != 0) {
    Area120Tables.Tables.Rows.batchCreate({ requests: createRows }, `tables/${tableId}`);
  }
}

// Returns an Array of change_ids.
function _fetchOpenRfcsCls() {
  const data = parseGerritResponse(UrlFetchApp.fetch(
    GERRIT_API_URL + '/changes/?q='
    + 'dir:' + encodeURIComponent(RFCS_DIR)
    + '+is:open'
    + '&n=100'));

  const changeIds = [];

  for (const cl of data) {
    if (cl.subject.toLowerCase().startsWith(SUBJECT_TAG)) {
      changeIds.push(cl.change_id);
    }
  }

  return changeIds;
}

// Returns {[change_id]: {name: 'row_name'}, ...}
function _getExistingRfcs(tableId) {
  // In order to limit total response sizes,
  // https://developers.google.com/apps-script/advanced/tables?hl=en#read_rows_of_a_table has clients
  // read through the rows in units of pages, which we do here so that this script won't fail when
  // there are more than N RFCs
  const PAGE_SIZE = 1000;
  let response = Area120Tables.Tables.Rows.list(`tables/${tableId}`, { page_size: PAGE_SIZE });
  let rfcs = {};
  while (response && 'rows' in response) {
    let rows = response.rows;
    // Add existing RFCs to the object
    for (let i = 0; i < rows.length; i++) {
      let change_id = rows[i].values[CHANGE_ID_COL];
      if (change_id == null) {
        continue;
      }
      rfcs[change_id] = { name: rows[i].name };
    }
    // Read next page of rows
    let pageToken = response.nextPageToken;
    if (!pageToken) {
      response = undefined;
    } else {
      response = Area120Tables.Tables.Rows.list(`tables/${tableId}`, { page_size: PAGE_SIZE, page_token: pageToken });
    }
  }
  return rfcs;
}

// Apply any programmatic updates we might want to make to the given row.
// Specifically, fetch the latest state from gerrit and update the row to
// match.
function syncRow(tableId, rowId) {
  const rowName = `tables/${tableId}/rows/${rowId}`;
  const row = Area120Tables.Tables.Rows.get(rowName);

  console.log('Row before: ', row);

  const changeId = row.values[CHANGE_ID_COL];

  const cl = parseGerritResponse(UrlFetchApp.fetch(
    // include _account_id, email and username fields when referencing accounts.
    GERRIT_API_URL + `/changes/${changeId}?o=DETAILED_ACCOUNTS`
  ));

  // Remove subject prefix tags (e.g. '[rfc][docs]')
  const title = cl.subject.replace(/^(\S+]\s)/i, '');

  const patchedValues = {
    [TITLE_COL]: title,
    [CL_COL]: `fxrev.dev/${cl._number}`,
    [AUTHORS_COL]: cl.owner.email,
    [SUBMITTED_COL]: cl.created,
    [CL_UPDATED_COL]: cl.updated,

    [NEEDS_SYNC_COL]: false,
  };

  if (cl.work_in_progress) {
    if (!row.values[STATUS_COL]) {
      patchedValues[STATUS_COL] = WIP_STATUS;
    }
  } else {
    if (!row.values[STATUS_COL] || row.values[STATUS_COL] === WIP_STATUS) {
      patchedValues[STATUS_COL] = DEFAULT_STATUS;
    }
  }

  // Abandoning the CL amounts to withdrawing the RFC.
  if (cl.status === 'ABANDONED') {
    patchedValues[STATUS_COL] = ABANDONED_STATUS;
  }

  Area120Tables.Tables.Rows.patch({ values: patchedValues }, rowName);
}

// Returns {[change_id]: true, ...}
function _getExistingRfcsFromAppSheet() {
  const rows = callAppSheetAPI({
    "Action": "Find",
    "Properties": {},
  });

  const res = {};
  for (const row of rows) {
    res[row['Change ID']] = true;
  }

  return res;
}

// Gets the list of open RFC CLs from gerrit and compares that to the set of
// RFCs in the AppSheet tracker. For any CLs missing from the tracker, creates
// stub rows with just the change_id filled in.
function addNewRfcsToAppSheet() {
  const gerritCls = _fetchOpenRfcsCls();
  const trackerCls = _getExistingRfcsFromAppSheet();

  // Accumulate create requests so that requests can be batched.
  let createRows = [];
  for (const changeId of gerritCls) {
    if (!(changeId in trackerCls)) {
      createRows.push({ [CHANGE_ID_COL]: changeId });
    }
  }

  if (createRows.length != 0) {
    callAppSheetAPI({
      "Action": "Add",
      "Properties": {},
      Rows: createRows,
    });
  }
}

// Call the gerrit API and return some specific information about the named CL.
function getClInfo(changeId) {
  const cl = parseGerritResponse(UrlFetchApp.fetch(
    // include _account_id, email and username fields when referencing accounts.
    GERRIT_API_URL + `/changes/${changeId}?o=DETAILED_ACCOUNTS`
  ));

  // Remove subject prefix tags (e.g. '[rfc][docs]')
  const title = cl.subject.replace(/^(\S+]\s)/i, '');

  return {
    title,
    number: cl._number,
    author: cl.owner.email,
    created: cl.created,
    updated: cl.updated,
    status: cl.status,
    work_in_progress: Boolean(cl.work_in_progress),
  };
}
