/*
 * 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.FindBanner = class FindBanner extends WI.NavigationItem
{
    constructor(delegate, className, fixed = false)
    {
        super();

        this._delegate = delegate || null;

        this.element.classList.add("find-banner");

        if (className)
            this.element.classList.add(className);

        this._resultCountLabel = document.createElement("label");
        this.element.appendChild(this._resultCountLabel);

        this._inputField = document.createElement("input");
        this._inputField.type = "search";
        this._inputField.spellcheck = false;
        this._inputField.incremental = true;
        this._inputField.setAttribute("results", 5);
        this._inputField.setAttribute("autosave", "inspector-search");
        this._inputField.addEventListener("keydown", this._inputFieldKeyDown.bind(this), false);
        this._inputField.addEventListener("keyup", this._inputFieldKeyUp.bind(this), false);
        this._inputField.addEventListener("search", this._inputFieldSearch.bind(this), false);
        this.element.appendChild(this._inputField);

        this._previousResultButton = document.createElement("button");
        this._previousResultButton.classList.add("segmented", "previous-result");
        this._previousResultButton.disabled = true;
        this._previousResultButton.title = WI.UIString("Find Previous (%s)").format(WI.findPreviousKeyboardShortcut.displayName);
        this._previousResultButton.addEventListener("click", this._previousResultButtonClicked.bind(this));
        this.element.appendChild(this._previousResultButton);

        let previousResultButtonGlyphElement = document.createElement("div");
        previousResultButtonGlyphElement.classList.add(WI.FindBanner.SegmentGlyphStyleClassName);
        this._previousResultButton.appendChild(previousResultButtonGlyphElement);

        this._nextResultButton = document.createElement("button");
        this._nextResultButton.classList.add("segmented", "next-result");
        this._nextResultButton.disabled = true;
        this._nextResultButton.title = WI.UIString("Find Next (%s)").format(WI.findNextKeyboardShortcut.displayName);
        this._nextResultButton.addEventListener("click", this._nextResultButtonClicked.bind(this));
        this.element.appendChild(this._nextResultButton);

        let nextResultButtonGlyphElement = document.createElement("div");
        nextResultButtonGlyphElement.classList.add(WI.FindBanner.SegmentGlyphStyleClassName);
        this._nextResultButton.appendChild(nextResultButtonGlyphElement);

        if (fixed)
            this._clearAndBlurKeyboardShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Escape, this._clearAndBlur.bind(this), this.element);
        else {
            let doneButtonElement = document.createElement("button");
            doneButtonElement.textContent = WI.UIString("Done");
            doneButtonElement.addEventListener("click", this._doneButtonClicked.bind(this));
            this.element.appendChild(doneButtonElement);
            this._hideKeyboardShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Escape, this.hide.bind(this), this.element);
        }

        this._numberOfResults = null;
        this._searchBackwards = false;
        this._searchKeyPressed = false;
        this._previousSearchValue = "";
    }

    // Public

    get delegate() { return this._delegate; }
    set delegate(newDelegate) { this._delegate = newDelegate || null; }
    get inputField() { return this._inputField; }
    get searchQuery() { return this._inputField.value || ""; }
    set searchQuery(query) { this._inputField.value = query || ""; }
    get numberOfResults() { return this._numberOfResults; }

    set numberOfResults(numberOfResults)
    {
        if (numberOfResults === undefined || isNaN(numberOfResults))
            numberOfResults = null;

        this._numberOfResults = numberOfResults;

        this._previousResultButton.disabled = this._nextResultButton.disabled = numberOfResults <= 0;

        if (numberOfResults === null)
            this._resultCountLabel.textContent = "";
        else if (numberOfResults <= 0)
            this._resultCountLabel.textContent = WI.UIString("Not found");
        else if (numberOfResults === 1)
            this._resultCountLabel.textContent = WI.UIString("1 match");
        else if (numberOfResults > 1)
            this._resultCountLabel.textContent = WI.UIString("%d matches").format(numberOfResults);
    }

    get targetElement()
    {
        return this._targetElement;
    }

    set targetElement(element)
    {
        function delayedWork()
        {
            oldTargetElement.classList.remove(WI.FindBanner.NoTransitionStyleClassName);
            this.element.classList.remove(WI.FindBanner.NoTransitionStyleClassName);
        }

        if (this._targetElement) {
            var oldTargetElement = this._targetElement;

            this._targetElement.classList.add(WI.FindBanner.NoTransitionStyleClassName);
            this._targetElement.classList.remove(WI.FindBanner.SupportsFindBannerStyleClassName);
            this._targetElement.classList.remove(WI.FindBanner.ShowingFindBannerStyleClassName);

            this.element.classList.add(WI.FindBanner.NoTransitionStyleClassName);
            this.element.classList.remove(WI.FindBanner.ShowingStyleClassName);

            // Delay so we can remove the no transition style class after the other style changes are committed.
            setTimeout(delayedWork.bind(this), 0);
        }

        this._targetElement = element || null;

        if (this._targetElement)
            this._targetElement.classList.add(WI.FindBanner.SupportsFindBannerStyleClassName);
    }

    get showing()
    {
        return this.element.classList.contains(WI.FindBanner.ShowingStyleClassName);
    }

    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();
    }

    _clearAndBlur()
    {
        this.numberOfResults = null;

        this._inputField.value = "";
        this._previousSearchValue = "";

        if (this._delegate.findBannerSearchCleared)
            this._delegate.findBannerSearchCleared();
        if (this._delegate.findBannerWantsToClearAndBlur)
            this._delegate.findBannerWantsToClearAndBlur();
    }

    show()
    {
        console.assert(this._targetElement);
        if (!this._targetElement)
            return;

        console.assert(this._targetElement.parentNode);
        if (!this._targetElement.parentNode)
            return;

        if (this.element.parentNode !== this._targetElement.parentNode)
            this._targetElement.parentNode.insertBefore(this.element, this._targetElement);

        function delayedWork()
        {
            this._targetElement.classList.add(WI.FindBanner.ShowingFindBannerStyleClassName);
            this.element.classList.add(WI.FindBanner.ShowingStyleClassName);

            this._inputField.select();
        }

        // Delay adding the classes in case the target element and/or the find banner were just added to
        // the document. Adding the class right away will prevent the animation from working the first time.
        setTimeout(delayedWork.bind(this), 0);

        this.dispatchEventToListeners(WI.FindBanner.Event.DidShow);
    }

    hide()
    {
        console.assert(this._targetElement);
        if (!this._targetElement)
            return;

        this._inputField.blur();

        this._targetElement.classList.remove(WI.FindBanner.ShowingFindBannerStyleClassName);
        this.element.classList.remove(WI.FindBanner.ShowingStyleClassName);

        this.dispatchEventToListeners(WI.FindBanner.Event.DidHide);
    }

    // Private

    _inputFieldKeyDown(event)
    {
        if (event.keyIdentifier === "Shift")
            this._searchBackwards = true;
        else if (event.keyIdentifier === "Enter")
            this._searchKeyPressed = true;
    }

    _inputFieldKeyUp(event)
    {
        if (event.keyIdentifier === "Shift")
            this._searchBackwards = false;
        else if (event.keyIdentifier === "Enter")
            this._searchKeyPressed = false;
    }

    _inputFieldSearch(event)
    {
        if (this._inputField.value) {
            if (this._previousSearchValue !== this.searchQuery) {
                if (this._delegate && typeof this._delegate.findBannerPerformSearch === "function")
                    this._delegate.findBannerPerformSearch(this, this.searchQuery);
            } else if (this._searchKeyPressed && this._numberOfResults > 0) {
                if (this._searchBackwards) {
                    if (this._delegate && typeof this._delegate.findBannerRevealPreviousResult === "function")
                        this._delegate.findBannerRevealPreviousResult(this);
                } else {
                    if (this._delegate && typeof this._delegate.findBannerRevealNextResult === "function")
                        this._delegate.findBannerRevealNextResult(this);
                }
            }
        } else {
            this.numberOfResults = null;
            if (this._delegate && typeof this._delegate.findBannerSearchCleared === "function")
                this._delegate.findBannerSearchCleared(this);
        }

        this._previousSearchValue = this.searchQuery;
    }

    _previousResultButtonClicked(event)
    {
        if (this._delegate && typeof this._delegate.findBannerRevealPreviousResult === "function")
            this._delegate.findBannerRevealPreviousResult(this);
    }

    _nextResultButtonClicked(event)
    {
        if (this._delegate && typeof this._delegate.findBannerRevealNextResult === "function")
            this._delegate.findBannerRevealNextResult(this);
    }

    _doneButtonClicked(event)
    {
        this.hide();
    }
};

WI.FindBanner.SupportsFindBannerStyleClassName = "supports-find-banner";
WI.FindBanner.ShowingFindBannerStyleClassName = "showing-find-banner";
WI.FindBanner.NoTransitionStyleClassName = "no-find-banner-transition";
WI.FindBanner.ShowingStyleClassName = "showing";
WI.FindBanner.SegmentGlyphStyleClassName = "glyph";

WI.FindBanner.Event = {
    DidShow: "find-banner-did-show",
    DidHide: "find-banner-did-hide"
};
