/*
 * Copyright (C) 2010 Apple Inc. 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 BY APPLE INC. AND ITS CONTRIBUTORS ``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 ITS 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.
 */

/**
 * @unrestricted
 */
Resources.ApplicationCacheItemsView = class extends UI.SimpleView {
  constructor(model, frameId) {
    super(Common.UIString('AppCache'));

    this._model = model;

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

    this._deleteButton = new UI.ToolbarButton(Common.UIString('Delete'), 'largeicon-delete');
    this._deleteButton.setVisible(false);
    this._deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._deleteButtonClicked, this);

    this._connectivityIcon = createElement('span', 'dt-icon-label');
    this._connectivityIcon.style.margin = '0 2px 0 5px';
    this._statusIcon = createElement('span', 'dt-icon-label');
    this._statusIcon.style.margin = '0 2px 0 5px';

    this._frameId = frameId;

    this._emptyWidget = new UI.EmptyWidget(Common.UIString('No Application Cache information available.'));
    this._emptyWidget.show(this.element);

    this._markDirty();

    const status = this._model.frameManifestStatus(frameId);
    this.updateStatus(status);
    this.updateNetworkState(this._model.onLine);

    // FIXME: Status bar items don't work well enough yet, so they are being hidden.
    // http://webkit.org/b/41637 Web Inspector: Give Semantics to "Refresh" and "Delete" Buttons in ApplicationCache DataGrid
    this._deleteButton.element.style.display = 'none';
  }

  /**
   * @override
   * @return {!Array.<!UI.ToolbarItem>}
   */
  syncToolbarItems() {
    return [
      this._deleteButton, new UI.ToolbarItem(this._connectivityIcon), new UI.ToolbarSeparator(),
      new UI.ToolbarItem(this._statusIcon)
    ];
  }

  /**
   * @override
   */
  wasShown() {
    this._maybeUpdate();
  }

  /**
   * @override
   */
  willHide() {
    this._deleteButton.setVisible(false);
  }

  _maybeUpdate() {
    if (!this.isShowing() || !this._viewDirty) {
      return;
    }

    this._update();
    this._viewDirty = false;
  }

  _markDirty() {
    this._viewDirty = true;
  }

  /**
   * @param {number} status
   */
  updateStatus(status) {
    const oldStatus = this._status;
    this._status = status;

    const statusInformation = {};
    // We should never have UNCACHED status, since we remove frames with UNCACHED application cache status from the tree.
    statusInformation[Resources.ApplicationCacheModel.UNCACHED] = {type: 'smallicon-red-ball', text: 'UNCACHED'};
    statusInformation[Resources.ApplicationCacheModel.IDLE] = {type: 'smallicon-green-ball', text: 'IDLE'};
    statusInformation[Resources.ApplicationCacheModel.CHECKING] = {type: 'smallicon-orange-ball', text: 'CHECKING'};
    statusInformation[Resources.ApplicationCacheModel.DOWNLOADING] = {
      type: 'smallicon-orange-ball',
      text: 'DOWNLOADING'
    };
    statusInformation[Resources.ApplicationCacheModel.UPDATEREADY] = {
      type: 'smallicon-green-ball',
      text: 'UPDATEREADY'
    };
    statusInformation[Resources.ApplicationCacheModel.OBSOLETE] = {type: 'smallicon-red-ball', text: 'OBSOLETE'};

    const info = statusInformation[status] || statusInformation[Resources.ApplicationCacheModel.UNCACHED];

    this._statusIcon.type = info.type;
    this._statusIcon.textContent = info.text;

    if (this.isShowing() && this._status === Resources.ApplicationCacheModel.IDLE &&
        (oldStatus === Resources.ApplicationCacheModel.UPDATEREADY || !this._resources)) {
      this._markDirty();
    }
    this._maybeUpdate();
  }

  /**
   * @param {boolean} isNowOnline
   */
  updateNetworkState(isNowOnline) {
    if (isNowOnline) {
      this._connectivityIcon.type = 'smallicon-green-ball';
      this._connectivityIcon.textContent = Common.UIString('Online');
    } else {
      this._connectivityIcon.type = 'smallicon-red-ball';
      this._connectivityIcon.textContent = Common.UIString('Offline');
    }
  }

  async _update() {
    const applicationCache = await this._model.requestApplicationCache(this._frameId);

    if (!applicationCache || !applicationCache.manifestURL) {
      delete this._manifest;
      delete this._creationTime;
      delete this._updateTime;
      delete this._size;
      delete this._resources;

      this._emptyWidget.show(this.element);
      this._deleteButton.setVisible(false);
      if (this._dataGrid) {
        this._dataGrid.element.classList.add('hidden');
      }
      return;
    }
    // FIXME: are these variables needed anywhere else?
    this._manifest = applicationCache.manifestURL;
    this._creationTime = applicationCache.creationTime;
    this._updateTime = applicationCache.updateTime;
    this._size = applicationCache.size;
    this._resources = applicationCache.resources;

    if (!this._dataGrid) {
      this._createDataGrid();
    }

    this._populateDataGrid();
    this._dataGrid.autoSizeColumns(20, 80);
    this._dataGrid.element.classList.remove('hidden');
    this._emptyWidget.detach();
    this._deleteButton.setVisible(true);

    // FIXME: For Chrome, put creationTime and updateTime somewhere.
    // NOTE: localizedString has not yet been added.
    // Common.UIString("(%s) Created: %s Updated: %s", this._size, this._creationTime, this._updateTime);
  }

  _createDataGrid() {
    const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
      {id: 'resource', title: Common.UIString('Resource'), sort: DataGrid.DataGrid.Order.Ascending, sortable: true},
      {id: 'type', title: Common.UIString('Type'), sortable: true},
      {id: 'size', title: Common.UIString('Size'), align: DataGrid.DataGrid.Align.Right, sortable: true}
    ]);
    this._dataGrid = new DataGrid.DataGrid(columns);
    this._dataGrid.setStriped(true);
    this._dataGrid.asWidget().show(this.element);
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._populateDataGrid, this);
  }

  _populateDataGrid() {
    const selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.resource : null;
    const sortDirection = this._dataGrid.isSortOrderAscending() ? 1 : -1;

    function numberCompare(field, resource1, resource2) {
      return sortDirection * (resource1[field] - resource2[field]);
    }
    function localeCompare(field, resource1, resource2) {
      return sortDirection * (resource1[field] + '').localeCompare(resource2[field] + '');
    }

    let comparator;
    switch (this._dataGrid.sortColumnId()) {
      case 'resource':
        comparator = localeCompare.bind(null, 'url');
        break;
      case 'type':
        comparator = localeCompare.bind(null, 'type');
        break;
      case 'size':
        comparator = numberCompare.bind(null, 'size');
        break;
      default:
        localeCompare.bind(null, 'resource');  // FIXME: comparator = ?
    }

    this._resources.sort(comparator);
    this._dataGrid.rootNode().removeChildren();

    let nodeToSelect;
    for (let i = 0; i < this._resources.length; ++i) {
      const data = {};
      const resource = this._resources[i];
      data.resource = resource.url;
      data.type = resource.type;
      data.size = Number.bytesToString(resource.size);
      const node = new DataGrid.DataGridNode(data);
      node.resource = resource;
      node.selectable = true;
      this._dataGrid.rootNode().appendChild(node);
      if (resource === selectedResource) {
        nodeToSelect = node;
        nodeToSelect.selected = true;
      }
    }

    if (!nodeToSelect && this._dataGrid.rootNode().children.length) {
      this._dataGrid.rootNode().children[0].selected = true;
    }
  }

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

    // FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?)
    this._deleteCallback(this._dataGrid.selectedNode);
  }

  _deleteCallback(node) {
    // FIXME: Should we delete a single (selected) resource or all resources?
    // Protocol.inspectorBackend.deleteCachedResource(...)
    // this._update();
  }
};
