/*
 * Copyright (C) 2011-2018 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. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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"
#include "CSSValuePool.h"

#include "CSSParser.h"
#include "CSSPrimitiveValueMappings.h"
#include "CSSValueKeywords.h"
#include "CSSValueList.h"
#include <wtf/text/StringConcatenateNumbers.h>

namespace WebCore {

LazyNeverDestroyed<StaticCSSValuePool> staticCSSValuePool;

StaticCSSValuePool::StaticCSSValuePool()
{
    m_implicitInitialValue.construct(CSSValue::StaticCSSValue, CSSPrimitiveValue::ImplicitInitialValue);
    
    m_transparentColor.construct(CSSValue::StaticCSSValue, Color::transparentBlack);
    m_whiteColor.construct(CSSValue::StaticCSSValue, Color::white);
    m_blackColor.construct(CSSValue::StaticCSSValue, Color::black);

    for (unsigned i = firstCSSValueKeyword; i <= lastCSSValueKeyword; ++i)
        m_identifierValues[i].construct(CSSValue::StaticCSSValue, static_cast<CSSValueID>(i));

    for (unsigned i = 0; i < (maximumCacheableIntegerValue + 1); ++i) {
        m_pixelValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PX);
        m_percentValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PERCENTAGE);
        m_numberValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_NUMBER);
    }
}

void StaticCSSValuePool::init()
{
    static std::once_flag onceKey;
    std::call_once(onceKey, []() {
        staticCSSValuePool.construct();
    });
}

CSSValuePool::CSSValuePool()
{
    StaticCSSValuePool::init();
}

CSSValuePool& CSSValuePool::singleton()
{
    static MainThreadNeverDestroyed<CSSValuePool> pool;
    return pool;
}

Ref<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSValueID ident)
{
    RELEASE_ASSERT(ident >= firstCSSValueKeyword && ident <= lastCSSValueKeyword);
    return staticCSSValuePool->m_identifierValues[ident].get();
}

Ref<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSPropertyID ident)
{
    return CSSPrimitiveValue::createIdentifier(ident);
}

Ref<CSSPrimitiveValue> CSSValuePool::createColorValue(const Color& color)
{
    // These are the empty and deleted values of the hash table.
    if (color == Color::transparentBlack)
        return staticCSSValuePool->m_transparentColor.get();
    if (color == Color::white)
        return staticCSSValuePool->m_whiteColor.get();
    // Just because it is common.
    if (color == Color::black)
        return staticCSSValuePool->m_blackColor.get();

    // Remove one entry at random if the cache grows too large.
    // FIXME: Use TinyLRUCache instead?
    const int maximumColorCacheSize = 512;
    if (m_colorValueCache.size() >= maximumColorCacheSize)
        m_colorValueCache.remove(m_colorValueCache.random());

    return *m_colorValueCache.ensure(color, [&color] {
        return CSSPrimitiveValue::create(color);
    }).iterator->value;
}

Ref<CSSPrimitiveValue> CSSValuePool::createValue(double value, CSSUnitType type)
{
    if (value < 0 || value > StaticCSSValuePool::maximumCacheableIntegerValue)
        return CSSPrimitiveValue::create(value, type);

    int intValue = static_cast<int>(value);
    if (value != intValue)
        return CSSPrimitiveValue::create(value, type);

    switch (type) {
    case CSSUnitType::CSS_PX:
        return staticCSSValuePool->m_pixelValues[intValue].get();
    case CSSUnitType::CSS_PERCENTAGE:
        return staticCSSValuePool->m_percentValues[intValue].get();
    case CSSUnitType::CSS_NUMBER:
        return staticCSSValuePool->m_numberValues[intValue].get();
    default:
        return CSSPrimitiveValue::create(value, type);
    }
}

Ref<CSSPrimitiveValue> CSSValuePool::createFontFamilyValue(const String& familyName, FromSystemFontID fromSystemFontID)
{
    // Remove one entry at random if the cache grows too large.
    // FIXME: Use TinyLRUCache instead?
    const int maximumFontFamilyCacheSize = 128;
    if (m_fontFamilyValueCache.size() >= maximumFontFamilyCacheSize)
        m_fontFamilyValueCache.remove(m_fontFamilyValueCache.random());

    bool isFromSystemID = fromSystemFontID == FromSystemFontID::Yes;
    return *m_fontFamilyValueCache.ensure({ familyName, isFromSystemID }, [&familyName, isFromSystemID] {
        return CSSPrimitiveValue::create(CSSFontFamily { familyName, isFromSystemID });
    }).iterator->value;
}

RefPtr<CSSValueList> CSSValuePool::createFontFaceValue(const AtomString& string)
{
    // Remove one entry at random if the cache grows too large.
    // FIXME: Use TinyLRUCache instead?
    const int maximumFontFaceCacheSize = 128;
    if (m_fontFaceValueCache.size() >= maximumFontFaceCacheSize)
        m_fontFaceValueCache.remove(m_fontFaceValueCache.random());

    return m_fontFaceValueCache.ensure(string, [&string] () -> RefPtr<CSSValueList> {
        auto result = CSSParser::parseSingleValue(CSSPropertyFontFamily, string);
        if (!is<CSSValueList>(result))
            return nullptr;
        // FIXME: Make downcast work on RefPtr, remove the get() below, and save one reference count churn.
        return downcast<CSSValueList>(result.get());
    }).iterator->value;
}

void CSSValuePool::drain()
{
    m_colorValueCache.clear();
    m_fontFaceValueCache.clear();
    m_fontFamilyValueCache.clear();
}

}
