import {grantedOptPermissions, isPermissionsObjectEmpty, missingPermissions} from './optionsPermissions.js';
import {optionsPrototype} from './optionsPrototype';
import specialOptions from './specialOptions.json5';

export {optionsPrototype, specialOptions};

// Adds missing options with their default value. If |dryRun| is set to false,
// they are also saved to the sync storage area.
export function cleanUpOptions(options, dryRun = false) {
  console.debug('[cleanUpOptions] Previous options', JSON.stringify(options));

  if (typeof options !== 'object' || options === null) options = {};

  var ok = true;
  for (const [opt, optMeta] of Object.entries(optionsPrototype)) {
    if (!(opt in options) &&
        optMeta['killSwitchType'] !== 'internalKillSwitch') {
      ok = false;
      options[opt] = optMeta['defaultValue'];
    }
  }

  console.debug('[cleanUpOptions] New options', JSON.stringify(options));

  if (!ok && !dryRun) {
    chrome.storage.sync.set(options);
  }

  return options;
}

// This piece of code is used as part of the getOptions computation, and so
// isn't that useful. It's exported since we sometimes need to finish the
// computation in a service worker, where we have access to the
// chrome.permissions API.
//
// It accepts as an argument an object |items| with the same structure of the
// items saved in the sync storage area, and an array |permissionChecksFeatures|
// of features
export function disableItemsWithMissingPermissions(
    items, permissionChecksFeatures) {
  return grantedOptPermissions().then(grantedPerms => {
    let permissionChecksPromises = [];
    for (const f of permissionChecksFeatures)
      permissionChecksPromises.push(missingPermissions(f, grantedPerms));

    Promise.all(permissionChecksPromises).then(missingPerms => {
      for (let i = 0; i < permissionChecksFeatures.length; i++)
        if (!isPermissionsObjectEmpty(missingPerms[i]))
          items[permissionChecksFeatures[i]] = false;

      return items;
    });
  });
}

// Returns a promise which returns the values of options |options| which are
// stored in the sync storage area.
//
// |requireOptionalPermissions| will determine whether to check if the required
// optional permissions have been granted or not to the options which have such
// requirements. If it is true, features with missing permissions will have
// their value set to false.
//
// When a kill switch is active, affected options always have their value set to
// false.

// #!if !production
let timerId = 0;
let randomId = btoa(Math.random().toString()).substr(10, 5);
// #!endif
export function getOptions(options, requireOptionalPermissions = true) {
  // #!if !production
  const timeLabel = 'getOptions--' + randomId + '-' + (timerId++);
  const startMark = `mark_start_get_options_${timeLabel}`;
  const grantedPermissionsCheckMark =
      `mark_get_options_check_granted_permissions_${timeLabel}`;
  const endMark = `mark_end_get_options_${timeLabel}`;
  const measureName = `measure_get_options_${timeLabel}`;
  window.performance.mark(startMark, {detail: {options}});
  // #!endif
  // Once we only target MV3, this can be greatly simplified.
  return new Promise((resolve, reject) => {
           if (typeof options === 'string')
             options = [options, '_forceDisabledFeatures'];
           else if (Array.isArray(options))
             options = [...options, '_forceDisabledFeatures'];
           else if (options !== null)
             return reject(new Error(
                 'Unexpected |options| parameter of type ' + (typeof options) +
                 ' (expected: string, array, or null).'));

           chrome.storage.sync.get(options, items => {
             if (chrome.runtime.lastError)
               return reject(chrome.runtime.lastError);

             // Handle applicable kill switches which force disable features
             if (items?._forceDisabledFeatures) {
               for (let feature of items._forceDisabledFeatures) {
                 items[feature] = false;
               }

               delete items._forceDisabledFeatures;
             }

             if (!requireOptionalPermissions) return resolve(items);

             // Check whether some options have missing permissions which would
             // force disable these features
             let permissionChecksFeatures = [];
             for (const [key, value] of Object.entries(items))
               if ((key in optionsPrototype) && value &&
                   optionsPrototype[key].requiredOptPermissions?.length)
                 permissionChecksFeatures.push(key);

             if (permissionChecksFeatures.length == 0) return resolve(items);

             // If we don't have access to the chrome.permissions API (content
             // scripts don't have access to it[1]), do the final piece of
             // computation in the service worker/background script.
             // [1]:
             // https://developer.chrome.com/docs/extensions/mv3/content_scripts/

             // #!if !production
             window.performance.mark(
                 grantedPermissionsCheckMark, {detail: {options}});
             // #!endif
             if (!chrome.permissions) {
               return chrome.runtime.sendMessage(
                   {
                     message: 'runDisableItemsWithMissingPermissions',
                     options: {
                       items,
                       permissionChecksFeatures,
                     },
                   },
                   response => {
                     if (response === undefined)
                       return reject(new Error(
                           'An error ocurred while communicating with the service worker: ' +
                           chrome.runtime.lastError.message));

                     if (response.status == 'rejected')
                       return reject(response.error);
                     if (response.status == 'resolved')
                       return resolve(response.items);
                     return reject(new Error(
                         'An unknown response was recieved from service worker.'));
                   });
             }

             disableItemsWithMissingPermissions(items, permissionChecksFeatures)
                 .then(finalItems => resolve(finalItems))
                 .catch(err => reject(err));
           });
         })
      // #!if !production
      .then(items => {
        window.performance.mark(endMark, {detail: {options}});
        window.performance.measure(measureName, {
          detail: {options},
          start: startMark,
          end: endMark,
        });
        return items;
      })
      .catch(err => {
        window.performance.mark(endMark, {detail: {options}});
        window.performance.measure(measureName, {
          detail: {options},
          start: startMark,
          end: endMark,
        });
        throw err;
      })
      // #!endif
      ;
}

// Returns a promise which returns whether the |option| option/feature is
// currently enabled. If the feature requires optional permissions to work,
// |requireOptionalPermissions| will determine whether to check if the required
// optional permissions have been granted or not.
export function isOptionEnabled(option, requireOptionalPermissions = true) {
  return getOptions(option, requireOptionalPermissions).then(options => {
    return options?.[option] === true;
  });
}

export function getForceDisabledFeatures() {
  return new Promise((res, rej) => {
    chrome.storage.sync.get('_forceDisabledFeatures', items => {
      if (chrome.runtime.lastError) return rej(chrome.runtime.lastError);
      res(items?.['_forceDisabledFeatures'] ?? []);
    });
  });
}
