// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* eslint-disable @devtools/no-imperative-dom-api */

import * as Common from '../../core/common/common.js';
import * as i18n from '../../core/i18n/i18n.js';
import * as Platform from '../../core/platform/platform.js';
import * as SDK from '../../core/sdk/sdk.js';
import * as Protocol from '../../generated/protocol.js';
import type * as Buttons from '../../ui/components/buttons/buttons.js';
import * as uiI18n from '../../ui/i18n/i18n.js';
import {Icon, Link} from '../../ui/kit/kit.js';
import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';
import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.js';
import * as UI from '../../ui/legacy/legacy.js';
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';

import {DOMStorageModel} from './DOMStorageModel.js';
import {IndexedDBModel} from './IndexedDBModel.js';
import storageViewStyles from './storageView.css.js';

const UIStrings = {
  /**
   * @description Text in the Storage View that expresses the amount of used and available storage quota
   * @example {1.5 MB} PH1
   * @example {123.1 MB} PH2
   */
  storageQuotaUsed: '{PH1} used out of {PH2} storage quota',
  /**
   * @description Tooltip in the Storage View that expresses the precise amount of used and available storage quota
   * @example {200} PH1
   * @example {400} PH2
   */
  storageQuotaUsedWithBytes: '{PH1} bytes used out of {PH2} bytes storage quota',
  /**
   * @description Fragment indicating that a certain data size has been custom configured
   * @example {1.5 MB} PH1
   */
  storageWithCustomMarker: '{PH1} (custom)',
  /**
   * @description Text in Application Panel Sidebar and title text of the Storage View of the Application panel
   */
  storageTitle: 'Storage',
  /**
   * @description Title text in Storage View of the Application panel
   */
  usage: 'Usage',
  /**
   * @description Unit for data size in DevTools
   */
  mb: 'MB',
  /**
   * @description Link to learn more about Progressive Web Apps
   */
  learnMore: 'Learn more',
  /**
   * @description Button text for the button in the Storage View of the Application panel for clearing site-specific storage
   */
  clearSiteData: 'Clear site data',
  /**
   * @description Announce message when the "clear site data" task is complete
   */
  SiteDataCleared: 'Site data cleared',
  /**
   * @description Category description in the Clear Storage section of the Storage View of the Application panel
   */
  application: 'Application',
  /**
   * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel
   */
  unregisterServiceWorker: 'Unregister service workers',
  /**
   * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel
   */
  localAndSessionStorage: 'Local and session storage',
  /**
   * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel
   */
  indexDB: 'IndexedDB',
  /**
   * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel
   */
  cookies: 'Cookies',
  /**
   * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel
   */
  cacheStorage: 'Cache storage',
  /**
   * @description Checkbox label in the Clear Storage section of the Storage View of the Application panel
   */
  includingThirdPartyCookies: 'including third-party cookies',
  /**
   * @description Text for error message in Application Quota Override
   * @example {Image} PH1
   */
  sFailedToLoad: '{PH1} (failed to load)',
  /**
   * @description Text for error message in Application Quota Override
   */
  internalError: 'Internal error',
  /**
   * @description Text for error message in Application Quota Override
   */
  pleaseEnterANumber: 'Please enter a number',
  /**
   * @description Text for error message in Application Quota Override
   */
  numberMustBeNonNegative: 'Number must be non-negative',
  /**
   * @description Text for error message in Application Quota Override
   * @example {9000000000000} PH1
   */
  numberMustBeSmaller: 'Number must be smaller than {PH1}',
  /**
   * @description Button text for the "Clear site data" button in the Storage View of the Application panel while the clearing action is pending
   */
  clearing: 'Clearing…',
  /**
   * @description Quota row title in Clear Storage View of the Application panel
   */
  storageQuotaIsLimitedIn: 'Storage quota is limited in Incognito mode',
  /**
   * @description Text in Application Panel Sidebar of the Application panel
   */
  fileSystem: 'File System',
  /**
   * @description Text in Application Panel Sidebar of the Application panel
   */
  other: 'Other',
  /**
   * @description Text in Application Panel Sidebar of the Application panel
   */
  storageUsage: 'Storage usage',
  /**
   * @description Text in Application Panel Sidebar of the Application panel
   */
  serviceWorkers: 'Service workers',
  /**
   * @description Checkbox label in Application Panel Sidebar of the Application panel.
   * Storage quota refers to the amount of disk available for the website or app.
   */
  simulateCustomStorage: 'Simulate custom storage quota',
} as const;
const str_ = i18n.i18n.registerUIStrings('panels/application/StorageView.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);

/**
 * @implements {SDK.TargetManager.Observer}
 */
export class StorageView extends UI.Widget.VBox {
  private pieColors: Map<Protocol.Storage.StorageType, string>;
  private reportView: UI.ReportView.ReportView;
  private target: SDK.Target.Target|null;
  private securityOrigin: string|null;
  private storageKey: string|null;
  private settings: Map<Protocol.Storage.StorageType, Common.Settings.Setting<boolean>>;
  private includeThirdPartyCookiesSetting: Common.Settings.Setting<boolean>;
  private quotaRow: HTMLElement;
  private quotaUsage: number|null;
  private pieChart: PerfUI.PieChart.PieChart;
  private previousOverrideFieldValue: string;
  private quotaOverrideCheckbox: UI.UIUtils.CheckboxLabel;
  private quotaOverrideControlRow: HTMLElement;
  private quotaOverrideEditor: HTMLInputElement;
  private quotaOverrideErrorMessage: HTMLElement;
  private clearButton: Buttons.Button.Button;
  private readonly throttler = new Common.Throttler.Throttler(1000);

  constructor() {
    super({useShadowDom: true});
    this.registerRequiredCSS(storageViewStyles);

    this.contentElement.classList.add('clear-storage-container');
    this.contentElement.setAttribute('jslog', `${VisualLogging.pane('clear-storage')}`);
    this.pieColors = new Map([
      [Protocol.Storage.StorageType.Cache_storage, 'rgb(229, 113, 113)'],   // red
      [Protocol.Storage.StorageType.Cookies, 'rgb(239, 196, 87)'],          // yellow
      [Protocol.Storage.StorageType.Indexeddb, 'rgb(155, 127, 230)'],       // purple
      [Protocol.Storage.StorageType.Local_storage, 'rgb(116, 178, 102)'],   // green
      [Protocol.Storage.StorageType.Service_workers, 'rgb(255, 167, 36)'],  // orange
    ]);

    // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.
    this.reportView = new UI.ReportView.ReportView(i18nString(UIStrings.storageTitle));
    this.reportView.registerRequiredCSS(storageViewStyles);

    this.reportView.element.classList.add('clear-storage-header');
    this.reportView.show(this.contentElement);
    this.target = null;
    this.securityOrigin = null;
    this.storageKey = null;

    this.settings = new Map();
    for (const type of AllStorageTypes) {
      this.settings.set(
          type,
          Common.Settings.Settings.instance().createSetting(
              'clear-storage-' + Platform.StringUtilities.toKebabCase(type), true));
    }

    this.includeThirdPartyCookiesSetting =
        Common.Settings.Settings.instance().createSetting('clear-storage-include-third-party-cookies', false);

    const clearButtonSection = this.reportView.appendSection('', 'clear-storage-button').appendRow();
    this.clearButton = UI.UIUtils.createTextButton(
        i18nString(UIStrings.clearSiteData), this.clear.bind(this), {jslogContext: 'storage.clear-site-data'});
    this.clearButton.id = 'storage-view-clear-button';
    clearButtonSection.appendChild(this.clearButton);

    const includeThirdPartyCookiesCheckbox = SettingsUI.SettingsUI.createSettingCheckbox(
        i18nString(UIStrings.includingThirdPartyCookies), this.includeThirdPartyCookiesSetting);
    includeThirdPartyCookiesCheckbox.classList.add('include-third-party-cookies');
    clearButtonSection.appendChild(includeThirdPartyCookiesCheckbox);

    const quota = this.reportView.appendSection(i18nString(UIStrings.usage));
    quota.element.setAttribute('jslog', `${VisualLogging.section('usage')}`);
    this.quotaRow = quota.appendSelectableRow();
    this.quotaRow.classList.add('quota-usage-row');
    const learnMoreRow = quota.appendRow();
    const learnMore = Link.create(
        'https://developer.chrome.com/docs/devtools/progressive-web-apps#opaque-responses',
        i18nString(UIStrings.learnMore), undefined, 'learn-more');
    learnMoreRow.appendChild(learnMore);
    this.quotaUsage = null;
    this.pieChart = new PerfUI.PieChart.PieChart();
    this.populatePieChart(0, []);
    const usageBreakdownRow = quota.appendRow();
    usageBreakdownRow.classList.add('usage-breakdown-row');
    usageBreakdownRow.appendChild(this.pieChart);

    this.previousOverrideFieldValue = '';
    const quotaOverrideCheckboxRow = quota.appendRow();
    quotaOverrideCheckboxRow.classList.add('quota-override-row');
    this.quotaOverrideCheckbox = UI.UIUtils.CheckboxLabel.create(i18nString(UIStrings.simulateCustomStorage), false);
    this.quotaOverrideCheckbox.setAttribute(
        'jslog', `${VisualLogging.toggle('simulate-custom-quota').track({change: true})}`);
    quotaOverrideCheckboxRow.appendChild(this.quotaOverrideCheckbox);
    this.quotaOverrideCheckbox.addEventListener('click', this.onClickCheckbox.bind(this), false);
    this.quotaOverrideControlRow = quota.appendRow();
    this.quotaOverrideEditor = this.quotaOverrideControlRow.createChild('input', 'quota-override-notification-editor');
    this.quotaOverrideEditor.setAttribute('placeholder', i18nString(UIStrings.pleaseEnterANumber));
    this.quotaOverrideEditor.setAttribute(
        'jslog', `${VisualLogging.textField('quota-override').track({change: true})}`);
    this.quotaOverrideControlRow.appendChild(UI.UIUtils.createLabel(i18nString(UIStrings.mb)));
    this.quotaOverrideControlRow.classList.add('hidden');
    this.quotaOverrideEditor.addEventListener('keyup', event => {
      if (event.key === 'Enter') {
        void this.applyQuotaOverrideFromInputField();
        event.consume(true);
      }
    });
    this.quotaOverrideEditor.addEventListener('focusout', event => {
      void this.applyQuotaOverrideFromInputField();
      event.consume(true);
    });

    const errorMessageRow = quota.appendRow();
    this.quotaOverrideErrorMessage = errorMessageRow.createChild('div', 'quota-override-error');

    const application = this.reportView.appendSection(i18nString(UIStrings.application));
    application.element.setAttribute('jslog', `${VisualLogging.section('application')}`);
    this.appendItem(
        application, i18nString(UIStrings.unregisterServiceWorker), Protocol.Storage.StorageType.Service_workers);
    application.markFieldListAsGroup();

    const storage = this.reportView.appendSection(i18nString(UIStrings.storageTitle));
    storage.element.setAttribute('jslog', `${VisualLogging.section('storage')}`);
    this.appendItem(storage, i18nString(UIStrings.localAndSessionStorage), Protocol.Storage.StorageType.Local_storage);
    this.appendItem(storage, i18nString(UIStrings.indexDB), Protocol.Storage.StorageType.Indexeddb);
    this.appendItem(storage, i18nString(UIStrings.cookies), Protocol.Storage.StorageType.Cookies);
    this.appendItem(storage, i18nString(UIStrings.cacheStorage), Protocol.Storage.StorageType.Cache_storage);
    storage.markFieldListAsGroup();

    SDK.TargetManager.TargetManager.instance().observeTargets(this);
  }

  private appendItem(
      section: UI.ReportView.Section, title: Platform.UIString.LocalizedString,
      settingName: Protocol.Storage.StorageType): void {
    const row = section.appendRow();
    const setting = this.settings.get(settingName);
    if (setting) {
      row.appendChild(SettingsUI.SettingsUI.createSettingCheckbox(title, setting));
    }
  }

  targetAdded(target: SDK.Target.Target): void {
    if (target !== SDK.TargetManager.TargetManager.instance().primaryPageTarget()) {
      return;
    }
    this.target = target;
    const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager) as
        SDK.SecurityOriginManager.SecurityOriginManager;
    this.updateOrigin(
        securityOriginManager.mainSecurityOrigin(), securityOriginManager.unreachableMainSecurityOrigin());
    securityOriginManager.addEventListener(
        SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this.originChanged, this);
    const storageKeyManager =
        target.model(SDK.StorageKeyManager.StorageKeyManager) as SDK.StorageKeyManager.StorageKeyManager;
    this.updateStorageKey(storageKeyManager.mainStorageKey());
    storageKeyManager.addEventListener(
        SDK.StorageKeyManager.Events.MAIN_STORAGE_KEY_CHANGED, this.storageKeyChanged, this);
  }

  targetRemoved(target: SDK.Target.Target): void {
    if (this.target !== target) {
      return;
    }
    const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager) as
        SDK.SecurityOriginManager.SecurityOriginManager;
    securityOriginManager.removeEventListener(
        SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this.originChanged, this);
    const storageKeyManager =
        target.model(SDK.StorageKeyManager.StorageKeyManager) as SDK.StorageKeyManager.StorageKeyManager;
    storageKeyManager.removeEventListener(
        SDK.StorageKeyManager.Events.MAIN_STORAGE_KEY_CHANGED, this.storageKeyChanged, this);
  }

  private originChanged(
      event: Common.EventTarget.EventTargetEvent<SDK.SecurityOriginManager.MainSecurityOriginChangedEvent>): void {
    const {mainSecurityOrigin, unreachableMainSecurityOrigin} = event.data;
    this.updateOrigin(mainSecurityOrigin, unreachableMainSecurityOrigin);
  }

  private storageKeyChanged(
      event: Common.EventTarget.EventTargetEvent<SDK.StorageKeyManager.MainStorageKeyChangedEvent>): void {
    const {mainStorageKey} = event.data;
    this.updateStorageKey(mainStorageKey);
  }

  private updateOrigin(mainOrigin: string, unreachableMainOrigin: string|null): void {
    const oldOrigin = this.securityOrigin;
    if (unreachableMainOrigin) {
      this.securityOrigin = unreachableMainOrigin;
      this.reportView.setSubtitle(i18nString(UIStrings.sFailedToLoad, {PH1: unreachableMainOrigin}));
    } else {
      this.securityOrigin = mainOrigin;
      this.reportView.setSubtitle(mainOrigin);
    }

    if (oldOrigin !== this.securityOrigin) {
      this.quotaOverrideControlRow.classList.add('hidden');
      this.quotaOverrideCheckbox.checked = false;
      this.quotaOverrideErrorMessage.textContent = '';
    }
    void this.performUpdate();
  }

  private updateStorageKey(mainStorageKey: string): void {
    const oldStorageKey = this.storageKey;

    this.storageKey = mainStorageKey;
    this.reportView.setSubtitle(mainStorageKey);

    if (oldStorageKey !== this.storageKey) {
      this.quotaOverrideControlRow.classList.add('hidden');
      this.quotaOverrideCheckbox.checked = false;
      this.quotaOverrideErrorMessage.textContent = '';
    }
    void this.performUpdate();
  }

  private async applyQuotaOverrideFromInputField(): Promise<void> {
    if (!this.target || !this.securityOrigin) {
      this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.internalError);
      return;
    }
    this.quotaOverrideErrorMessage.textContent = '';
    const editorString = this.quotaOverrideEditor.value;
    if (editorString === '') {
      await this.clearQuotaForOrigin(this.target, this.securityOrigin);
      this.previousOverrideFieldValue = '';
      return;
    }
    const quota = parseFloat(editorString);
    if (!Number.isFinite(quota)) {
      this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.pleaseEnterANumber);
      return;
    }
    if (quota < 0) {
      this.quotaOverrideErrorMessage.textContent = i18nString(UIStrings.numberMustBeNonNegative);
      return;
    }
    const cutoff = 9_000_000_000_000;
    if (quota >= cutoff) {
      this.quotaOverrideErrorMessage.textContent =
          i18nString(UIStrings.numberMustBeSmaller, {PH1: cutoff.toLocaleString()});
      return;
    }
    const bytesPerMB = 1000 * 1000;
    const quotaInBytes = Math.round(quota * bytesPerMB);
    const quotaFieldValue = `${quotaInBytes / bytesPerMB}`;
    this.quotaOverrideEditor.value = quotaFieldValue;
    this.previousOverrideFieldValue = quotaFieldValue;
    await this.target.storageAgent().invoke_overrideQuotaForOrigin(
        {origin: this.securityOrigin, quotaSize: quotaInBytes});
  }

  private async clearQuotaForOrigin(target: SDK.Target.Target, origin: string): Promise<void> {
    await target.storageAgent().invoke_overrideQuotaForOrigin({origin});
  }

  private async onClickCheckbox(): Promise<void> {
    if (this.quotaOverrideControlRow.classList.contains('hidden')) {
      this.quotaOverrideControlRow.classList.remove('hidden');
      this.quotaOverrideCheckbox.checked = true;
      this.quotaOverrideEditor.value = this.previousOverrideFieldValue;
      window.setTimeout(() => this.quotaOverrideEditor.focus(), 500);
    } else if (this.target && this.securityOrigin) {
      this.quotaOverrideControlRow.classList.add('hidden');
      this.quotaOverrideCheckbox.checked = false;
      await this.clearQuotaForOrigin(this.target, this.securityOrigin);
      this.quotaOverrideErrorMessage.textContent = '';
    }
  }

  private clear(): void {
    if (!this.securityOrigin) {
      return;
    }
    const selectedStorageTypes = [];
    for (const type of this.settings.keys()) {
      const setting = this.settings.get(type);
      if (setting?.get()) {
        selectedStorageTypes.push(type);
      }
    }

    if (this.target) {
      const includeThirdPartyCookies = this.includeThirdPartyCookiesSetting.get();
      StorageView.clear(
          this.target, this.storageKey, this.securityOrigin, selectedStorageTypes, includeThirdPartyCookies);
    }

    this.clearButton.disabled = true;
    const label = this.clearButton.textContent;
    this.clearButton.textContent = i18nString(UIStrings.clearing);
    window.setTimeout(() => {
      this.clearButton.disabled = false;
      this.clearButton.textContent = label;
      this.clearButton.focus();
    }, 500);

    UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.SiteDataCleared));
  }

  static clear(
      target: SDK.Target.Target, storageKey: string|null, originForCookies: string|null, selectedStorageTypes: string[],
      includeThirdPartyCookies: boolean): void {
    console.assert(Boolean(storageKey));
    if (!storageKey) {
      return;
    }
    void target.storageAgent().invoke_clearDataForStorageKey(
        {storageKey, storageTypes: selectedStorageTypes.join(',')});

    const set = new Set(selectedStorageTypes);
    const hasAll = set.has(Protocol.Storage.StorageType.All);

    if (set.has(Protocol.Storage.StorageType.Local_storage) || hasAll) {
      const storageModel = target.model(DOMStorageModel);
      if (storageModel) {
        storageModel.clearForStorageKey(storageKey);
      }
    }

    if (set.has(Protocol.Storage.StorageType.Indexeddb) || hasAll) {
      for (const target of SDK.TargetManager.TargetManager.instance().targets()) {
        const indexedDBModel = target.model(IndexedDBModel);
        if (indexedDBModel) {
          indexedDBModel.clearForStorageKey(storageKey);
        }
      }
    }

    if (originForCookies && (set.has(Protocol.Storage.StorageType.Cookies) || hasAll)) {
      void target.storageAgent().invoke_clearDataForOrigin(
          {origin: originForCookies, storageTypes: Protocol.Storage.StorageType.Cookies});
      const cookieModel = target.model(SDK.CookieModel.CookieModel);
      if (cookieModel) {
        void cookieModel.clear(undefined, includeThirdPartyCookies ? undefined : originForCookies);
      }
    }

    if (set.has(Protocol.Storage.StorageType.Cache_storage) || hasAll) {
      const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
      const model = target?.model(SDK.ServiceWorkerCacheModel.ServiceWorkerCacheModel);
      if (model) {
        model.clearForStorageKey(storageKey);
      }
    }
  }

  override async performUpdate(): Promise<void> {
    if (!this.securityOrigin || !this.target) {
      this.quotaRow.textContent = '';
      this.populatePieChart(0, []);
      return;
    }

    const securityOrigin = this.securityOrigin;
    const response = await this.target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin});
    this.quotaRow.textContent = '';
    if (response.getError()) {
      this.populatePieChart(0, []);
      return;
    }
    const quotaOverridden = response.overrideActive;
    const quotaAsString = i18n.ByteUtilities.bytesToString(response.quota);
    const usageAsString = i18n.ByteUtilities.bytesToString(response.usage);
    const formattedQuotaAsString = i18nString(UIStrings.storageWithCustomMarker, {PH1: quotaAsString});

    let quota: string|HTMLElement = quotaAsString;
    if (quotaOverridden) {
      const element = document.createElement('b');
      element.textContent = formattedQuotaAsString;
      quota = element;
    }

    const element = uiI18n.getFormatLocalizedString(str_, UIStrings.storageQuotaUsed, {PH1: usageAsString, PH2: quota});
    this.quotaRow.appendChild(element);
    UI.Tooltip.Tooltip.install(
        this.quotaRow,
        i18nString(
            UIStrings.storageQuotaUsedWithBytes,
            {PH1: response.usage.toLocaleString(), PH2: response.quota.toLocaleString()}));

    if (!response.overrideActive && response.quota < 125829120) {  // 120 MB
      const icon = new Icon();
      icon.name = 'info';
      icon.style.color = 'var(--icon-info)';
      icon.classList.add('small');
      UI.Tooltip.Tooltip.install(this.quotaRow, i18nString(UIStrings.storageQuotaIsLimitedIn));
      this.quotaRow.appendChild(icon);
    }

    if (this.quotaUsage === null || this.quotaUsage !== response.usage) {
      this.quotaUsage = response.usage;
      const slices: PerfUI.PieChart.Slice[] = [];
      for (const usageForType of response.usageBreakdown.sort((a, b) => b.usage - a.usage)) {
        const value = usageForType.usage;
        if (!value) {
          continue;
        }
        const title = this.getStorageTypeName(usageForType.storageType);
        const color = this.pieColors.get(usageForType.storageType) || '#ccc';
        slices.push({value, color, title});
      }
      this.populatePieChart(response.usage, slices);
    }

    void this.throttler.schedule(this.requestUpdate.bind(this));
  }

  private populatePieChart(total: number, slices: PerfUI.PieChart.Slice[]): void {
    this.pieChart.data = {
      chartName: i18nString(UIStrings.storageUsage),
      size: 110,
      formatter: i18n.ByteUtilities.bytesToString,
      showLegend: true,
      total,
      slices,
    };
  }

  private getStorageTypeName(type: Protocol.Storage.StorageType): string {
    switch (type) {
      case Protocol.Storage.StorageType.File_systems:
        return i18nString(UIStrings.fileSystem);
      case Protocol.Storage.StorageType.Indexeddb:
        return i18nString(UIStrings.indexDB);
      case Protocol.Storage.StorageType.Cache_storage:
        return i18nString(UIStrings.cacheStorage);
      case Protocol.Storage.StorageType.Service_workers:
        return i18nString(UIStrings.serviceWorkers);
      default:
        return i18nString(UIStrings.other);
    }
  }
}

export const AllStorageTypes = [
  Protocol.Storage.StorageType.Cache_storage,
  Protocol.Storage.StorageType.Cookies,
  Protocol.Storage.StorageType.Indexeddb,
  Protocol.Storage.StorageType.Local_storage,
  Protocol.Storage.StorageType.Service_workers,
];

export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
  handleAction(_context: UI.Context.Context, actionId: string): boolean {
    switch (actionId) {
      case 'resources.clear':
        return this.handleClear(false);
      case 'resources.clear-incl-third-party-cookies':
        return this.handleClear(true);
    }
    return false;
  }

  private handleClear(includeThirdPartyCookies: boolean): boolean {
    const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
    if (!target) {
      return false;
    }
    const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
    if (!resourceTreeModel) {
      return false;
    }
    const securityOrigin = resourceTreeModel.getMainSecurityOrigin();
    resourceTreeModel.getMainStorageKey().then(storageKey => {
      StorageView.clear(target, storageKey, securityOrigin, AllStorageTypes, includeThirdPartyCookies);
    }, _ => {});
    return true;
  }
}
