/*
 * 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.placeholder = " "; // This is necessary for :placeholder-shown.
        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"
};
