/*
 * Copyright (C) 2008 Nokia Inc.  All rights reserved.
 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
  /**
   * @param {!Resources.DOMStorage} domStorage
   */
  constructor(domStorage) {
    super(Common.UIString('DOM Storage'), 'domStoragePanel');

    this._domStorage = domStorage;

    this.element.classList.add('storage-view', 'table');

    const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
      {id: 'key', title: Common.UIString('Key'), sortable: false, editable: true, longText: true, weight: 50},
      {id: 'value', title: Common.UIString('Value'), sortable: false, editable: true, longText: true, weight: 50}
    ]);
    this._dataGrid = new DataGrid.DataGrid(
        columns, this._editingCallback.bind(this), this._deleteCallback.bind(this), this.refreshItems.bind(this));
    this._dataGrid.addEventListener(
        DataGrid.DataGrid.Events.SelectedNode,
        event => this._previewEntry(/** @type {!DataGrid.DataGridNode} */ (event.data)));
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.DeselectedNode, event => this._previewEntry(null));
    this._dataGrid.setStriped(true);
    this._dataGrid.setName('DOMStorageItemsView');

    this._splitWidget = new UI.SplitWidget(false, false);
    this._splitWidget.show(this.element);
    this._splitWidget.setSecondIsSidebar(true);

    this._previewPanel = new UI.VBox();
    const resizer = this._previewPanel.element.createChild('div', 'preview-panel-resizer');
    const dataGridWidget = this._dataGrid.asWidget();
    dataGridWidget.setMinimumSize(0, 50);
    this._splitWidget.setMainWidget(dataGridWidget);
    this._splitWidget.setSidebarWidget(this._previewPanel);
    this._splitWidget.installResizer(resizer);

    /** @type {?UI.Widget} */
    this._preview = null;
    /** @type {?string} */
    this._previewValue = null;

    this._showPreview(null, null);

    this._eventListeners = [];
    this.setStorage(domStorage);
  }

  /**
   * @param {!Resources.DOMStorage} domStorage
   */
  setStorage(domStorage) {
    Common.EventTarget.removeEventListeners(this._eventListeners);
    this._domStorage = domStorage;
    this._eventListeners = [
      this._domStorage.addEventListener(
          Resources.DOMStorage.Events.DOMStorageItemsCleared, this._domStorageItemsCleared, this),
      this._domStorage.addEventListener(
          Resources.DOMStorage.Events.DOMStorageItemRemoved, this._domStorageItemRemoved, this),
      this._domStorage.addEventListener(
          Resources.DOMStorage.Events.DOMStorageItemAdded, this._domStorageItemAdded, this),
      this._domStorage.addEventListener(
          Resources.DOMStorage.Events.DOMStorageItemUpdated, this._domStorageItemUpdated, this),
    ];
    this.refreshItems();
  }

  _domStorageItemsCleared() {
    if (!this.isShowing() || !this._dataGrid) {
      return;
    }

    this._dataGrid.rootNode().removeChildren();
    this._dataGrid.addCreationNode(false);
    this.setCanDeleteSelected(false);
  }

  /**
   * @param {!Common.Event} event
   */
  _domStorageItemRemoved(event) {
    if (!this.isShowing() || !this._dataGrid) {
      return;
    }

    const storageData = event.data;
    const rootNode = this._dataGrid.rootNode();
    const children = rootNode.children;

    for (let i = 0; i < children.length; ++i) {
      const childNode = children[i];
      if (childNode.data.key === storageData.key) {
        rootNode.removeChild(childNode);
        this.setCanDeleteSelected(children.length > 1);
        return;
      }
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _domStorageItemAdded(event) {
    if (!this.isShowing() || !this._dataGrid) {
      return;
    }

    const storageData = event.data;
    const rootNode = this._dataGrid.rootNode();
    const children = rootNode.children;

    for (let i = 0; i < children.length; ++i) {
      if (children[i].data.key === storageData.key) {
        return;
      }
    }

    const childNode = new DataGrid.DataGridNode({key: storageData.key, value: storageData.value}, false);
    rootNode.insertChild(childNode, children.length - 1);
  }

  /**
   * @param {!Common.Event} event
   */
  _domStorageItemUpdated(event) {
    if (!this.isShowing() || !this._dataGrid) {
      return;
    }

    const storageData = event.data;
    const childNode = this._dataGrid.rootNode().children.find(child => child.data.key === storageData.key);
    if (!childNode || childNode.data.value === storageData.value) {
      return;
    }

    childNode.data.value = storageData.value;
    childNode.refresh();
    if (!childNode.selected) {
      return;
    }
    this._previewEntry(childNode);
    this.setCanDeleteSelected(true);
  }

  /**
   * @param {!Array<!Array<string>>} items
   */
  _showDOMStorageItems(items) {
    const rootNode = this._dataGrid.rootNode();
    let selectedKey = null;
    for (const node of rootNode.children) {
      if (!node.selected) {
        continue;
      }
      selectedKey = node.data.key;
      break;
    }
    rootNode.removeChildren();
    let selectedNode = null;
    const filteredItems = item => `${item[0]} ${item[1]}`;
    for (const item of this.filter(items, filteredItems)) {
      const key = item[0];
      const value = item[1];
      const node = new DataGrid.DataGridNode({key: key, value: value}, false);
      node.selectable = true;
      rootNode.appendChild(node);
      if (!selectedNode || key === selectedKey) {
        selectedNode = node;
      }
    }
    if (selectedNode) {
      selectedNode.selected = true;
    }
    this._dataGrid.addCreationNode(false);
    this.setCanDeleteSelected(!!selectedNode);
  }

  /**
   * @override
   */
  deleteSelectedItem() {
    if (!this._dataGrid || !this._dataGrid.selectedNode) {
      return;
    }

    this._deleteCallback(this._dataGrid.selectedNode);
  }

  /**
   * @override
   */
  refreshItems() {
    this._domStorage.getItems().then(items => items && this._showDOMStorageItems(items));
  }

  /**
   * @override
   */
  deleteAllItems() {
    this._domStorage.clear();
    // explicitly clear the view because the event won't be fired when it has no items
    this._domStorageItemsCleared();
  }

  _editingCallback(editingNode, columnIdentifier, oldText, newText) {
    const domStorage = this._domStorage;
    if (columnIdentifier === 'key') {
      if (typeof oldText === 'string') {
        domStorage.removeItem(oldText);
      }
      domStorage.setItem(newText, editingNode.data.value || '');
      this._removeDupes(editingNode);
    } else {
      domStorage.setItem(editingNode.data.key || '', newText);
    }
  }

  /**
   * @param {!DataGrid.DataGridNode} masterNode
   */
  _removeDupes(masterNode) {
    const rootNode = this._dataGrid.rootNode();
    const children = rootNode.children;
    for (let i = children.length - 1; i >= 0; --i) {
      const childNode = children[i];
      if ((childNode.data.key === masterNode.data.key) && (masterNode !== childNode)) {
        rootNode.removeChild(childNode);
      }
    }
  }

  _deleteCallback(node) {
    if (!node || node.isCreationNode) {
      return;
    }

    if (this._domStorage) {
      this._domStorage.removeItem(node.data.key);
    }
  }

  /**
   * @param {?UI.Widget} preview
   * @param {?string} value
   */
  _showPreview(preview, value) {
    if (this._preview && this._previewValue === value) {
      return;
    }
    if (this._preview) {
      this._preview.detach();
    }
    if (!preview) {
      preview = new UI.EmptyWidget(Common.UIString('Select a value to preview'));
    }
    this._previewValue = value;
    this._preview = preview;
    preview.show(this._previewPanel.contentElement);
  }

  /**
   * @param {?DataGrid.DataGridNode} entry
   */
  async _previewEntry(entry) {
    const value = entry && entry.data && entry.data.value;
    if (!value) {
      this._showPreview(null, value);
      return;
    }
    const protocol = this._domStorage.isLocalStorage ? 'localstorage' : 'sessionstorage';
    const url = `${protocol}://${entry.key}`;
    const provider =
        Common.StaticContentProvider.fromString(url, Common.resourceTypes.XHR, /** @type {string} */ (value));
    const preview = await SourceFrame.PreviewFactory.createPreview(provider, 'text/plain');
    // Selection could've changed while the preview was loaded
    if (!entry.selected) {
      return;
    }
    this._showPreview(preview, value);
  }
};
