/*
 * Copyright (C) 2013, 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.FilterBar = class FilterBar extends WI.Object
{
    constructor(element)
    {
        super();

        this._element = element || document.createElement("div");
        this._element.classList.add("filter-bar");

        this._filterFunctionsMap = new Map;

        this._inputField = document.createElement("input");
        this._inputField.type = "search";
        this._inputField.placeholder = WI.UIString("Filter");
        this._inputField.spellcheck = false;
        this._inputField.incremental = true;
        this._inputField.addEventListener("search", this._handleFilterChanged.bind(this));
        this._inputField.addEventListener("input", this._handleFilterInputEvent.bind(this));
        this._element.appendChild(this._inputField);

        this._filtersNavigationBar = new WI.NavigationBar;
        this._element.appendChild(this._filtersNavigationBar.element);

        this._lastFilterValue = this.filters;
    }

    // Public

    get element()
    {
        return this._element;
    }

    get inputField()
    {
        return this._inputField;
    }

    get placeholder()
    {
        return this._inputField.placeholder;
    }

    set placeholder(text)
    {
        this._inputField.placeholder = text;
    }

    get incremental()
    {
        return this._inputField.incremental;
    }

    set incremental(incremental)
    {
        this._inputField.incremental = incremental;
    }

    get filters()
    {
        return {text: this._inputField.value, functions: [...this._filterFunctionsMap.values()]};
    }

    set filters(filters)
    {
        filters = filters || {};

        var oldTextValue = this._inputField.value;
        this._inputField.value = filters.text || "";
        if (oldTextValue !== this._inputField.value)
            this._handleFilterChanged();
    }

    focus()
    {
        // FIXME: Workaround for: <https://webkit.org/b/149504> Caret missing from <input> after clearing text and calling select()
        if (!this._inputField.value.length)
            this._inputField.focus();
        else
            this._inputField.select();
    }

    clear()
    {
        this._filterFunctionsMap.clear();
        this.filters = null;

        // Only toggle the `WI.FilterBarButton`s after clearing the function map, as otherwise each
        // toggle will fire another WI.FilterBar.Event.FilterDidChange event.
        for (let navigationItem of this._filtersNavigationBar.navigationItems) {
            if (navigationItem instanceof WI.FilterBarButton)
                navigationItem.toggle(false);
        }

        this._inputField.value = null; // Get the placeholder to show again.
    }

    addFilterNavigationItem(navigationItem)
    {
        console.assert(navigationItem instanceof WI.NavigationItem);
        this._filtersNavigationBar.addNavigationItem(navigationItem);
    }

    addFilterBarButton(identifier, filterFunction, activatedByDefault, defaultToolTip, activatedToolTip, image, imageWidth, imageHeight)
    {
        var filterBarButton = new WI.FilterBarButton(identifier, filterFunction, activatedByDefault, defaultToolTip, activatedToolTip, image, imageWidth, imageHeight);
        filterBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleFilterBarButtonClicked, this);
        filterBarButton.addEventListener(WI.FilterBarButton.Event.ActivatedStateToggled, this._handleFilterButtonToggled, this);
        this.addFilterNavigationItem(filterBarButton);
        if (filterBarButton.activated) {
            this._filterFunctionsMap.set(filterBarButton.identifier, filterBarButton.filterFunction);
            this._handleFilterChanged();
        }
    }

    hasActiveFilters()
    {
        return !!this._inputField.value || !!this._filterFunctionsMap.size;
    }

    hasFilterChanged()
    {
        var currentFunctions = this.filters.functions;

        if (this._lastFilterValue.text !== this._inputField.value || this._lastFilterValue.functions.length !== currentFunctions.length)
            return true;

        for (var i = 0; i < currentFunctions.length; ++i) {
            if (this._lastFilterValue.functions[i] !== currentFunctions[i])
                return true;
        }

        return false;
    }

    // Private

    _handleFilterBarButtonClicked(event)
    {
        var filterBarButton = event.target;
        filterBarButton.toggle();
    }

    _handleFilterButtonToggled(event)
    {
        var filterBarButton = event.target;
        if (filterBarButton.activated)
            this._filterFunctionsMap.set(filterBarButton.identifier, filterBarButton.filterFunction);
        else
            this._filterFunctionsMap.delete(filterBarButton.identifier);
        this._handleFilterChanged();
    }

    _handleFilterChanged()
    {
        if (this.hasFilterChanged()) {
            this._lastFilterValue = this.filters;
            this.dispatchEventToListeners(WI.FilterBar.Event.FilterDidChange);
        } else if (!this._inputField.value)
            this._inputField.blur();
    }

    _handleFilterInputEvent(event)
    {
        // When not incremental we still want to detect if the field becomes empty.

        if (this.incremental)
            return;

        if (!this._inputField.value)
            this._handleFilterChanged();
    }
};

WI.FilterBar.Event = {
    FilterDidChange: "filter-bar-text-filter-did-change"
};
