/*
 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
 *
 * 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 "core/dom/CheckedRadioButtons.h"

#include "core/html/HTMLInputElement.h"
#include "wtf/HashSet.h"

namespace WebCore {

class RadioButtonGroup {
    WTF_MAKE_FAST_ALLOCATED;
public:
    static PassOwnPtr<RadioButtonGroup> create();
    bool isEmpty() const { return m_members.isEmpty(); }
    bool isRequired() const { return m_requiredCount; }
    HTMLInputElement* checkedButton() const { return m_checkedButton; }
    void add(HTMLInputElement*);
    void updateCheckedState(HTMLInputElement*);
    void requiredAttributeChanged(HTMLInputElement*);
    void remove(HTMLInputElement*);
    bool contains(HTMLInputElement*) const;

private:
    RadioButtonGroup();
    void setNeedsValidityCheckForAllButtons();
    bool isValid() const;
    void setCheckedButton(HTMLInputElement*);

    HashSet<HTMLInputElement*> m_members;
    HTMLInputElement* m_checkedButton;
    size_t m_requiredCount;
};

RadioButtonGroup::RadioButtonGroup()
    : m_checkedButton(0)
    , m_requiredCount(0)
{
}

PassOwnPtr<RadioButtonGroup> RadioButtonGroup::create()
{
    return adoptPtr(new RadioButtonGroup);
}

inline bool RadioButtonGroup::isValid() const
{
    return !isRequired() || m_checkedButton;
}

void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
{
    HTMLInputElement* oldCheckedButton = m_checkedButton;
    if (oldCheckedButton == button)
        return;
    m_checkedButton = button;
    if (oldCheckedButton)
        oldCheckedButton->setChecked(false);
}

void RadioButtonGroup::add(HTMLInputElement* button)
{
    ASSERT(button->isRadioButton());
    if (!m_members.add(button).isNewEntry)
        return;
    bool groupWasValid = isValid();
    if (button->isRequired())
        ++m_requiredCount;
    if (button->checked())
        setCheckedButton(button);

    bool groupIsValid = isValid();
    if (groupWasValid != groupIsValid)
        setNeedsValidityCheckForAllButtons();
    else if (!groupIsValid) {
        // A radio button not in a group is always valid. We need to make it
        // invalid only if the group is invalid.
        button->setNeedsValidityCheck();
    }
}

void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
{
    ASSERT(button->isRadioButton());
    ASSERT(m_members.contains(button));
    bool wasValid = isValid();
    if (button->checked())
        setCheckedButton(button);
    else {
        if (m_checkedButton == button)
            m_checkedButton = 0;
    }
    if (wasValid != isValid())
        setNeedsValidityCheckForAllButtons();
}

void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
{
    ASSERT(button->isRadioButton());
    ASSERT(m_members.contains(button));
    bool wasValid = isValid();
    if (button->isRequired())
        ++m_requiredCount;
    else {
        ASSERT(m_requiredCount);
        --m_requiredCount;
    }
    if (wasValid != isValid())
        setNeedsValidityCheckForAllButtons();
}

void RadioButtonGroup::remove(HTMLInputElement* button)
{
    ASSERT(button->isRadioButton());
    HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
    if (it == m_members.end())
        return;
    bool wasValid = isValid();
    m_members.remove(it);
    if (button->isRequired()) {
        ASSERT(m_requiredCount);
        --m_requiredCount;
    }
    if (m_checkedButton == button)
        m_checkedButton = 0;

    if (m_members.isEmpty()) {
        ASSERT(!m_requiredCount);
        ASSERT(!m_checkedButton);
    } else if (wasValid != isValid())
        setNeedsValidityCheckForAllButtons();
    if (!wasValid) {
        // A radio button not in a group is always valid. We need to make it
        // valid only if the group was invalid.
        button->setNeedsValidityCheck();
    }
}

void RadioButtonGroup::setNeedsValidityCheckForAllButtons()
{
    typedef HashSet<HTMLInputElement*>::const_iterator Iterator;
    Iterator end = m_members.end();
    for (Iterator it = m_members.begin(); it != end; ++it) {
        HTMLInputElement* button = *it;
        ASSERT(button->isRadioButton());
        button->setNeedsValidityCheck();
    }
}

bool RadioButtonGroup::contains(HTMLInputElement* button) const
{
    return m_members.contains(button);
}

// ----------------------------------------------------------------

// Explicity define empty constructor and destructor in order to prevent the
// compiler from generating them as inlines. So we don't need to to define
// RadioButtonGroup in the header.
CheckedRadioButtons::CheckedRadioButtons()
{
}

CheckedRadioButtons::~CheckedRadioButtons()
{
}

void CheckedRadioButtons::addButton(HTMLInputElement* element)
{
    ASSERT(element->isRadioButton());
    if (element->name().isEmpty())
        return;

    if (!m_nameToGroupMap)
        m_nameToGroupMap = adoptPtr(new NameToGroupMap);

    OwnPtr<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name().impl(), PassOwnPtr<RadioButtonGroup>()).iterator->value;
    if (!group)
        group = RadioButtonGroup::create();
    group->add(element);
}

void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element)
{
    ASSERT(element->isRadioButton());
    if (element->name().isEmpty())
        return;
    ASSERT(m_nameToGroupMap);
    if (!m_nameToGroupMap)
        return;
    RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
    ASSERT(group);
    group->updateCheckedState(element);
}

void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element)
{
    ASSERT(element->isRadioButton());
    if (element->name().isEmpty())
        return;
    ASSERT(m_nameToGroupMap);
    if (!m_nameToGroupMap)
        return;
    RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
    ASSERT(group);
    group->requiredAttributeChanged(element);
}

HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const
{
    if (!m_nameToGroupMap)
        return 0;
    RadioButtonGroup* group = m_nameToGroupMap->get(name.impl());
    return group ? group->checkedButton() : 0;
}

bool CheckedRadioButtons::isInRequiredGroup(HTMLInputElement* element) const
{
    ASSERT(element->isRadioButton());
    if (element->name().isEmpty())
        return false;
    if (!m_nameToGroupMap)
        return false;
    RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
    return group && group->isRequired() && group->contains(element);
}

void CheckedRadioButtons::removeButton(HTMLInputElement* element)
{
    ASSERT(element->isRadioButton());
    if (element->name().isEmpty())
        return;
    if (!m_nameToGroupMap)
        return;

    NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl());
    if (it == m_nameToGroupMap->end())
        return;
    it->value->remove(element);
    if (it->value->isEmpty()) {
        // FIXME: We may skip deallocating the empty RadioButtonGroup for
        // performance improvement. If we do so, we need to change the key type
        // of m_nameToGroupMap from StringImpl* to AtomicString.
        m_nameToGroupMap->remove(it);
        if (m_nameToGroupMap->isEmpty())
            m_nameToGroupMap.clear();
    }
}

} // namespace
