/*
 * 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.scrollContainer.addEventListener("scroll", this._dataGridScrolled.bind(this));
        this.addSubview(this._dataGrid);

        this._entries = [];

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

        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._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];
    }

    // 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 = this._entries.concat(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.storageManager.requestIndexedDatabaseData(this._objectStore, this._objectStoreIndex, this._entries.length, 25, processEntries.bind(this));
    }

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

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