// Since we disconnect all tabs from the policy prefs, we need to manually reload
// them on pref updates. If the pref change is a temporary add-on-inflicted change,
// we reload only a specific tab.
var ahtStatus = {
  reloadAllTabs: true
};

var blockButtonClicks = [];

messenger.messageContentPolicy.onChanged.addListener(async (newValue) => {
  // If this policy change is part of an add-on inflicted temporary
  // policy change, ignore it.
  if (ahtStatus.ignorePolicyChange) {
    return;
  }

  let tabs = await messenger.tabs.query({});
  for (let tab of tabs) {
    if (!["messageDisplay", "mail"].includes(tab.type)) {
      continue;
    }
    if (ahtStatus.reloadAllTabs || ahtStatus.reloadTab == tab.id) {
      await messenger.allowHtmlTemp.reloadTab(tab.id);
    }
  }
  await setButtonIconAndLabel();
});

// An option change could cause the button policy to be identical to the current
// policy and the button needs to be disabled.
messenger.storage.onChanged.addListener(async (changes) => {
  await optionsInit();
  if (changes.buttonHtmlMode) {
    // Reload all already open tabs, to trigger the single entry point for all
    // UI updates of the AHT addon: a message display.
    let tabs = await messenger.tabs.query({});
    for (let tab of tabs) {
      if (!["messageDisplay", "mail"].includes(tab.type)) {
        continue;
      }
      await messenger.allowHtmlTemp.reloadTab(tab.id);
    }
  }
  await setButtonIconAndLabel();
  await setCommandKey();
});

// Add eventListener for onClicked on the message header button.
messenger.messageDisplayAction.onClicked.addListener(async (tab, info) => {
  await ahtLogic(tab.id, info, false);
});

// Add eventListener for remote item in remoteContentBar doorhanger context menu
messenger.allowHtmlTemp.onClick.addListener(async (tabId) => {
  consoleDebug("AHT: allowHtmlTemp.onClick.addListener: tabId = ", tabId);
  await ahtLogic(tabId, "", true);
});

// Disconnect all message tabs from the menu/prefs and disable/enable buttons.
messenger.messageDisplay.onMessagesDisplayed.addListener(async (tab, messages) => {
  await messenger.allowHtmlTemp.disconnectTab(tab.id);

  // This is a reload caused by an add-on inflicted policy change, return to the
  // user defined value without reloading the tab again.
  if (ahtStatus.returnToPolicy) {
    // The following policy update should not trigger a reload.
    // not 100 % sure, but use the complete object, not only msgBodyAs
    let updateProperties = ahtStatus.returnToPolicy;
    ahtStatus = {
      ignorePolicyChange: true
    }
    // not 100 % sure, but use the complete object, not only msgBodyAs
    await messenger.messageContentPolicy.update(updateProperties);
  } else {
    // Update buttons for the newly loaded message.
    updateActionButtonForNewMessages(tab, messages);
  }

  // Remove the action block now that the policy has been reset to default. 
  blockButtonClicks[tab.id] = false;
  consoleDebug("AHT: onMessagesDisplayed: blockButtonClicks tab.id: ", tab.id);
  consoleDebug("AHT: onMessagesDisplayed: blockButtonClicks value: ", blockButtonClicks[tab.id]);

  // Reconnect after the add-on inflicted temporary policy change, to have all tabs reloaded 
  // in case of later default policy change
  if (ahtStatus.ignorePolicyChange) {
    ahtStatus = {
      reloadAllTabs: true
    }
  }
  await setButtonIconAndLabel();
});

(async () => {getCurrentPolicy
  await optionsMigrate();
  await optionsInit();

  // Reload all already open tabs, to trigger the single entry point for all
  // UI updates of the AHT addon: a message display.
  let tabs = await messenger.tabs.query({});
  for (let tab of tabs) {
    if (!["messageDisplay", "mail"].includes(tab.type)) {
      continue;
    }
    await messenger.allowHtmlTemp.reloadTab(tab.id);
  }

})();

async function ahtLogic(tabId, info, remoteButton) {
  consoleDebug("AHT: allowHtmlTemp: fired");
  consoleDebug("AHT: allowHtmlTemp: options.debug = " + options.debug);
  consoleDebug("AHT: allowHtmlTemp: options.buttonHtmlMode = " + options.buttonHtmlMode);
  consoleDebug("AHT: allowHtmlTemp: options.tempRemoteContent = " + options.tempRemoteContent);
  consoleDebug("AHT: allowHtmlTemp: tabId: " + tabId);
  consoleDebug("AHT: allowHtmlTemp: info.modifiers: " + info.modifiers);
  consoleDebug("AHT: allowHtmlTemp: remoteButton: " + remoteButton);

  let buttonPolicy = await getButtonPolicy(info, remoteButton);
  let currentPolicy = await getCurrentPolicy();
  consoleDebug("AHT: ahtLogic: buttonPolicy: ", buttonPolicy);
  consoleDebug("AHT: ahtLogic: currentPolicy: ", currentPolicy);

  // Block the action in case of quick multiple clicks, to prevent garbled default prefs
  consoleDebug("AHT: ahtLogic: blockButtonClicks tabId: ", tabId);
  consoleDebug("AHT: ahtLogic: blockButtonClicks value: ", blockButtonClicks[tabId]);
  if (blockButtonClicks[tabId])  { return; }
  blockButtonClicks[tabId] = true;
  consoleDebug("AHT: ahtLogic: blockButtonClicks tabId: ", tabId);
  consoleDebug("AHT: ahtLogic: blockButtonClicks value: ", blockButtonClicks[tabId]);

  // The following policy switch is not a change of the default, but a temporary
  // switch, so we have to return to the current policy once the tab is loaded.
  ahtStatus = {
    returnToPolicy: currentPolicy,
    reloadTab: tabId,
  }

  await ahtFunctions.allowHtmlTemp(tabId, info.modifiers, remoteButton);

  // In the following case the above call of ahtFunctions.allowhtmltemp() doesn't trigger a message reload,
  // so we need to trigger the message reload manual by the following lines
  if (buttonPolicy.msgBodyAs == currentPolicy.msgBodyAs) {
    consoleDebug("AHT: ahtLogic: buttonPolicy.msgBodyAs == currentPolicy.msgBodyAs: ", (buttonPolicy.msgBodyAs == currentPolicy.msgBodyAs));
    await messenger.allowHtmlTemp.reloadTab(tabId);
  }
}

async function getButtonPolicy(info, remoteButton) {
  // RemoteContent popupmenu item clicked in remote content bar in a HTML message
  if (remoteButton === true) {
    consoleDebug("AHT: getButtonPolicy: remoteButton === true");
    return { 
      msgBodyAs: "original",
      disableRemoteContent: false,
      // do not use false for attachmentsInline, but null to leave option unset if not tempInline
      attachmentsInline: ((options.tempInline === true) ? true : null)
    };
  }

  // Adapt button policy according to the possible modifier keys
  // Addon button clicked + both CTRL and SHIFT key
  if((info.modifiers.includes("Ctrl") || info.modifiers.includes("Command")) && info.modifiers.includes("Shift")) {
    consoleDebug("AHT: getButtonPolicy: Addon button clicked + both CTRL and SHIFT key");
    return { msgBodyAs: "sanitized" };
  }
  // Addon button clicked + only CTRL key
  else if((info.modifiers.includes("Ctrl") || info.modifiers.includes("Command")) && !(info.modifiers.includes("Shift"))) {
    consoleDebug("AHT: getButtonPolicy: Addon button clicked + only CTRL key");
    return { 
      msgBodyAs: "original",
      disableRemoteContent: false,
      // do not use false for attachmentsInline, but null to leave option unset if not tempInline
      attachmentsInline: ((options.tempInline === true) ? true : null)
    };
  }
  // Addon button clicked + only SHIFT key
  else if ((info.modifiers.includes("Shift")) && !((info.modifiers.includes("Ctrl") || info.modifiers.includes("Command")))) {
    consoleDebug("AHT: getButtonPolicy: Addon button clicked + only SHIFT key");
    return { msgBodyAs: "plaintext" };
  }

  // The last case is just the button without a relevant modifier key
  else {
    const modeMap = {
      "buttonMode_plaintext": "plaintext",
      "buttonMode_sanitized": "sanitized",
      "buttonMode_html": "original",
    }
    // return modeMap[await getOption("buttonHtmlMode")];
    // buttonPolicy must include the options tempRemoteContent (which is vice versa to disableRemoteContent) 
    // and tempInline
    return { 
      msgBodyAs: modeMap[await getOption("buttonHtmlMode")], 
      disableRemoteContent: !(options.tempRemoteContent), 
      // do not use false for attachmentsInline, but null to leave option unset if not tempInline
      attachmentsInline: ((options.tempInline === true) ? true : null)
    };
  }
}

async function getCurrentPolicy() {
  let currentPolicy = await messenger.messageContentPolicy.getCurrent();
  return currentPolicy;
}
