import {grantedOptPermissions, isPermissionsObjectEmpty, missingPermissions} from './optionsPermissions.js';
import optionsPrototype from './optionsPrototype.json5';
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
  let timeLabel = 'getOptions--' + randomId + '-' + (timerId++);
  console.time(timeLabel);
  // #!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
             console.debug(
                 'We are about to start checking granted permissions');
             console.timeLog(timeLabel);
             // #!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 => {
        console.group('getOptions(options); resolved; options: ', options);
        console.timeEnd(timeLabel);
        console.groupEnd();
        return items;
      })
      .catch(err => {
        console.group('getOptions(options); rejected; options: ', options);
        console.timeEnd(timeLabel);
        console.groupEnd();
        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).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'] ?? []);
    });
  });
}
