/*
 * Copyright (C) 2019 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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"
#include "CSSUnitValue.h"

#if ENABLE(CSS_TYPED_OM)

#include "CSSParserToken.h"
#include "CSSPrimitiveValue.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(CSSUnitValue);

CSSUnitType CSSUnitValue::parseUnit(const String& unit)
{
    if (unit == "number"_s)
        return CSSUnitType::CSS_NUMBER;
    if (unit == "percent"_s)
        return CSSUnitType::CSS_PERCENTAGE;

    // FIXME: Remove these when LineHeightUnitsEnabled is changed back to true or removed
    // https://bugs.webkit.org/show_bug.cgi?id=211351
    if (unit == "lh"_s)
        return CSSUnitType::CSS_LHS;
    if (unit == "rlh"_s)
        return CSSUnitType::CSS_RLHS;

    return CSSParserToken::stringToUnitType(unit);
}

ASCIILiteral CSSUnitValue::unit() const
{
    switch (m_unit) {
    case CSSUnitType::CSS_NUMBER:
        return "number"_s;
    case CSSUnitType::CSS_PERCENTAGE:
        return "percent"_s;
    default:
        break;
    }
    return unitSerialization();
}

ASCIILiteral CSSUnitValue::unitSerialization() const
{
    return CSSPrimitiveValue::unitTypeString(m_unit);
}

void CSSUnitValue::serialize(StringBuilder& builder, OptionSet<SerializationArguments>) const
{
    builder.append(FormattedCSSNumber::create(m_value));
    builder.append(unitSerialization());
}

ExceptionOr<Ref<CSSUnitValue>> CSSUnitValue::create(double value, const String& unit)
{
    auto parsedUnit = parseUnit(unit);
    if (parsedUnit == CSSUnitType::CSS_UNKNOWN)
        return Exception { TypeError };
    auto type = CSSNumericType::create(parsedUnit);
    if (!type)
        return Exception { TypeError };
    auto unitValue = adoptRef(*new CSSUnitValue(value, parsedUnit));
    unitValue->m_type = WTFMove(*type);
    return unitValue;
}

CSSUnitValue::CSSUnitValue(double value, CSSUnitType unit)
    : CSSNumericValue(CSSNumericType::create(unit).value_or(CSSNumericType()))
    , m_value(value)
    , m_unit(unit)
{
}

static double conversionToCanonicalUnitsScaleFactor(CSSUnitType unit)
{
    constexpr double pixelsPerInch = 96;
    constexpr double pixelsPerCentimeter = pixelsPerInch / 2.54;
    constexpr double pointsPerInch = 72;
    constexpr double picasPerInch = 6;

    switch (unit) {
    case CSSUnitType::CSS_MS:
        return 0.001;
    case CSSUnitType::CSS_CM:
        return pixelsPerCentimeter;
    case CSSUnitType::CSS_DPCM:
        return 1.0 / pixelsPerCentimeter;
    case CSSUnitType::CSS_MM:
        return pixelsPerCentimeter / 10;
    case CSSUnitType::CSS_Q:
        return pixelsPerCentimeter / 40;
    case CSSUnitType::CSS_IN:
        return pixelsPerInch;
    case CSSUnitType::CSS_DPI:
        return 1.0 / pixelsPerInch;
    case CSSUnitType::CSS_PT:
        return pixelsPerInch / pointsPerInch;
    case CSSUnitType::CSS_PC:
        return pixelsPerInch / picasPerInch;
    case CSSUnitType::CSS_RAD:
        return 180 / piDouble;
    case CSSUnitType::CSS_GRAD:
        return 0.9;
    case CSSUnitType::CSS_TURN:
        return 360;
    case CSSUnitType::CSS_KHZ:
        return 1000;
    default:
        return 1.0;
    }
}

RefPtr<CSSUnitValue> CSSUnitValue::convertTo(CSSUnitType unit) const
{
    // https://drafts.css-houdini.org/css-typed-om/#convert-a-cssunitvalue
    if (unitCategory(unitEnum()) != unitCategory(unit))
        return nullptr;

    return create(m_value * conversionToCanonicalUnitsScaleFactor(unitEnum()) / conversionToCanonicalUnitsScaleFactor(unit), unit);
}

auto CSSUnitValue::toSumValue() const -> std::optional<SumValue>
{
    // https://drafts.css-houdini.org/css-typed-om/#create-a-sum-value
    auto canonicalUnit = [] (CSSUnitType unit) {
        // FIXME: We probably want to change the definition of canonicalUnitTypeForCategory so this lambda isn't necessary.
        auto category = unitCategory(unit);
        switch (category) {
        case CSSUnitCategory::Percent:
            return CSSUnitType::CSS_PERCENTAGE;
        case CSSUnitCategory::Other:
            if (unit == CSSUnitType::CSS_FR)
                return CSSUnitType::CSS_FR;
            break;
        default:
            break;
        }
        return canonicalUnitTypeForCategory(category);
    } (m_unit);
    auto convertedValue = m_value * conversionToCanonicalUnitsScaleFactor(unitEnum()) / conversionToCanonicalUnitsScaleFactor(canonicalUnit);

    if (m_unit == CSSUnitType::CSS_NUMBER)
        return { { { convertedValue, { } } } };
    return { { { convertedValue, { { canonicalUnit, 1 } } } } };
}

} // namespace WebCore

#endif
