/*
 * Copyright (C) 2009 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 "WebSearchableFormData.h"

#include "HTMLNames.h"
#include "WebFormElement.h"
#include "WebInputElement.h"
#include "core/dom/Document.h"
#include "core/html/FormDataList.h"
#include "core/html/HTMLFormControlElement.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/html/HTMLSelectElement.h"
#include "platform/network/FormDataBuilder.h"
#include "wtf/text/TextEncoding.h"

using namespace WebCore;
using namespace HTMLNames;

namespace {

// Gets the encoding for the form.
void GetFormEncoding(const HTMLFormElement* form, WTF::TextEncoding* encoding)
{
    String str(form->getAttribute(HTMLNames::accept_charsetAttr));
    str.replace(',', ' ');
    Vector<String> charsets;
    str.split(' ', charsets);
    for (Vector<String>::const_iterator i(charsets.begin()); i != charsets.end(); ++i) {
        *encoding = WTF::TextEncoding(*i);
        if (encoding->isValid())
            return;
    }
    if (!form->document().loader())
         return;
    *encoding = WTF::TextEncoding(form->document().encoding());
}

// Returns true if the submit request results in an HTTP URL.
bool IsHTTPFormSubmit(const HTMLFormElement* form)
{
    // FIXME: This function is insane. This is an overly complicated way to get this information.
    String action(form->action());
    // The isNull() check is trying to avoid completeURL returning KURL() when passed a null string.
    return form->document().completeURL(action.isNull() ? "" : action).protocolIs("http");
}

// If the form does not have an activated submit button, the first submit
// button is returned.
HTMLFormControlElement* GetButtonToActivate(HTMLFormElement* form)
{
    HTMLFormControlElement* firstSubmitButton = 0;
    const Vector<FormAssociatedElement*>& element = form->associatedElements();
    for (Vector<FormAssociatedElement*>::const_iterator i(element.begin()); i != element.end(); ++i) {
        if (!(*i)->isFormControlElement())
            continue;
        HTMLFormControlElement* control = toHTMLFormControlElement(*i);
        if (control->isActivatedSubmit()) {
            // There's a button that is already activated for submit, return 0.
            return 0;
        }
        if (!firstSubmitButton && control->isSuccessfulSubmitButton())
            firstSubmitButton = control;
    }
    return firstSubmitButton;
}

// Returns true if the selected state of all the options matches the default
// selected state.
bool IsSelectInDefaultState(HTMLSelectElement* select)
{
    const Vector<HTMLElement*>& listItems = select->listItems();
    if (select->multiple() || select->size() > 1) {
        for (Vector<HTMLElement*>::const_iterator i(listItems.begin()); i != listItems.end(); ++i) {
            if (!(*i)->hasLocalName(HTMLNames::optionTag))
                continue;
            HTMLOptionElement* optionElement = toHTMLOptionElement(*i);
            if (optionElement->selected() != optionElement->hasAttribute(selectedAttr))
                return false;
        }
        return true;
    }

    // The select is rendered as a combobox (called menulist in WebKit). At
    // least one item is selected, determine which one.
    HTMLOptionElement* initialSelected = 0;
    for (Vector<HTMLElement*>::const_iterator i(listItems.begin()); i != listItems.end(); ++i) {
        if (!(*i)->hasLocalName(HTMLNames::optionTag))
            continue;
        HTMLOptionElement* optionElement = toHTMLOptionElement(*i);
        if (optionElement->hasAttribute(selectedAttr)) {
            // The page specified the option to select.
            initialSelected = optionElement;
            break;
        }
        if (!initialSelected)
            initialSelected = optionElement;
    }
    return !initialSelected || initialSelected->selected();
}

// Returns true if the form element is in its default state, false otherwise.
// The default state is the state of the form element on initial load of the
// page, and varies depending upon the form element. For example, a checkbox is
// in its default state if the checked state matches the state of the checked attribute.
bool IsInDefaultState(HTMLFormControlElement* formElement)
{
    ASSERT(formElement);
    if (isHTMLInputElement(*formElement)) {
        const HTMLInputElement& inputElement = toHTMLInputElement(*formElement);
        if (inputElement.isCheckbox() || inputElement.isRadioButton())
            return inputElement.checked() == inputElement.hasAttribute(checkedAttr);
    } else if (isHTMLSelectElement(*formElement)) {
        return IsSelectInDefaultState(toHTMLSelectElement(formElement));
    }
    return true;
}

// Look for a suitable search text field in a given HTMLFormElement
// Return nothing if one of those items are found:
//  - A text area field
//  - A file upload field
//  - A Password field
//  - More than one text field
HTMLInputElement* findSuitableSearchInputElement(const HTMLFormElement* form)
{
    HTMLInputElement* textElement = 0;
    const Vector<FormAssociatedElement*>& element = form->associatedElements();
    for (Vector<FormAssociatedElement*>::const_iterator i(element.begin()); i != element.end(); ++i) {
        if (!(*i)->isFormControlElement())
            continue;

        HTMLFormControlElement* control = toHTMLFormControlElement(*i);

        if (control->isDisabledFormControl() || control->name().isNull())
            continue;

        if (!IsInDefaultState(control) || isHTMLTextAreaElement(*control))
            return 0;

        if (isHTMLInputElement(*control) && control->willValidate()) {
            const HTMLInputElement& input = toHTMLInputElement(*control);

            // Return nothing if a file upload field or a password field are found.
            if (input.isFileUpload() || input.isPasswordField())
                return 0;

            if (input.isTextField()) {
                if (textElement) {
                    // The auto-complete bar only knows how to fill in one value.
                    // This form has multiple fields; don't treat it as searchable.
                    return 0;
                }
                textElement = toHTMLInputElement(control);
            }
        }
    }
    return textElement;
}

// Build a search string based on a given HTMLFormElement and HTMLInputElement
//
// Search string output example from www.google.com:
// "hl=en&source=hp&biw=1085&bih=854&q={searchTerms}&btnG=Google+Search&aq=f&aqi=&aql=&oq="
//
// Return false if the provided HTMLInputElement is not found in the form
bool buildSearchString(const HTMLFormElement* form, Vector<char>* encodedString, WTF::TextEncoding* encoding, const HTMLInputElement* textElement)
{
    bool isElementFound = false;

    Vector<FormAssociatedElement*> elements = form->associatedElements();
    for (Vector<FormAssociatedElement*>::const_iterator i(elements.begin()); i != elements.end(); ++i) {
        if (!(*i)->isFormControlElement())
            continue;

        HTMLFormControlElement* control = toHTMLFormControlElement(*i);

        if (control->isDisabledFormControl() || control->name().isNull())
            continue;

        FormDataList dataList(*encoding);
        if (!control->appendFormData(dataList, false))
            continue;

        const WillBeHeapVector<FormDataList::Item>& items = dataList.items();

        for (WillBeHeapVector<FormDataList::Item>::const_iterator j(items.begin()); j != items.end(); ++j) {
            if (!encodedString->isEmpty())
                encodedString->append('&');
            FormDataBuilder::encodeStringAsFormData(*encodedString, j->data());
            encodedString->append('=');
            ++j;
            if (control == textElement) {
                encodedString->append("{searchTerms}", 13);
                isElementFound = true;
            } else
                FormDataBuilder::encodeStringAsFormData(*encodedString, j->data());
        }
    }
    return isElementFound;
}
} // namespace

namespace blink {

WebSearchableFormData::WebSearchableFormData(const WebFormElement& form, const WebInputElement& selectedInputElement)
{
    RefPtr<HTMLFormElement> formElement = form.operator PassRefPtr<HTMLFormElement>();
    HTMLInputElement* inputElement = selectedInputElement.operator PassRefPtr<HTMLInputElement>().get();

    // Only consider forms that GET data.
    // Allow HTTPS only when an input element is provided.
    if (equalIgnoringCase(formElement->getAttribute(methodAttr), "post")
        || (!IsHTTPFormSubmit(formElement.get()) && !inputElement))
        return;

    Vector<char> encodedString;
    WTF::TextEncoding encoding;

    GetFormEncoding(formElement.get(), &encoding);
    if (!encoding.isValid()) {
        // Need a valid encoding to encode the form elements.
        // If the encoding isn't found webkit ends up replacing the params with
        // empty strings. So, we don't try to do anything here.
        return;
    }

    // Look for a suitable search text field in the form when a
    // selectedInputElement is not provided.
    if (!inputElement) {
        inputElement = findSuitableSearchInputElement(formElement.get());

        // Return if no suitable text element has been found.
        if (!inputElement)
            return;
    }

    HTMLFormControlElement* firstSubmitButton = GetButtonToActivate(formElement.get());
    if (firstSubmitButton) {
        // The form does not have an active submit button, make the first button
        // active. We need to do this, otherwise the URL will not contain the
        // name of the submit button.
        firstSubmitButton->setActivatedSubmit(true);
    }

    bool isValidSearchString = buildSearchString(formElement.get(), &encodedString, &encoding, inputElement);

    if (firstSubmitButton)
        firstSubmitButton->setActivatedSubmit(false);

    // Return if the search string is not valid.
    if (!isValidSearchString)
        return;

    String action(formElement->action());
    KURL url(formElement->document().completeURL(action.isNull() ? "" : action));
    RefPtr<FormData> formData = FormData::create(encodedString);
    url.setQuery(formData->flattenToString());
    m_url = url;
    m_encoding = String(encoding.name());
}

} // namespace blink
