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

WI.IndexedDatabaseObjectStoreContentView = class IndexedDatabaseObjectStoreContentView extends WI.ContentView
{
    constructor(objectStoreOrIndex)
    {
        super(objectStoreOrIndex);

        this.element.classList.add("indexed-database-object-store");

        if (objectStoreOrIndex instanceof WI.IndexedDatabaseObjectStore) {
            this._objectStore = objectStoreOrIndex;
            this._objectStoreIndex = null;
        } else if (objectStoreOrIndex instanceof WI.IndexedDatabaseObjectStoreIndex) {
            this._objectStore = objectStoreOrIndex.parentObjectStore;
            this._objectStoreIndex = objectStoreOrIndex;
        }

        function displayKeyPath(keyPath)
        {
            if (!keyPath)
                return "";
            if (keyPath instanceof Array)
                return keyPath.join(WI.UIString(", "));
            console.assert(keyPath instanceof String || typeof keyPath === "string");
            return keyPath;
        }

        var displayPrimaryKeyPath = displayKeyPath(this._objectStore.keyPath);

        var columnInfo = {
            primaryKey: {title: displayPrimaryKeyPath ? WI.UIString("Primary Key \u2014 %s").format(displayPrimaryKeyPath) : WI.UIString("Primary Key")},
            key: {},
            value: {title: WI.UIString("Value")}
        };

        if (this._objectStoreIndex) {
            // When there is an index, show the key path in the Key column.
            var displayIndexKeyPath = displayKeyPath(this._objectStoreIndex.keyPath);
            columnInfo.key.title = WI.UIString("Index Key \u2014 %s").format(displayIndexKeyPath);
        } else {
            // Only need to show Key for indexes -- it is the same as Primary Key
            // when there is no index being used.
            delete columnInfo.key;
        }

        this._dataGrid = new WI.DataGrid(columnInfo);
        this._dataGrid.variableHeightRows = true;
        this._dataGrid.filterDelegate = this;
        this._dataGrid.scrollContainer.addEventListener("scroll", this._dataGridScrolled.bind(this));
        this.addSubview(this._dataGrid);

        this._entries = [];

        this._fetchingMoreData = false;
        this._fetchMoreData();

        this._filterBarNavigationItem = new WI.FilterBarNavigationItem;
        this._filterBarNavigationItem.filterBar.addEventListener(WI.FilterBar.Event.FilterDidChange, this._handleFilterBarFilterDidChange, this);

        this._refreshButtonNavigationItem = new WI.ButtonNavigationItem("indexed-database-object-store-refresh", WI.UIString("Refresh"), "Images/ReloadFull.svg", 13, 13);
        this._refreshButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._refreshButtonClicked, this);

        this._clearButtonNavigationItem = new WI.ButtonNavigationItem("indexed-database-object-store-clear", WI.UIString("Clear object store"), "Images/NavigationItemTrash.svg", 15, 15);
        this._clearButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        this._clearButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._clearButtonClicked, this);
    }

    // Public

    get navigationItems()
    {
        return [
            this._filterBarNavigationItem,
            new WI.DividerNavigationItem,
            this._refreshButtonNavigationItem,
            this._clearButtonNavigationItem,
        ];
    }

    closed()
    {
        super.closed();

        this._reset();
    }

    saveToCookie(cookie)
    {
        cookie.type = WI.ContentViewCookieType.IndexedDatabaseObjectStore;
        cookie.securityOrigin = this._objectStore.parentDatabase.securityOrigin;
        cookie.databaseName = this._objectStore.parentDatabase.name;
        cookie.objectStoreName = this._objectStore.name;
        cookie.objectStoreIndexName = this._objectStoreIndex && this._objectStoreIndex.name;
    }

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

    get canFocusFilterBar()
    {
        return true;
    }

    focusFilterBar()
    {
        this._filterBarNavigationItem.filterBar.focus();
    }

    // Protected

    dataGridMatchNodeAgainstCustomFilters(node)
    {
        let filterText = this._filterBarNavigationItem.filterBar.filters.text;
        if (!filterText)
            return true;

        let regex = WI.SearchUtilities.regExpForString(filterText, WI.SearchUtilities.defaultSettings);

        // Iterate over each cell.
        for (let child of node.element.children) {
            if (regex.test(child.textContent))
                return true;
        }

        return false;
    }

    // Private

    _reset()
    {
        for (var entry of this._entries) {
            entry.primaryKey.release();
            entry.key.release();
            entry.value.release();
        }

        this._entries = [];
        this._dataGrid.removeChildren();
    }

    _dataGridScrolled()
    {
        if (!this._moreEntriesAvailable || !this._dataGrid.isScrolledToLastRow())
            return;

        this._fetchMoreData();
    }

    _fetchMoreData()
    {
        if (this._fetchingMoreData)
            return;

        function processEntries(entries, moreAvailable)
        {
            this._entries.pushAll(entries);
            this._moreEntriesAvailable = moreAvailable;

            for (var entry of entries) {
                var dataGridNode = new WI.IndexedDatabaseEntryDataGridNode(entry);
                this._dataGrid.appendChild(dataGridNode);
            }

            this._fetchingMoreData = false;

            if (moreAvailable && this._dataGrid.isScrolledToLastRow())
                this._fetchMoreData();
        }

        this._fetchingMoreData = true;

        WI.indexedDBManager.requestIndexedDatabaseData(this._objectStore, this._objectStoreIndex, this._entries.length, 25, processEntries.bind(this));
    }

    _handleFilterBarFilterDidChange(event)
    {
        this._dataGrid.filterDidChange();
    }

    _refreshButtonClicked()
    {
        this._reset();
        this._fetchMoreData();
    }

    _clearButtonClicked()
    {
        WI.indexedDBManager.clearObjectStore(this._objectStore);
        this._reset();
    }
};
