/*
 * Copyright (C) 2013-2015 Apple 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 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.
 */

WI.DOMStorageContentView = class DOMStorageContentView extends WI.ContentView
{
    constructor(representedObject)
    {
        super(representedObject);

        this.element.classList.add("dom-storage");

        representedObject.addEventListener(WI.DOMStorageObject.Event.ItemsCleared, this.itemsCleared, this);
        representedObject.addEventListener(WI.DOMStorageObject.Event.ItemAdded, this.itemAdded, this);
        representedObject.addEventListener(WI.DOMStorageObject.Event.ItemRemoved, this.itemRemoved, this);
        representedObject.addEventListener(WI.DOMStorageObject.Event.ItemUpdated, this.itemUpdated, this);

        let columns = {};
        columns.key = {title: WI.UIString("Key"), sortable: true};
        columns.value = {title: WI.UIString("Value"), sortable: true};

        this._dataGrid = new WI.DataGrid(columns, {
            editCallback: this._editingCallback.bind(this),
            copyCallback: this._dataGridCopy.bind(this),
            deleteCallback: this._deleteCallback.bind(this),
        });
        this._dataGrid.sortOrder = WI.DataGrid.SortOrder.Ascending;
        this._dataGrid.sortColumnIdentifier = "key";
        this._dataGrid.createSettings("dom-storage-content-view");
        this._dataGrid.addEventListener(WI.DataGrid.Event.SortChanged, this._sortDataGrid, this);

        this.addSubview(this._dataGrid);

        this._populate();
    }

    // Public

    saveToCookie(cookie)
    {
        cookie.type = WI.ContentViewCookieType.DOMStorage;
        cookie.isLocalStorage = this.representedObject.isLocalStorage();
        cookie.host = this.representedObject.host;
    }

    get scrollableElements()
    {
        return [this._dataGrid.scrollContainer];
    }

    itemsCleared(event)
    {
        this._dataGrid.removeChildren();
        this._dataGrid.addPlaceholderNode();
    }

    itemRemoved(event)
    {
        for (let node of this._dataGrid.children) {
            if (node.data.key === event.data.key)
                return this._dataGrid.removeChild(node);
        }

        return null;
    }

    itemAdded(event)
    {
        let {key, value} = event.data;
        let originalValue = value;
        value = this._truncateValue(value);

        // Enforce key uniqueness.
        for (let node of this._dataGrid.children) {
            if (node.data.key === key)
                return;
        }

        this._dataGrid.appendChild(new WI.DataGridNode({key, value, originalValue}, false));
        this._sortDataGrid();
    }

    itemUpdated(event)
    {
        let {key, value} = event.data;
        let originalValue = value;
        value = this._truncateValue(value);

        let keyFound = false;
        for (let childNode of this._dataGrid.children) {
            if (childNode.data.key === key) {
                // Remove any rows that are now duplicates.
                if (keyFound) {
                    this._dataGrid.removeChild(childNode);
                    continue;
                }

                keyFound = true;
                childNode.data.value = value;
                childNode.data.originalValue = originalValue;
                childNode.refresh();
            }
        }
        this._sortDataGrid();
    }

    // Private

    _truncateValue(value)
    {
        return value.truncate(200);
    }

    _populate()
    {
        this.representedObject.getEntries(function(error, entries) {
            if (error)
                return;

            for (let [key, value] of entries) {
                if (!key || !value)
                    continue;

                let originalValue = value;
                value = this._truncateValue(value);
                let node = new WI.DataGridNode({key, value, originalValue}, false);
                this._dataGrid.appendChild(node);
            }

            this._sortDataGrid();
            this._dataGrid.addPlaceholderNode();
            this._dataGrid.updateLayout();
        }.bind(this));
    }

    _sortDataGrid()
    {
        let sortColumnIdentifier = this._dataGrid.sortColumnIdentifier || "key";

        function comparator(a, b)
        {
            return a.data[sortColumnIdentifier].extendedLocaleCompare(b.data[sortColumnIdentifier]);
        }

        this._dataGrid.sortNodesImmediately(comparator);
    }

    _deleteCallback(node)
    {
        if (!node || node.isPlaceholderNode)
            return;

        this._dataGrid.removeChild(node);
        this.representedObject.removeItem(node.data["key"]);
    }

    _editingCallback(editingNode, columnIdentifier, oldText, newText, moveDirection)
    {
        var key = editingNode.data["key"].trim().removeWordBreakCharacters();
        var value = editingNode.data["value"].trim().removeWordBreakCharacters();
        var previousValue = oldText.trim().removeWordBreakCharacters();
        var enteredValue = newText.trim().removeWordBreakCharacters();
        var hasUncommittedEdits = editingNode.__hasUncommittedEdits;
        var hasChange = previousValue !== enteredValue;
        var isEditingKey = columnIdentifier === "key";
        var isEditingValue = !isEditingKey;
        var domStorage = this.representedObject;

        // Nothing changed, just bail.
        if (!hasChange && !hasUncommittedEdits)
            return;

        // Something changed, save the original key/value and enter uncommitted state.
        if (hasChange && !editingNode.__hasUncommittedEdits) {
            editingNode.__hasUncommittedEdits = true;
            editingNode.__originalKey = isEditingKey ? previousValue : key;
            editingNode.__originalValue = isEditingValue ? previousValue : value;
        }

        function cleanup()
        {
            editingNode.element.classList.remove(WI.DOMStorageContentView.MissingKeyStyleClassName);
            editingNode.element.classList.remove(WI.DOMStorageContentView.MissingValueStyleClassName);
            editingNode.element.classList.remove(WI.DOMStorageContentView.DuplicateKeyStyleClassName);
            editingNode.__hasUncommittedEdits = undefined;
            editingNode.__originalKey = undefined;
            editingNode.__originalValue = undefined;
        }

        // If the key/value field was cleared, add "missing" style.
        if (isEditingKey) {
            if (key.length)
                editingNode.element.classList.remove(WI.DOMStorageContentView.MissingKeyStyleClassName);
            else
                editingNode.element.classList.add(WI.DOMStorageContentView.MissingKeyStyleClassName);
        } else if (isEditingValue) {
            if (value.length)
                editingNode.element.classList.remove(WI.DOMStorageContentView.MissingValueStyleClassName);
            else
                editingNode.element.classList.add(WI.DOMStorageContentView.MissingValueStyleClassName);
        }

        // Check for key duplicates. If this is a new row, or an existing row that changed key.
        var keyChanged = key !== editingNode.__originalKey;
        if (keyChanged) {
            if (domStorage.entries.has(key))
                editingNode.element.classList.add(WI.DOMStorageContentView.DuplicateKeyStyleClassName);
            else
                editingNode.element.classList.remove(WI.DOMStorageContentView.DuplicateKeyStyleClassName);
        }

        // See if we are done editing this row or not.
        var columnIndex = this._dataGrid.orderedColumns.indexOf(columnIdentifier);
        var mayMoveToNextRow = moveDirection === "forward" && columnIndex === this._dataGrid.orderedColumns.length - 1;
        var mayMoveToPreviousRow = moveDirection === "backward" && columnIndex === 0;
        var doneEditing = mayMoveToNextRow || mayMoveToPreviousRow || !moveDirection;

        // Expecting more edits on this row.
        if (!doneEditing)
            return;

        // Key and value were cleared, remove the row.
        if (!key.length && !value.length && !editingNode.isPlaceholderNode) {
            this._dataGrid.removeChild(editingNode);
            domStorage.removeItem(editingNode.__originalKey);
            return;
        }

        // Done editing but leaving the row in an invalid state. Leave in uncommitted state.
        var isDuplicate = editingNode.element.classList.contains(WI.DOMStorageContentView.DuplicateKeyStyleClassName);
        if (!key.length || !value.length || isDuplicate)
            return;

        // Commit.
        if (keyChanged && !editingNode.isPlaceholderNode)
            domStorage.removeItem(editingNode.__originalKey);
        if (editingNode.isPlaceholderNode)
            this._dataGrid.addPlaceholderNode();
        cleanup();
        domStorage.setItem(key, value);
    }

    _dataGridCopy(node, columnIdentifier, text)
    {
        if (columnIdentifier === "value" && node.data.originalValue)
            return node.data.originalValue;
        return text;
    }
};

WI.DOMStorageContentView.DuplicateKeyStyleClassName = "duplicate-key";
WI.DOMStorageContentView.MissingKeyStyleClassName = "missing-key";
WI.DOMStorageContentView.MissingValueStyleClassName = "missing-value";
