/**
 * This file is part of the DOM implementation for KDE.
 *
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
 *
 * 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "config.h"
#include "HTMLAreaElement.h"

#include "Document.h"
#include "HTMLNames.h"
#include "FloatRect.h"
#include "HitTestResult.h"
#include "RenderObject.h"

using namespace std;

namespace WebCore {

using namespace HTMLNames;

HTMLAreaElement::HTMLAreaElement(Document *doc)
    : HTMLAnchorElement(areaTag, doc)
    , m_coords(0)
    , m_coordsLen(0)
    , m_lastSize(-1, -1)
    , m_shape(Unknown)
{
}

HTMLAreaElement::~HTMLAreaElement()
{
    delete [] m_coords;
}

void HTMLAreaElement::parseMappedAttribute(MappedAttribute *attr)
{
    if (attr->name() == shapeAttr) {
        if (equalIgnoringCase(attr->value(), "default"))
            m_shape = Default;
        else if (equalIgnoringCase(attr->value(), "circle"))
            m_shape = Circle;
        else if (equalIgnoringCase(attr->value(), "poly"))
            m_shape = Poly;
        else if (equalIgnoringCase(attr->value(), "rect"))
            m_shape = Rect;
    } else if (attr->name() == coordsAttr) {
        delete [] m_coords;
        m_coords = attr->value().toCoordsArray(m_coordsLen);
    } else if (attr->name() == altAttr || attr->name() == accesskeyAttr) {
        // Do nothing.
    } else
        HTMLAnchorElement::parseMappedAttribute(attr);
}

bool HTMLAreaElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestResult& result)
{
    if (m_lastSize != size) {
        region = getRegion(size);
        m_lastSize = size;
    }

    if (!region.contains(IntPoint(x, y)))
        return false;
    
    result.setInnerNode(this);
    result.setURLElement(this);
    return true;
}

IntRect HTMLAreaElement::getRect(RenderObject* obj) const
{
    int dx, dy;
    obj->absolutePosition(dx, dy);
    Path p = getRegion(m_lastSize);
    p.translate(IntSize(dx, dy));
    return enclosingIntRect(p.boundingRect());
}

Path HTMLAreaElement::getRegion(const IntSize& size) const
{
    if (!m_coords && m_shape != Default)
        return Path();

    int width = size.width();
    int height = size.height();

    // If element omits the shape attribute, select shape based on number of coordinates.
    Shape shape = m_shape;
    if (shape == Unknown) {
        if (m_coordsLen == 3)
            shape = Circle;
        else if (m_coordsLen == 4)
            shape = Rect;
        else if (m_coordsLen >= 6)
            shape = Poly;
    }

    Path path;
    switch (shape) {
        case Poly:
            if (m_coordsLen >= 6) {
                int numPoints = m_coordsLen / 2;
                path.moveTo(FloatPoint(m_coords[0].calcMinValue(width), m_coords[1].calcMinValue(height)));
                for (int i = 1; i < numPoints; ++i)
                    path.addLineTo(FloatPoint(m_coords[i * 2].calcMinValue(width), m_coords[i * 2 + 1].calcMinValue(height)));
                path.closeSubpath();
            }
            break;
        case Circle:
            if (m_coordsLen >= 3) {
                Length radius = m_coords[2];
                int r = min(radius.calcMinValue(width), radius.calcMinValue(height));
                path.addEllipse(FloatRect(m_coords[0].calcMinValue(width) - r, m_coords[1].calcMinValue(height) - r, 2 * r, 2 * r));
            }
            break;
        case Rect:
            if (m_coordsLen >= 4) {
                int x0 = m_coords[0].calcMinValue(width);
                int y0 = m_coords[1].calcMinValue(height);
                int x1 = m_coords[2].calcMinValue(width);
                int y1 = m_coords[3].calcMinValue(height);
                path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0));
            }
            break;
        case Default:
            path.addRect(FloatRect(0, 0, width, height));
            break;
        case Unknown:
            break;
    }

    return path;
}

String HTMLAreaElement::accessKey() const
{
    return getAttribute(accesskeyAttr);
}

void HTMLAreaElement::setAccessKey(const String& value)
{
    setAttribute(accesskeyAttr, value);
}

String HTMLAreaElement::alt() const
{
    return getAttribute(altAttr);
}

void HTMLAreaElement::setAlt(const String& value)
{
    setAttribute(altAttr, value);
}

String HTMLAreaElement::coords() const
{
    return getAttribute(coordsAttr);
}

void HTMLAreaElement::setCoords(const String& value)
{
    setAttribute(coordsAttr, value);
}

String HTMLAreaElement::href() const
{
    return document()->completeURL(getAttribute(hrefAttr));
}

void HTMLAreaElement::setHref(const String& value)
{
    setAttribute(hrefAttr, value);
}

bool HTMLAreaElement::noHref() const
{
    return !getAttribute(nohrefAttr).isNull();
}

void HTMLAreaElement::setNoHref(bool noHref)
{
    setAttribute(nohrefAttr, noHref ? "" : 0);
}

String HTMLAreaElement::shape() const
{
    return getAttribute(shapeAttr);
}

void HTMLAreaElement::setShape(const String& value)
{
    setAttribute(shapeAttr, value);
}

void HTMLAreaElement::setTabIndex(int tabIndex)
{
    setAttribute(tabindexAttr, String::number(tabIndex));
}

String HTMLAreaElement::target() const
{
    return getAttribute(targetAttr);
}

void HTMLAreaElement::setTarget(const String& value)
{
    setAttribute(targetAttr, value);
}

}
