/*
 * Copyright (C) 2018 Sony Interactive Entertainment Inc.
 *
 * 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 "KeyedDecoderGeneric.h"

#include "KeyedEncoderGeneric.h"
#include <wtf/HashMap.h>
#include <wtf/Variant.h>
#include <wtf/Vector.h>
#include <wtf/persistence/PersistentDecoder.h>
#include <wtf/text/StringHash.h>

namespace WebCore {

class KeyedDecoderGeneric::Dictionary {
    WTF_MAKE_FAST_ALLOCATED;
public:
    using Node = Variant<Vector<uint8_t>, bool, uint32_t, uint64_t, int32_t, int64_t, float, double, String, std::unique_ptr<Dictionary>, std::unique_ptr<Array>>;

    template <typename T>
    void add(const String& key, T&& value) { m_map.add(key, makeUnique<Node>(std::forward<T>(value))); }
    Node& get(const String& key) { return *m_map.get(key); }

private:
    HashMap<String, std::unique_ptr<Node>> m_map;
};

static bool readString(WTF::Persistence::Decoder& decoder, String& result)
{
    size_t size;
    if (!decoder.decode(size))
        return false;
    Vector<uint8_t> buffer(size);
    if (!decoder.decodeFixedLengthData(buffer.data(), size))
        return false;
    result = String::fromUTF8(buffer.data(), size);
    return true;
}

template<typename T>
static bool readSimpleValue(WTF::Persistence::Decoder& decoder, KeyedDecoderGeneric::Dictionary& dictionary)
{
    String key;
    bool ok = readString(decoder, key);
    if (!ok)
        return false;
    T value;
    ok = decoder.decode(value);
    if (!ok)
        return false;
    dictionary.add(key, WTFMove(value));
    return true;
}

std::unique_ptr<KeyedDecoder> KeyedDecoder::decoder(const uint8_t* data, size_t size)
{
    return makeUnique<KeyedDecoderGeneric>(data, size);
}

KeyedDecoderGeneric::KeyedDecoderGeneric(const uint8_t* data, size_t size)
{
    WTF::Persistence::Decoder decoder(data, size);
    KeyedEncoderGeneric::Type type;
    String key;

    m_rootDictionary = makeUnique<Dictionary>();
    m_dictionaryStack.append(m_rootDictionary.get());

    bool ok = true;
    while (ok && decoder.decodeEnum(type)) {
        switch (type) {
        case KeyedEncoderGeneric::Type::Bytes: {
            ok = readString(decoder, key);
            if (!ok)
                break;
            size_t size;
            ok = decoder.decode(size);
            if (!ok)
                break;
            Vector<uint8_t> buffer(size);
            ok = decoder.decodeFixedLengthData(buffer.data(), size);
            if (!ok)
                break;
            m_dictionaryStack.last()->add(key, WTFMove(buffer));
            break;
        }
        case KeyedEncoderGeneric::Type::Bool:
            ok = readSimpleValue<bool>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::UInt32:
            ok = readSimpleValue<uint32_t>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::UInt64:
            ok = readSimpleValue<uint64_t>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::Int32:
            ok = readSimpleValue<int32_t>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::Int64:
            ok = readSimpleValue<int64_t>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::Float:
            ok = readSimpleValue<float>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::Double:
            ok = readSimpleValue<double>(decoder, *m_dictionaryStack.last());
            break;
        case KeyedEncoderGeneric::Type::String: {
            ok = readString(decoder, key);
            if (!ok)
                break;
            String value;
            ok = readString(decoder, value);
            if (!ok)
                break;
            m_dictionaryStack.last()->add(key, WTFMove(value));
            break;
        }
        case KeyedEncoderGeneric::Type::BeginObject: {
            ok = readString(decoder, key);
            if (!ok)
                break;
            auto* currentDictinary = m_dictionaryStack.last();
            auto newDictionary = makeUnique<Dictionary>();
            m_dictionaryStack.append(newDictionary.get());
            currentDictinary->add(key, WTFMove(newDictionary));
            break;
        }
        case KeyedEncoderGeneric::Type::EndObject:
            m_dictionaryStack.removeLast();
            break;
        case KeyedEncoderGeneric::Type::BeginArray: {
            ok = readString(decoder, key);
            if (!ok)
                break;
            auto newArray = makeUnique<Array>();
            m_arrayStack.append(newArray.get());
            m_dictionaryStack.last()->add(key, WTFMove(newArray));
            break;
        }
        case KeyedEncoderGeneric::Type::BeginArrayElement: {
            auto newDictionary = makeUnique<Dictionary>();
            m_dictionaryStack.append(newDictionary.get());
            m_arrayStack.last()->append(WTFMove(newDictionary));
            break;
        }
        case KeyedEncoderGeneric::Type::EndArrayElement:
            m_dictionaryStack.removeLast();
            break;
        case KeyedEncoderGeneric::Type::EndArray:
            m_arrayStack.removeLast();
            break;
        }
    }
    while (m_dictionaryStack.size() > 1)
        m_dictionaryStack.removeLast();
    while (!m_arrayStack.isEmpty())
        m_arrayStack.removeLast();
}

bool KeyedDecoderGeneric::decodeBytes(const String& key, const uint8_t*& data, size_t& size)
{
    auto* value = WTF::get_if<Vector<uint8_t>>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    data = value->data();
    size = value->size();
    return true;
}

bool KeyedDecoderGeneric::decodeBool(const String& key, bool& result)
{
    auto* value = WTF::get_if<bool>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeUInt32(const String& key, uint32_t& result)
{
    auto* value = WTF::get_if<uint32_t>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeUInt64(const String& key, uint64_t& result)
{
    auto* value = WTF::get_if<uint64_t>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeInt32(const String& key, int32_t& result)
{
    auto* value = WTF::get_if<int32_t>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeInt64(const String& key, int64_t& result)
{
    auto* value = WTF::get_if<int64_t>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeFloat(const String& key, float& result)
{
    auto* value = WTF::get_if<float>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeDouble(const String& key, double& result)
{
    auto* value = WTF::get_if<double>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeString(const String& key, String& result)
{
    auto* value = WTF::get_if<String>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    result = *value;
    return true;
}

bool KeyedDecoderGeneric::beginObject(const String& key)
{
    auto* value = WTF::get_if<std::unique_ptr<Dictionary>>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    m_dictionaryStack.append(value->get());
    return true;
}

void KeyedDecoderGeneric::endObject()
{
    m_dictionaryStack.removeLast();
}

bool KeyedDecoderGeneric::beginArray(const String& key)
{
    auto* value = WTF::get_if<std::unique_ptr<Array>>(m_dictionaryStack.last()->get(key));
    if (!value)
        return false;
    m_arrayStack.append(value->get());
    m_arrayIndexStack.append(0);
    return true;
}

bool KeyedDecoderGeneric::beginArrayElement()
{
    if (m_arrayIndexStack.last() >= m_arrayStack.last()->size())
        return false;

    auto dictionary = m_arrayStack.last()->at(m_arrayIndexStack.last()++).get();
    m_dictionaryStack.append(dictionary);
    return true;
}

void KeyedDecoderGeneric::endArrayElement()
{
    m_dictionaryStack.removeLast();
}

void KeyedDecoderGeneric::endArray()
{
    m_arrayStack.removeLast();
    m_arrayIndexStack.removeLast();
}

} // namespace WebCore
