/*
 * Copyright (C) 2009 Apple Inc.  All rights reserved.
 * Copyright (C) 2009 Joseph Pecoraro
 * Copyright (C) 2010 Google 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE 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 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
 */
CookieTable.CookiesTable = class extends UI.VBox {
  /**
   * @param {function(!SDK.Cookie, ?SDK.Cookie): !Promise<boolean>=} saveCallback
   * @param {function()=} refreshCallback
   * @param {function()=} selectedCallback
   * @param {function(!SDK.Cookie, function())=} deleteCallback
   */
  constructor(saveCallback, refreshCallback, selectedCallback, deleteCallback) {
    super();

    this._saveCallback = saveCallback;
    this._refreshCallback = refreshCallback;
    this._deleteCallback = deleteCallback;

    const editable = !!saveCallback;

    const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
      {
        id: 'name',
        title: Common.UIString('Name'),
        sortable: true,
        disclosure: editable,
        sort: DataGrid.DataGrid.Order.Ascending,
        longText: true,
        weight: 24,
        editable: editable
      },
      {id: 'value', title: Common.UIString('Value'), sortable: true, longText: true, weight: 34, editable: editable},
      {id: 'domain', title: Common.UIString('Domain'), sortable: true, weight: 7, editable: editable},
      {id: 'path', title: Common.UIString('Path'), sortable: true, weight: 7, editable: editable},
      {id: 'expires', title: Common.UIString('Expires / Max-Age'), sortable: true, weight: 7, editable: editable},
      {id: 'size', title: Common.UIString('Size'), sortable: true, align: DataGrid.DataGrid.Align.Right, weight: 7}, {
        id: 'httpOnly',
        title: Common.UIString('HTTP'),
        sortable: true,
        align: DataGrid.DataGrid.Align.Center,
        weight: 7
      },
      {
        id: 'secure',
        title: Common.UIString('Secure'),
        sortable: true,
        align: DataGrid.DataGrid.Align.Center,
        weight: 7
      },
      {
        id: 'sameSite',
        title: Common.UIString('SameSite'),
        sortable: true,
        align: DataGrid.DataGrid.Align.Center,
        weight: 7
      }
    ]);

    if (editable) {
      this._dataGrid = new DataGrid.DataGrid(
          columns, this._onUpdateCookie.bind(this), this._onDeleteCookie.bind(this), refreshCallback);
    } else {
      this._dataGrid = new DataGrid.DataGrid(columns);
    }
    this._dataGrid.setStriped(true);

    this._dataGrid.setName('cookiesTable');
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._rebuildTable, this);

    if (selectedCallback)
      this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode, selectedCallback, this);

    /** @type {?string} */
    this._lastEditedColumnId = null;

    this._dataGrid.asWidget().show(this.element);
    this._data = [];

    /** @type {string} */
    this._cookieDomain = '';
  }

  /**
   * @param {!Array.<!SDK.Cookie>} cookies
   */
  setCookies(cookies) {
    this.setCookieFolders([{cookies: cookies}]);
  }

  /**
   * @param {!Array.<!{folderName: ?string, cookies: ?Array.<!SDK.Cookie>}>} cookieFolders
   */
  setCookieFolders(cookieFolders) {
    this._data = cookieFolders;
    this._rebuildTable();
  }

  /**
   * @param {string} cookieDomain
   */
  setCookieDomain(cookieDomain) {
    this._cookieDomain = cookieDomain;
  }

  /**
   * @return {?SDK.Cookie}
   */
  selectedCookie() {
    const node = this._dataGrid.selectedNode;
    return node ? node.cookie : null;
  }

  /**
   * @return {{current: ?SDK.Cookie, neighbor: ?SDK.Cookie}}
   */
  _getSelectionCookies() {
    const node = this._dataGrid.selectedNode;
    const nextNeighbor = node && node.traverseNextNode(true);
    const previousNeighbor = node && node.traversePreviousNode(true);

    return {
      current: node && node.cookie,
      neighbor: (nextNeighbor && nextNeighbor.cookie) || (previousNeighbor && previousNeighbor.cookie)
    };
  }

  /**
   * @override
   */
  willHide() {
    this._lastEditedColumnId = null;
  }

  /**
   * @param {{current: ?SDK.Cookie, neighbor: ?SDK.Cookie}} selectionCookies
   * @param {?Array<!SDK.Cookie>} cookies
   * @return {?SDK.Cookie}
   */
  _findSelectedCookie(selectionCookies, cookies) {
    if (!cookies)
      return null;

    const current = selectionCookies.current;
    const foundCurrent = cookies.find(cookie => this._isSameCookie(cookie, current));
    if (foundCurrent)
      return foundCurrent;

    const neighbor = selectionCookies.neighbor;
    const foundNeighbor = cookies.find(cookie => this._isSameCookie(cookie, neighbor));
    if (foundNeighbor)
      return foundNeighbor;

    return null;
  }

  /**
   * @param {!SDK.Cookie} cookieA
   * @param {?SDK.Cookie} cookieB
   * @return {boolean}
   */
  _isSameCookie(cookieA, cookieB) {
    return !!cookieB && cookieB.name() === cookieA.name() && cookieB.domain() === cookieA.domain() &&
        cookieB.path() === cookieA.path();
  }

  _rebuildTable() {
    const selectionCookies = this._getSelectionCookies();
    const lastEditedColumnId = this._lastEditedColumnId;
    this._lastEditedColumnId = null;
    this._dataGrid.rootNode().removeChildren();
    for (let i = 0; i < this._data.length; ++i) {
      const item = this._data[i];
      const selectedCookie = this._findSelectedCookie(selectionCookies, item.cookies);
      if (item.folderName) {
        const groupData = {
          name: item.folderName,
          value: '',
          domain: '',
          path: '',
          expires: '',
          size: this._totalSize(item.cookies),
          httpOnly: '',
          secure: '',
          sameSite: ''
        };
        const groupNode = new DataGrid.DataGridNode(groupData);
        groupNode.selectable = true;
        this._dataGrid.rootNode().appendChild(groupNode);
        groupNode.element().classList.add('row-group');
        this._populateNode(groupNode, item.cookies, selectedCookie, lastEditedColumnId);
        groupNode.expand();
      } else {
        this._populateNode(this._dataGrid.rootNode(), item.cookies, selectedCookie, lastEditedColumnId);
      }
    }
    if (selectionCookies.current && lastEditedColumnId && !this._dataGrid.selectedNode)
      this._addInactiveNode(this._dataGrid.rootNode(), selectionCookies.current, lastEditedColumnId);
    if (this._saveCallback)
      this._dataGrid.addCreationNode(false);
  }

  /**
   * @param {!DataGrid.DataGridNode} parentNode
   * @param {?Array.<!SDK.Cookie>} cookies
   * @param {?SDK.Cookie} selectedCookie
   * @param {?string} lastEditedColumnId
   */
  _populateNode(parentNode, cookies, selectedCookie, lastEditedColumnId) {
    parentNode.removeChildren();
    if (!cookies)
      return;

    this._sortCookies(cookies);
    for (let i = 0; i < cookies.length; ++i) {
      const cookie = cookies[i];
      const cookieNode = this._createGridNode(cookie);
      parentNode.appendChild(cookieNode);
      if (this._isSameCookie(cookie, selectedCookie)) {
        cookieNode.select();
        if (lastEditedColumnId !== null)
          this._dataGrid.startEditingNextEditableColumnOfDataGridNode(cookieNode, lastEditedColumnId);
      }
    }
  }

  /**
   * @param {!DataGrid.DataGridNode} parentNode
   * @param {!SDK.Cookie} cookie
   * @param {?string} editedColumnId
   */
  _addInactiveNode(parentNode, cookie, editedColumnId) {
    const cookieNode = this._createGridNode(cookie);
    parentNode.appendChild(cookieNode);
    cookieNode.select();
    cookieNode.setInactive(true);
    if (editedColumnId !== null)
      this._dataGrid.startEditingNextEditableColumnOfDataGridNode(cookieNode, editedColumnId);
  }

  _totalSize(cookies) {
    let totalSize = 0;
    for (let i = 0; cookies && i < cookies.length; ++i)
      totalSize += cookies[i].size();
    return totalSize;
  }

  /**
   * @param {!Array.<!SDK.Cookie>} cookies
   */
  _sortCookies(cookies) {
    const sortDirection = this._dataGrid.isSortOrderAscending() ? 1 : -1;

    /**
     * @param {!SDK.Cookie} cookie
     * @param {string} property
     * @return {string}
     */
    function getValue(cookie, property) {
      return typeof cookie[property] === 'function' ? String(cookie[property]()) : String(cookie.name());
    }

    /**
     * @param {string} property
     * @param {!SDK.Cookie} cookie1
     * @param {!SDK.Cookie} cookie2
     */
    function compareTo(property, cookie1, cookie2) {
      return sortDirection * getValue(cookie1, property).compareTo(getValue(cookie2, property));
    }

    /**
     * @param {!SDK.Cookie} cookie1
     * @param {!SDK.Cookie} cookie2
     */
    function numberCompare(cookie1, cookie2) {
      return sortDirection * (cookie1.size() - cookie2.size());
    }

    /**
     * @param {!SDK.Cookie} cookie1
     * @param {!SDK.Cookie} cookie2
     */
    function expiresCompare(cookie1, cookie2) {
      if (cookie1.session() !== cookie2.session())
        return sortDirection * (cookie1.session() ? 1 : -1);

      if (cookie1.session())
        return 0;

      if (cookie1.maxAge() && cookie2.maxAge())
        return sortDirection * (cookie1.maxAge() - cookie2.maxAge());
      if (cookie1.expires() && cookie2.expires())
        return sortDirection * (cookie1.expires() - cookie2.expires());
      return sortDirection * (cookie1.expires() ? 1 : -1);
    }

    let comparator;
    const columnId = this._dataGrid.sortColumnId() || 'name';
    if (columnId === 'expires')
      comparator = expiresCompare;
    else if (columnId === 'size')
      comparator = numberCompare;
    else
      comparator = compareTo.bind(null, columnId);
    cookies.sort(comparator);
  }

  /**
   * @param {!SDK.Cookie} cookie
   * @return {!DataGrid.DataGridNode}
   */
  _createGridNode(cookie) {
    const data = {};
    data.name = cookie.name();
    data.value = cookie.value();
    if (cookie.type() === SDK.Cookie.Type.Request) {
      data.domain = Common.UIString('N/A');
      data.path = Common.UIString('N/A');
      data.expires = Common.UIString('N/A');
    } else {
      data.domain = cookie.domain() || '';
      data.path = cookie.path() || '';
      if (cookie.maxAge())
        data.expires = Number.secondsToString(parseInt(cookie.maxAge(), 10));
      else if (cookie.expires())
        data.expires = new Date(cookie.expires()).toISOString();
      else
        data.expires = CookieTable.CookiesTable._expiresSessionValue;
    }
    data.size = cookie.size();
    const checkmark = '\u2713';
    data.httpOnly = (cookie.httpOnly() ? checkmark : '');
    data.secure = (cookie.secure() ? checkmark : '');
    data.sameSite = cookie.sameSite() || '';

    const node = new DataGrid.DataGridNode(data);
    node.cookie = cookie;
    node.selectable = true;
    return node;
  }

  /**
   * @param {!DataGrid.DataGridNode} node
   */
  _onDeleteCookie(node) {
    if (node.cookie && this._deleteCallback)
      this._deleteCallback(node.cookie, () => this._refresh());
  }

  /**
   * @param {!DataGrid.DataGridNode} editingNode
   * @param {string} columnIdentifier
   * @param {string} oldText
   * @param {string} newText
   */
  _onUpdateCookie(editingNode, columnIdentifier, oldText, newText) {
    this._lastEditedColumnId = columnIdentifier;
    this._setDefaults(editingNode);
    if (this._isValidCookieData(editingNode.data))
      this._saveNode(editingNode);
    else
      editingNode.setDirty(true);
  }

  /**
   * @param {!DataGrid.DataGridNode} node
   */
  _setDefaults(node) {
    if (node.data.name === null)
      node.data.name = '';
    if (node.data.value === null)
      node.data.value = '';
    if (node.data.domain === null)
      node.data.domain = this._cookieDomain;
    if (node.data.path === null)
      node.data.path = '/';
    if (node.data.expires === null)
      node.data.expires = CookieTable.CookiesTable._expiresSessionValue;
  }

  /**
   * @param {!DataGrid.DataGridNode} node
   */
  _saveNode(node) {
    const oldCookie = node.cookie;
    const newCookie = this._createCookieFromData(node.data);
    node.cookie = newCookie;
    this._saveCallback(newCookie, oldCookie).then(success => {
      if (success)
        this._refresh();
      else
        node.setDirty(true);
    });
  }

  /**
   * @param {!Object.<string, *>} data
   * @returns {!SDK.Cookie}
   */
  _createCookieFromData(data) {
    const cookie = new SDK.Cookie(data.name, data.value, null);
    cookie.addAttribute('domain', data.domain);
    cookie.addAttribute('path', data.path);
    if (data.expires && data.expires !== CookieTable.CookiesTable._expiresSessionValue)
      cookie.addAttribute('expires', (new Date(data.expires)).toUTCString());
    if (data.httpOnly)
      cookie.addAttribute('httpOnly');
    if (data.secure)
      cookie.addAttribute('secure');
    if (data.sameSite)
      cookie.addAttribute('sameSite', data.sameSite);
    cookie.setSize(data.name.length + data.value.length);
    return cookie;
  }

  /**
   * @param {!Object.<string, *>} data
   * @returns {boolean}
   */
  _isValidCookieData(data) {
    return (data.name || data.value) && this._isValidDomain(data.domain) && this._isValidPath(data.path) &&
        this._isValidDate(data.expires);
  }

  /**
   * @param {string} domain
   * @returns {boolean}
   */
  _isValidDomain(domain) {
    if (!domain)
      return true;
    const parsedURL = ('http://' + domain).asParsedURL();
    return !!parsedURL && parsedURL.domain() === domain;
  }

  /**
   * @param {string} path
   * @returns {boolean}
   */
  _isValidPath(path) {
    const parsedURL = ('http://example.com' + path).asParsedURL();
    return !!parsedURL && parsedURL.path === path;
  }

  /**
   * @param {string} date
   * @returns {boolean}
   */
  _isValidDate(date) {
    return date === '' || date === CookieTable.CookiesTable._expiresSessionValue || !isNaN(Date.parse(date));
  }

  _refresh() {
    if (this._refreshCallback)
      this._refreshCallback();
  }
};

/** @const */
CookieTable.CookiesTable._expiresSessionValue = Common.UIString('Session');
