/*
 * Copyright (C) 2011 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

#include "config.h"
#include "AutofillPopupMenuClient.h"

#include "CSSValueKeywords.h"
#include "WebAutofillClient.h"
#include "WebNode.h"
#include "WebViewClient.h"
#include "WebViewImpl.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/html/HTMLInputElement.h"
#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
#include "core/rendering/RenderTheme.h"
#include "public/platform/WebString.h"
#include "public/platform/WebVector.h"

using namespace WebCore;

namespace blink {

AutofillPopupMenuClient::AutofillPopupMenuClient()
    : m_selectedIndex(-1)
    , m_textField(0)
    , m_useLegacyBehavior(false)
{
}

AutofillPopupMenuClient::~AutofillPopupMenuClient()
{
}

unsigned AutofillPopupMenuClient::getSuggestionsCount() const
{
    return m_names.size();
}

WebString AutofillPopupMenuClient::getSuggestion(unsigned listIndex) const
{
    ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());
    return m_names[listIndex];
}

WebString AutofillPopupMenuClient::getLabel(unsigned listIndex) const
{
    ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_labels.size());
    return m_labels[listIndex];
}

WebString AutofillPopupMenuClient::getIcon(unsigned listIndex) const
{
    ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_icons.size());
    return m_icons[listIndex];
}

void AutofillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex)
{
    if (!canRemoveSuggestionAtIndex(listIndex))
        return;

    ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());

    m_names.remove(listIndex);
    m_labels.remove(listIndex);
    m_icons.remove(listIndex);
    m_itemIDs.remove(listIndex);
}

bool AutofillPopupMenuClient::canRemoveSuggestionAtIndex(unsigned listIndex)
{
    return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDAutocompleteEntry || m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDPasswordEntry;
}

void AutofillPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents)
{
    WebViewImpl* webView = getWebView();
    if (!webView)
        return;

    ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());

    if (m_useLegacyBehavior) {
        for (size_t i = 0; i < m_itemIDs.size(); ++i) {
            if (m_itemIDs[i] == WebAutofillClient::MenuItemIDSeparator) {
                if (listIndex > i)
                    listIndex--;
                break;
            }
        }
    }

    webView->autofillClient()->didAcceptAutofillSuggestion(WebNode(getTextField()),
                                                           m_names[listIndex],
                                                           m_labels[listIndex],
                                                           m_itemIDs[listIndex],
                                                           listIndex);
}

void AutofillPopupMenuClient::selectionChanged(unsigned listIndex, bool fireEvents)
{
    WebViewImpl* webView = getWebView();
    if (!webView)
        return;

    ASSERT_WITH_SECURITY_IMPLICATION(listIndex < m_names.size());

    webView->autofillClient()->didSelectAutofillSuggestion(WebNode(getTextField()),
                                                           m_names[listIndex],
                                                           m_labels[listIndex],
                                                           m_itemIDs[listIndex]);
}

void AutofillPopupMenuClient::selectionCleared()
{
    WebViewImpl* webView = getWebView();
    if (webView)
        webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()));
}

String AutofillPopupMenuClient::itemText(unsigned listIndex) const
{
    return getSuggestion(listIndex);
}

String AutofillPopupMenuClient::itemLabel(unsigned listIndex) const
{
    return getLabel(listIndex);
}

String AutofillPopupMenuClient::itemIcon(unsigned listIndex) const
{
    return getIcon(listIndex);
}

bool AutofillPopupMenuClient::itemIsEnabled(unsigned listIndex) const
{
    return !itemIsWarning(listIndex);
}

PopupMenuStyle AutofillPopupMenuClient::itemStyle(unsigned listIndex) const
{
    return itemIsWarning(listIndex) ? *m_warningStyle : *m_regularStyle;
}

PopupMenuStyle AutofillPopupMenuClient::menuStyle() const
{
    return *m_regularStyle;
}

WebCore::LayoutUnit AutofillPopupMenuClient::clientPaddingLeft() const
{
    // Bug http://crbug.com/7708 seems to indicate the style can be 0.
    RenderStyle* style = textFieldStyle();
    if (!style)
       return 0;

    return RenderTheme::theme().popupInternalPaddingLeft(style);
}

WebCore::LayoutUnit AutofillPopupMenuClient::clientPaddingRight() const
{
    // Bug http://crbug.com/7708 seems to indicate the style can be 0.
    RenderStyle* style = textFieldStyle();
    if (!style)
        return 0;

    return RenderTheme::theme().popupInternalPaddingRight(style);
}

void AutofillPopupMenuClient::popupDidHide()
{
    WebViewImpl* webView = getWebView();
    if (!webView)
        return;

    webView->autofillPopupDidHide();
    webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()));
}

bool AutofillPopupMenuClient::itemIsSeparator(unsigned listIndex) const
{
    return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDSeparator;
}

bool AutofillPopupMenuClient::itemIsWarning(unsigned listIndex) const
{
    return m_itemIDs[listIndex] == WebAutofillClient::MenuItemIDWarningMessage;
}

void AutofillPopupMenuClient::setTextFromItem(unsigned listIndex)
{
    m_textField->setValue(getSuggestion(listIndex));
}

FontSelector* AutofillPopupMenuClient::fontSelector() const
{
    return m_textField->document().styleEngine()->fontSelector();
}

HostWindow* AutofillPopupMenuClient::hostWindow() const
{
    return m_textField->document().view()->hostWindow();
}

PassRefPtr<Scrollbar> AutofillPopupMenuClient::createScrollbar(
    ScrollableArea* scrollableArea,
    ScrollbarOrientation orientation,
    ScrollbarControlSize size)
{
    return Scrollbar::create(scrollableArea, orientation, size);
}

void AutofillPopupMenuClient::initialize(
    HTMLInputElement* textField,
    const WebVector<WebString>& names,
    const WebVector<WebString>& labels,
    const WebVector<WebString>& icons,
    const WebVector<int>& itemIDs,
    int separatorIndex)
{
    ASSERT(names.size() == labels.size());
    ASSERT(names.size() == icons.size());
    ASSERT(names.size() == itemIDs.size());

    m_selectedIndex = -1;
    m_textField = textField;

    if (separatorIndex == -1) {
        // The suggestions must be set before initializing the
        // AutofillPopupMenuClient.
        setSuggestions(names, labels, icons, itemIDs);
    } else {
        m_useLegacyBehavior = true;
        WebVector<WebString> namesWithSeparator(names.size() + 1);
        WebVector<WebString> labelsWithSeparator(labels.size() + 1);
        WebVector<WebString> iconsWithSeparator(icons.size() + 1);
        WebVector<int> itemIDsWithSeparator(itemIDs.size() + 1);
        for (size_t i = 0; i < names.size(); ++i) {
            size_t j = i < static_cast<size_t>(separatorIndex) ? i : i + 1;
            namesWithSeparator[j] = names[i];
            labelsWithSeparator[j] = labels[i];
            iconsWithSeparator[j] = icons[i];
            itemIDsWithSeparator[j] = itemIDs[i];
        }
        itemIDsWithSeparator[separatorIndex] = WebAutofillClient::MenuItemIDSeparator;
        setSuggestions(namesWithSeparator, labelsWithSeparator, iconsWithSeparator, itemIDsWithSeparator);
    }

    FontDescription regularFontDescription;
    RenderTheme::theme().systemFont(CSSValueWebkitControl,
                                            regularFontDescription);
    RenderStyle* style = m_textField->computedStyle();
    regularFontDescription.setComputedSize(style->fontDescription().computedSize());

    Font regularFont(regularFontDescription, 0, 0);
    regularFont.update(textField->document().styleEngine()->fontSelector());
    // The direction of text in popup menu is set the same as the direction of
    // the input element: textField.
    m_regularStyle = adoptPtr(new PopupMenuStyle(Color::black, Color::white, regularFont, true, false,
        Length(WebCore::Fixed), textField->renderer()->style()->direction(),
        textField->renderer()->style()->unicodeBidi() == Override,
        PopupMenuStyle::CustomBackgroundColor, PopupMenuStyle::AutofillPopup));

    FontDescription warningFontDescription = regularFont.fontDescription();
    warningFontDescription.setItalic(true);
    Font warningFont(warningFontDescription, regularFont.letterSpacing(), regularFont.wordSpacing());
    warningFont.update(regularFont.fontSelector());
    m_warningStyle = adoptPtr(new PopupMenuStyle(Color::darkGray, m_regularStyle->backgroundColor(), warningFont,
        m_regularStyle->isVisible(), m_regularStyle->isDisplayNone(),
        m_regularStyle->textIndent(), m_regularStyle->textDirection(),
        m_regularStyle->hasTextDirectionOverride(),
        PopupMenuStyle::CustomBackgroundColor, PopupMenuStyle::AutofillPopup));
}

void AutofillPopupMenuClient::setSuggestions(const WebVector<WebString>& names,
                                             const WebVector<WebString>& labels,
                                             const WebVector<WebString>& icons,
                                             const WebVector<int>& itemIDs)
{
    ASSERT(names.size() == labels.size());
    ASSERT(names.size() == icons.size());
    ASSERT(names.size() == itemIDs.size());

    m_names.clear();
    m_labels.clear();
    m_icons.clear();
    m_itemIDs.clear();
    for (size_t i = 0; i < names.size(); ++i) {
        m_names.append(names[i]);
        m_labels.append(labels[i]);
        m_icons.append(icons[i]);
        m_itemIDs.append(itemIDs[i]);
    }

    // Try to preserve selection if possible.
    if (getSelectedIndex() >= static_cast<int>(names.size()))
        setSelectedIndex(-1);
}

WebViewImpl* AutofillPopupMenuClient::getWebView() const
{
    return WebViewImpl::fromPage(m_textField->document().page());
}

RenderStyle* AutofillPopupMenuClient::textFieldStyle() const
{
    RenderStyle* style = m_textField->computedStyle();
    if (!style) {
        // It seems we can only have a 0 style in a TextField if the
        // node is detached, in which case we the popup should not be
        // showing.  Please report this in http://crbug.com/7708 and
        // include the page you were visiting.
        ASSERT_NOT_REACHED();
    }
    return style;
}

} // namespace blink
