/*
 * 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();
}

template<typename T>
const T* KeyedDecoderGeneric::getPointerFromDictionaryStack(const String& key)
{
    auto& dictionary = m_dictionaryStack.last();

    auto node = dictionary->get(key);
    if (!node)
        return nullptr;

    return WTF::get_if<T>(*node);
}

template<typename T>
bool KeyedDecoderGeneric::decodeSimpleValue(const String& key, T& result)
{
    auto value = getPointerFromDictionaryStack<T>(key);
    if (!value)
        return false;

    result = *value;
    return true;
}

bool KeyedDecoderGeneric::decodeBytes(const String& key, const uint8_t*& data, size_t& size)
{
    auto value = getPointerFromDictionaryStack<Vector<uint8_t>>(key);
    if (!value)
        return false;

    data = value->data();
    size = value->size();
    return true;
}

bool KeyedDecoderGeneric::decodeBool(const String& key, bool& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeUInt32(const String& key, uint32_t& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeUInt64(const String& key, uint64_t& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeInt32(const String& key, int32_t& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeInt64(const String& key, int64_t& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeFloat(const String& key, float& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeDouble(const String& key, double& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::decodeString(const String& key, String& result)
{
    return decodeSimpleValue(key, result);
}

bool KeyedDecoderGeneric::beginObject(const String& key)
{
    auto value = getPointerFromDictionaryStack<std::unique_ptr<Dictionary>>(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 = getPointerFromDictionaryStack<std::unique_ptr<Array>>(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
