/*
 * Copyright (C) 2009 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. ``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 COMPUTER, INC. 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"

#if ENABLE(DATAGRID)

#include "DataGridColumn.h"
#include "HTMLDataGridElement.h"
#include "HTMLDataGridColElement.h"
#include "HTMLNames.h"
#include "MappedAttribute.h"
#include "Text.h"

namespace WebCore {

using namespace HTMLNames;

HTMLDataGridColElement::HTMLDataGridColElement(const QualifiedName& name, Document* doc)
    : HTMLElement(name, doc)
    , m_dataGrid(0)
{
}

HTMLDataGridElement* HTMLDataGridColElement::findDataGridAncestor() const
{
    if (parent() && parent()->hasTagName(datagridTag))
        return static_cast<HTMLDataGridElement*>(parent());
    return 0;
}

void HTMLDataGridColElement::ensureColumn()
{
    if (m_column)
        return;
    m_column = DataGridColumn::create(getAttribute(idAttributeName()), label(), type(), primary(), sortable());
}

void HTMLDataGridColElement::insertedIntoTree(bool deep)
{
    HTMLElement::insertedIntoTree(deep);
    if (dataGrid()) // We're connected to a datagrid already.
        return;
    m_dataGrid = findDataGridAncestor();
    if (dataGrid() && dataGrid()->dataSource()->isDOMDataGridDataSource()) {
        ensureColumn();
        m_dataGrid->columns()->add(column()); // FIXME: Deal with ordering issues (complicated, since columns can be made outside the DOM).
    }
}

void HTMLDataGridColElement::removedFromTree(bool deep)
{
    HTMLElement::removedFromTree(deep);
    if (dataGrid() && dataGrid()->dataSource()->isDOMDataGridDataSource()) {
        HTMLDataGridElement* grid = findDataGridAncestor();
        if (!grid && column()) {
            dataGrid()->columns()->remove(column());
            m_dataGrid = 0;
        }
    }
}
    
String HTMLDataGridColElement::label() const
{
    return getAttribute(labelAttr);
}

void HTMLDataGridColElement::setLabel(const String& label)
{
    setAttribute(labelAttr, label);
}

String HTMLDataGridColElement::type() const
{
    return getAttribute(typeAttr);
}

void HTMLDataGridColElement::setType(const String& type)
{
    setAttribute(typeAttr, type);
}

unsigned short HTMLDataGridColElement::sortable() const
{
    if (!hasAttribute(sortableAttr))
        return 2;
    return getAttribute(sortableAttr).toInt(0);
}

void HTMLDataGridColElement::setSortable(unsigned short sortable)
{
    setAttribute(sortableAttr, String::number(sortable));
}

unsigned short HTMLDataGridColElement::sortDirection() const
{
    String sortDirection = getAttribute(sortdirectionAttr);
    if (equalIgnoringCase(sortDirection, "ascending"))
        return 1;
    if (equalIgnoringCase(sortDirection, "descending"))
        return 2;
    return 0;
}

void HTMLDataGridColElement::setSortDirection(unsigned short sortDirection)
{
    // FIXME: Check sortable rules.
    if (sortDirection == 0)
        setAttribute(sortdirectionAttr, "natural");
    else if (sortDirection == 1)
        setAttribute(sortdirectionAttr, "ascending");
    else if (sortDirection == 2)
        setAttribute(sortdirectionAttr, "descending");
}

bool HTMLDataGridColElement::primary() const
{
    return hasAttribute(primaryAttr);
}

void HTMLDataGridColElement::setPrimary(bool primary)
{
    setAttribute(primaryAttr, primary ? "" : 0);
}

void HTMLDataGridColElement::parseMappedAttribute(MappedAttribute* attr) 
{
    HTMLElement::parseMappedAttribute(attr);
     
    if (!column())
        return;

    if (attr->name() == labelAttr)
        column()->setLabel(label());
    else if (attr->name() == typeAttr)
        column()->setType(type());
    else if (attr->name() == primaryAttr)
        column()->setPrimary(primary());
    else if (attr->name() == sortableAttr)
        column()->setSortable(sortable());
    else if (attr->name() == sortdirectionAttr)
        column()->setSortDirection(sortDirection());
    else if (attr->name() == idAttributeName())
        column()->setId(getAttribute(idAttributeName()));
}

} // namespace WebCore

#endif
