/*
    Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    Copyright (C) 2006, 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 Length_h
#define Length_h

#include <wtf/Assertions.h>
#include <wtf/FastAllocBase.h>
#include <wtf/MathExtras.h>

namespace WebCore {

class String;

const int undefinedLength = -1;
const int percentScaleFactor = 128;

enum LengthType { Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic };

struct Length : FastAllocBase {
    Length()
        : m_value(0)
    {
    }

    Length(LengthType t)
        : m_value(t)
    {
    }

    Length(int v, LengthType t, bool q = false)
        : m_value((v * 16) | (q << 3) | t) // FIXME: Doesn't work if the passed-in value is very large!
    {
        ASSERT(t != Percent);
    }

    Length(double v, LengthType t, bool q = false)
        : m_value(static_cast<int>(v * percentScaleFactor) * 16 | (q << 3) | t)
    {
        ASSERT(t == Percent);
    }

    bool operator==(const Length& o) const { return m_value == o.m_value; }
    bool operator!=(const Length& o) const { return m_value != o.m_value; }

    int value() const {
        ASSERT(type() != Percent);
        return rawValue();
    }

    int rawValue() const { return (m_value & ~0xF) / 16; }

    double percent() const
    {
        ASSERT(type() == Percent);
        return static_cast<double>(rawValue()) / percentScaleFactor;
    }

    LengthType type() const { return static_cast<LengthType>(m_value & 7); }
    bool quirk() const { return (m_value >> 3) & 1; }

    void setValue(LengthType t, int value)
    {
        ASSERT(t != Percent);
        setRawValue(t, value);
    }

    void setRawValue(LengthType t, int value) { m_value = value * 16 | (m_value & 0x8) | t; }

    void setValue(int value)
    {
        ASSERT(!value || type() != Percent);
        setRawValue(value);
    }

    void setRawValue(int value) { m_value = value * 16 | (m_value & 0xF); }

    void setValue(LengthType t, double value)
    {
        ASSERT(t == Percent);
        m_value = static_cast<int>(value * percentScaleFactor) * 16 | (m_value & 0x8) | t;
    }

    void setValue(double value)
    {
        ASSERT(type() == Percent);
        m_value = static_cast<int>(value * percentScaleFactor) * 16 | (m_value & 0xF);
    }

    // note: works only for certain types, returns undefinedLength otherwise
    int calcValue(int maxValue, bool roundPercentages = false) const
    {
        switch (type()) {
            case Fixed:
                return value();
            case Percent:
                if (roundPercentages)
                    return static_cast<int>(round(maxValue * percent() / 100.0));
                return maxValue * rawValue() / (100 * percentScaleFactor);
            case Auto:
                return maxValue;
            default:
                return undefinedLength;
        }
    }

    int calcMinValue(int maxValue, bool roundPercentages = false) const
    {
        switch (type()) {
            case Fixed:
                return value();
            case Percent:
                if (roundPercentages)
                    return static_cast<int>(round(maxValue * percent() / 100.0));
                return maxValue * rawValue() / (100 * percentScaleFactor);
            case Auto:
            default:
                return 0;
        }
    }

    float calcFloatValue(int maxValue) const
    {
        switch (type()) {
            case Fixed:
                return static_cast<float>(value());
            case Percent:
                return static_cast<float>(maxValue * percent() / 100.0);
            case Auto:
                return static_cast<float>(maxValue);
            default:
                return static_cast<float>(undefinedLength);
        }
    }

    bool isUndefined() const { return rawValue() == undefinedLength; }
    bool isZero() const { return !(m_value & ~0xF); }
    bool isPositive() const { return rawValue() > 0; }
    bool isNegative() const { return rawValue() < 0; }

    bool isAuto() const { return type() == Auto; }
    bool isRelative() const { return type() == Relative; }
    bool isPercent() const { return type() == Percent; }
    bool isFixed() const { return type() == Fixed; }
    bool isStatic() const { return type() == Static; }
    bool isIntrinsicOrAuto() const { return type() == Auto || type() == MinIntrinsic || type() == Intrinsic; }

    Length blend(const Length& from, double progress) const
    {
        // Blend two lengths to produce a new length that is in between them.  Used for animation.
        if (!from.isZero() && !isZero() && from.type() != type())
            return *this;

        if (from.isZero() && isZero())
            return *this;
        
        LengthType resultType = type();
        if (isZero())
            resultType = from.type();
        
        if (resultType == Percent) {
            double fromPercent = from.isZero() ? 0. : from.percent();
            double toPercent = isZero() ? 0. : percent();
            return Length(fromPercent + (toPercent - fromPercent) * progress, Percent);
        } 
            
        int fromValue = from.isZero() ? 0 : from.value();
        int toValue = isZero() ? 0 : value();
        return Length(int(fromValue + (toValue - fromValue) * progress), resultType);
    }

private:
    int m_value;
};

Length* newCoordsArray(const String&, int& len);
Length* newLengthArray(const String&, int& len);

} // namespace WebCore

#endif // Length_h
