/*
 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008 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.
 */

#ifndef Rect_h
#define Rect_h

#include "core/css/CSSPrimitiveValue.h"
#include "wtf/RefPtr.h"
#include "wtf/text/StringBuilder.h"

namespace WebCore {

class RectBase {
public:
    CSSPrimitiveValue* top() const { return m_top.get(); }
    CSSPrimitiveValue* right() const { return m_right.get(); }
    CSSPrimitiveValue* bottom() const { return m_bottom.get(); }
    CSSPrimitiveValue* left() const { return m_left.get(); }

    void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; }
    void setRight(PassRefPtr<CSSPrimitiveValue> right) { m_right = right; }
    void setBottom(PassRefPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; }
    void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; }

    bool equals(const RectBase& other) const
    {
        return compareCSSValuePtr(m_top, other.m_top)
            && compareCSSValuePtr(m_right, other.m_right)
            && compareCSSValuePtr(m_left, other.m_left)
            && compareCSSValuePtr(m_bottom, other.m_bottom);
    }

    bool hasVariableReference() const
    {
        return m_top->hasVariableReference()
            || m_right->hasVariableReference()
            || m_bottom->hasVariableReference()
            || m_left->hasVariableReference();
    }

protected:
    RectBase() { }
    RectBase(const RectBase& cloneFrom)
        : m_top(cloneFrom.m_top ? cloneFrom.m_top->cloneForCSSOM() : 0)
        , m_right(cloneFrom.m_right ? cloneFrom.m_right->cloneForCSSOM() : 0)
        , m_bottom(cloneFrom.m_bottom ? cloneFrom.m_bottom->cloneForCSSOM() : 0)
        , m_left(cloneFrom.m_left ? cloneFrom.m_left->cloneForCSSOM() : 0)
    {
    }

    ~RectBase() { }

private:
    RefPtr<CSSPrimitiveValue> m_top;
    RefPtr<CSSPrimitiveValue> m_right;
    RefPtr<CSSPrimitiveValue> m_bottom;
    RefPtr<CSSPrimitiveValue> m_left;
};

class Rect : public RectBase, public RefCounted<Rect> {
public:
    static PassRefPtr<Rect> create() { return adoptRef(new Rect); }

    PassRefPtr<Rect> cloneForCSSOM() const { return adoptRef(new Rect(*this)); }

    String cssText() const
    {
        return generateCSSString(top()->cssText(), right()->cssText(), bottom()->cssText(), left()->cssText());
    }

    String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
    {
        return generateCSSString(top()->customSerializeResolvingVariables(variables),
            right()->customSerializeResolvingVariables(variables),
            bottom()->customSerializeResolvingVariables(variables),
            left()->customSerializeResolvingVariables(variables));
    }

private:
    Rect() { }
    Rect(const Rect& cloneFrom) : RectBase(cloneFrom), RefCounted<Rect>() { }
    static String generateCSSString(const String& top, const String& right, const String& bottom, const String& left)
    {
        return "rect(" + top + ' ' + right + ' ' + bottom + ' ' + left + ')';
    }
};

class Quad : public RectBase, public RefCounted<Quad> {
public:
    static PassRefPtr<Quad> create() { return adoptRef(new Quad); }

    PassRefPtr<Quad> cloneForCSSOM() const { return adoptRef(new Quad(*this)); }

    String cssText() const
    {
        return generateCSSString(top()->cssText(), right()->cssText(), bottom()->cssText(), left()->cssText());
    }

    String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
    {
        return generateCSSString(top()->customSerializeResolvingVariables(variables),
            right()->customSerializeResolvingVariables(variables),
            bottom()->customSerializeResolvingVariables(variables),
            left()->customSerializeResolvingVariables(variables));
    }

private:
    Quad() { }
    Quad(const Quad& cloneFrom) : RectBase(cloneFrom), RefCounted<Quad>() { }
    static String generateCSSString(const String& top, const String& right, const String& bottom, const String& left)
    {
        StringBuilder result;
        // reserve space for the four strings, plus three space separator characters.
        result.reserveCapacity(top.length() + right.length() + bottom.length() + left.length() + 3);
        result.append(top);
        if (right != top || bottom != top || left != top) {
            result.append(' ');
            result.append(right);
            if (bottom != top || right != left) {
                result.append(' ');
                result.append(bottom);
                if (left != right) {
                    result.append(' ');
                    result.append(left);
                }
            }
        }
        return result.toString();
    }
};

} // namespace WebCore

#endif // Rect_h
