/****************************************************************************
**
** Copyright (C) 2018 Crimson AS <info@crimson.no>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qv4setobject_p.h" // ### temporary
#include "qv4mapobject_p.h"
#include "qv4mapiterator_p.h"
#include "qv4estable_p.h"
#include "qv4symbol_p.h"

using namespace QV4;

DEFINE_OBJECT_VTABLE(WeakMapCtor);
DEFINE_OBJECT_VTABLE(MapCtor);
DEFINE_OBJECT_VTABLE(MapObject);

void Heap::WeakMapCtor::init(QV4::ExecutionContext *scope)
{
    Heap::FunctionObject::init(scope, QStringLiteral("WeakMap"));
}

void Heap::MapCtor::init(QV4::ExecutionContext *scope)
{
    Heap::FunctionObject::init(scope, QStringLiteral("Map"));
}

ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget, bool weakMap)
{
    Scope scope(f);
    Scoped<MapObject> a(scope, scope.engine->memoryManager->allocate<MapObject>());
    bool protoSet = false;
    if (newTarget)
        protoSet = a->setProtoFromNewTarget(newTarget);
    if (!protoSet && weakMap) {
        a->setPrototypeOf(scope.engine->weakMapPrototype());
        scope.engine->memoryManager->registerWeakMap(a->d());
    }
    a->d()->isWeakMap = weakMap;

    if (argc > 0) {
        ScopedValue iterable(scope, argv[0]);

        if (!iterable->isNullOrUndefined()) {
            ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("set")))));
            if (!adder)
                return scope.engine->throwTypeError();

            ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true));
            if (scope.hasException())
                return Encode::undefined();
            Q_ASSERT(iter);

            ScopedValue obj(scope);
            Value *arguments = scope.alloc(2);
            ScopedValue done(scope);
            forever {
                done = Runtime::IteratorNext::call(scope.engine, iter, obj);
                if (scope.hasException())
                    break;
                if (done->toBoolean())
                    return a->asReturnedValue();
                const Object *o = obj->objectValue();
                if (!o) {
                    scope.engine->throwTypeError();
                    break;
                }

                arguments[0] = o->get(PropertyKey::fromArrayIndex(0));
                if (scope.hasException())
                    break;
                arguments[1] = o->get(PropertyKey::fromArrayIndex(1));
                if (scope.hasException())
                    break;

                adder->call(a, arguments, 2);
                if (scope.hasException())
                    break;
            }
            ScopedValue falsey(scope, Encode(false));
            return Runtime::IteratorClose::call(scope.engine, iter, falsey);
        }
    }
    return a->asReturnedValue();

}

ReturnedValue WeakMapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
    return construct(f, argv, argc, newTarget, true);
}

ReturnedValue WeakMapCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
{
    Scope scope(f);
    return scope.engine->throwTypeError(QString::fromLatin1("(Weak)Map requires new"));
}


ReturnedValue MapCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
    return construct(f, argv, argc, newTarget, false);
}

void WeakMapPrototype::init(ExecutionEngine *engine, Object *ctor)
{
    Scope scope(engine);
    ScopedObject o(scope);
    ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(0));
    ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
    defineDefaultProperty(engine->id_constructor(), (o = ctor));

    defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
    defineDefaultProperty(QStringLiteral("get"), method_get, 1);
    defineDefaultProperty(QStringLiteral("has"), method_has, 1);
    defineDefaultProperty(QStringLiteral("set"), method_set, 2);

    ScopedString val(scope, engine->newString(QLatin1String("WeakMap")));
    defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
}


void MapPrototype::init(ExecutionEngine *engine, Object *ctor)
{
    Scope scope(engine);
    ScopedObject o(scope);
    ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(0));
    ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
    ctor->addSymbolSpecies();
    defineDefaultProperty(engine->id_constructor(), (o = ctor));

    defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
    defineDefaultProperty(QStringLiteral("delete"), method_delete, 1);
    defineDefaultProperty(QStringLiteral("forEach"), method_forEach, 1);
    defineDefaultProperty(QStringLiteral("get"), method_get, 1);
    defineDefaultProperty(QStringLiteral("has"), method_has, 1);
    defineDefaultProperty(QStringLiteral("keys"), method_keys, 0);
    defineDefaultProperty(QStringLiteral("set"), method_set, 2);
    defineAccessorProperty(QStringLiteral("size"), method_get_size, nullptr);
    defineDefaultProperty(QStringLiteral("values"), method_values, 0);

    // Per the spec, the value for entries/@@iterator is the same
    ScopedString valString(scope, scope.engine->newIdentifier(QStringLiteral("entries")));
    ScopedFunctionObject entriesFn(scope, FunctionObject::createBuiltinFunction(engine, valString, MapPrototype::method_entries, 0));
    defineDefaultProperty(QStringLiteral("entries"), entriesFn);
    defineDefaultProperty(engine->symbol_iterator(), entriesFn);

    ScopedString val(scope, engine->newString(QLatin1String("Map")));
    defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), val);
}

void Heap::MapObject::init()
{
    Object::init();
    esTable = new ESTable();
}

void Heap::MapObject::destroy()
{
    delete esTable;
    esTable = nullptr;
}

void Heap::MapObject::removeUnmarkedKeys()
{
    esTable->removeUnmarkedKeys();
}

void Heap::MapObject::markObjects(Heap::Base *that, MarkStack *markStack)
{
    MapObject *m = static_cast<MapObject *>(that);
    m->esTable->markObjects(markStack, m->isWeakMap);
    Object::markObjects(that, markStack);
}

ReturnedValue WeakMapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || !that->d()->isWeakMap)
        return scope.engine->throwTypeError();
    if (!argc || !argv[0].isObject())
        return Encode(false);

    return Encode(that->d()->esTable->remove(argv[0]));

}

ReturnedValue WeakMapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || !that->d()->isWeakMap)
        return scope.engine->throwTypeError();
    if (!argc || !argv[0].isObject())
        return Encode::undefined();

    return that->d()->esTable->get(argv[0]);
}

ReturnedValue WeakMapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || !that->d()->isWeakMap)
        return scope.engine->throwTypeError();
    if (!argc || !argv[0].isObject())
        return Encode(false);

    return Encode(that->d()->esTable->has(argv[0]));
}

ReturnedValue WeakMapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if ((!that || !that->d()->isWeakMap) ||
        (!argc || !argv[0].isObject()))
        return scope.engine->throwTypeError();

    that->d()->esTable->set(argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
    return that.asReturnedValue();
}


ReturnedValue MapPrototype::method_clear(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    that->d()->esTable->clear();
    return Encode::undefined();
}

ReturnedValue MapPrototype::method_delete(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    return Encode(that->d()->esTable->remove(argc ? argv[0] : Value::undefinedValue()));
}

ReturnedValue MapPrototype::method_entries(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
    ao->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
    return ao->asReturnedValue();
}

ReturnedValue MapPrototype::method_forEach(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    ScopedFunctionObject callbackfn(scope, argv[0]);
    if (!callbackfn)
        return scope.engine->throwTypeError();

    ScopedValue thisArg(scope, Value::undefinedValue());
    if (argc > 1)
        thisArg = ScopedValue(scope, argv[1]);

    Value *arguments = scope.alloc(3);
    arguments[2] = that;
    for (uint i = 0; i < that->d()->esTable->size(); ++i) {
        that->d()->esTable->iterate(i, &arguments[1], &arguments[0]); // fill in key (0), value (1)

        callbackfn->call(thisArg, arguments, 3);
        CHECK_EXCEPTION();
    }
    return Encode::undefined();
}

ReturnedValue MapPrototype::method_get(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    return that->d()->esTable->get(argc ? argv[0] : Value::undefinedValue());
}

ReturnedValue MapPrototype::method_has(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    return Encode(that->d()->esTable->has(argc ? argv[0] : Value::undefinedValue()));
}

ReturnedValue MapPrototype::method_keys(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
    ao->d()->iterationKind = IteratorKind::KeyIteratorKind;
    return ao->asReturnedValue();
}

ReturnedValue MapPrototype::method_set(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    that->d()->esTable->set(argc ? argv[0] : Value::undefinedValue(), argc > 1 ? argv[1] : Value::undefinedValue());
    return that.asReturnedValue();
}

ReturnedValue MapPrototype::method_get_size(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    return Encode(that->d()->esTable->size());
}

ReturnedValue MapPrototype::method_values(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
    Scope scope(b);
    Scoped<MapObject> that(scope, thisObject);
    if (!that || that->d()->isWeakMap)
        return scope.engine->throwTypeError();

    Scoped<MapIteratorObject> ao(scope, scope.engine->newMapIteratorObject(that));
    ao->d()->iterationKind = IteratorKind::ValueIteratorKind;
    return ao->asReturnedValue();
}
