/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "FormAssociatedElement.h"

#include "HTMLFormControlElement.h"
#include "HTMLFormElement.h"
#include "HTMLNames.h"
#include "HTMLObjectElement.h"
#include "ValidityState.h"

namespace WebCore {

using namespace HTMLNames;

FormAssociatedElement::FormAssociatedElement(HTMLFormElement* form)
    : m_form(form)
{
}

FormAssociatedElement::~FormAssociatedElement()
{
}

ValidityState* FormAssociatedElement::validity()
{
    if (!m_validityState)
        m_validityState = ValidityState::create(this);

    return m_validityState.get();
}

void FormAssociatedElement::willMoveToNewOwnerDocument()
{
    HTMLElement* element = toHTMLElement(this);
    if (element->fastHasAttribute(formAttr))
        element->document()->unregisterFormElementWithFormAttribute(this);
}

void FormAssociatedElement::insertedIntoDocument()
{
    HTMLElement* element = toHTMLElement(this);
    if (element->fastHasAttribute(formAttr))
        element->document()->registerFormElementWithFormAttribute(this);
}

void FormAssociatedElement::removedFromDocument()
{
    HTMLElement* element = toHTMLElement(this);
    if (element->fastHasAttribute(formAttr))
        element->document()->unregisterFormElementWithFormAttribute(this);
}

void FormAssociatedElement::insertedIntoTree()
{
    HTMLElement* element = toHTMLElement(this);
    if (element->fastHasAttribute(formAttr)) {
        Element* formElement = element->document()->getElementById(element->fastGetAttribute(formAttr));
        if (formElement && formElement->hasTagName(formTag)) {
            if (m_form)
                m_form->removeFormElement(this);
            m_form = static_cast<HTMLFormElement*>(formElement);
            m_form->registerFormElement(this);
        }
    }
    if (!m_form) {
        // This handles the case of a new form element being created by
        // JavaScript and inserted inside a form.  In the case of the parser
        // setting a form, we will already have a non-null value for m_form,
        // and so we don't need to do anything.
        m_form = element->findFormAncestor();
        if (m_form)
            m_form->registerFormElement(this);
    }
}

static inline Node* findRoot(Node* n)
{
    Node* root = n;
    for (; n; n = n->parentNode())
        root = n;
    return root;
}

void FormAssociatedElement::removedFromTree()
{
    HTMLElement* element = toHTMLElement(this);

    // If the form and element are both in the same tree, preserve the connection to the form.
    // Otherwise, null out our form and remove ourselves from the form's list of elements.
    if (m_form && findRoot(element) != findRoot(m_form))
        removeFromForm();
}

void FormAssociatedElement::removeFromForm()
{
    if (!m_form)
        return;
    m_form->removeFormElement(this);
    m_form = 0;
}

void FormAssociatedElement::resetFormOwner(HTMLFormElement* form)
{
    HTMLElement* element = toHTMLElement(this);
    const AtomicString& formId(element->fastGetAttribute(formAttr));
    if (m_form) {
        if (formId.isNull())
            return;
        m_form->removeFormElement(this);
    }
    m_form = 0;
    if (!formId.isNull() && element->inDocument()) {
        // The HTML5 spec says that the element should be associated with
        // the first element in the document to have an ID that equal to
        // the value of form attribute, so we put the result of
        // document()->getElementById() over the given element.
        Element* firstElement = element->document()->getElementById(formId);
        if (firstElement && firstElement->hasTagName(formTag))
            m_form = static_cast<HTMLFormElement*>(firstElement);
        else
            m_form = form;
    } else
        m_form = element->findFormAncestor();
    if (m_form)
        m_form->registerFormElement(this);
}

void FormAssociatedElement::formAttributeChanged()
{
    HTMLElement* element = toHTMLElement(this);
    if (!element->fastHasAttribute(formAttr)) {
        // The form attribute removed. We need to reset form owner here.
        if (m_form)
            m_form->removeFormElement(this);
        m_form = element->findFormAncestor();
        if (m_form)
            form()->registerFormElement(this);
        element->document()->unregisterFormElementWithFormAttribute(this);
    } else
        resetFormOwner(0);
}

const HTMLElement* toHTMLElement(const FormAssociatedElement* associatedElement)
{
    if (associatedElement->isFormControlElement())
        return static_cast<const HTMLFormControlElement*>(associatedElement);
    // Assumes the element is an HTMLObjectElement
    const HTMLElement* element = static_cast<const HTMLObjectElement*>(associatedElement);
    ASSERT(element->hasTagName(objectTag));
    return element;
}

HTMLElement* toHTMLElement(FormAssociatedElement* associatedElement)
{
    return const_cast<HTMLElement*>(toHTMLElement(static_cast<const FormAssociatedElement*>(associatedElement)));
}

} // namespace Webcore
