// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "bindings/core/v8/ScriptPromisePropertyBase.h"

#include "bindings/core/v8/ScopedPersistent.h"
#include "bindings/core/v8/ScriptState.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8HiddenValue.h"
#include "core/dom/ExecutionContext.h"

namespace blink {

ScriptPromisePropertyBase::ScriptPromisePropertyBase(ExecutionContext* executionContext, Name name)
    : ContextLifecycleObserver(executionContext)
    , m_isolate(toIsolate(executionContext))
    , m_name(name)
    , m_state(Pending)
{
}

ScriptPromisePropertyBase::~ScriptPromisePropertyBase()
{
    clearWrappers();
}

static void clearHandle(const v8::WeakCallbackData<v8::Object, ScopedPersistent<v8::Object> >& data)
{
    data.GetParameter()->clear();
}

ScriptPromise ScriptPromisePropertyBase::promise(DOMWrapperWorld& world)
{
    if (!executionContext())
        return ScriptPromise();

    v8::HandleScope handleScope(m_isolate);
    v8::Handle<v8::Context> context = toV8Context(executionContext(), world);
    if (context.IsEmpty())
        return ScriptPromise();
    ScriptState* scriptState = ScriptState::from(context);
    ScriptState::Scope scope(scriptState);

    v8::Handle<v8::Object> wrapper = ensureHolderWrapper(scriptState);
    ASSERT(wrapper->CreationContext() == context);

    v8::Handle<v8::Value> cachedPromise = V8HiddenValue::getHiddenValue(m_isolate, wrapper, promiseName());
    if (!cachedPromise.IsEmpty())
        return ScriptPromise(scriptState, cachedPromise);

    // Create and cache the Promise
    v8::Handle<v8::Promise::Resolver> resolver = v8::Promise::Resolver::New(m_isolate);
    v8::Handle<v8::Promise> promise = resolver->GetPromise();
    V8HiddenValue::setHiddenValue(m_isolate, wrapper, promiseName(), promise);

    switch (m_state) {
    case Pending:
        // Cache the resolver too
        V8HiddenValue::setHiddenValue(m_isolate, wrapper, resolverName(), resolver);
        break;
    case Resolved:
    case Rejected:
        resolveOrRejectInternal(resolver);
        break;
    }

    return ScriptPromise(scriptState, promise);
}

void ScriptPromisePropertyBase::resolveOrReject(State targetState)
{
    ASSERT(executionContext());
    ASSERT(m_state == Pending);
    ASSERT(targetState == Resolved || targetState == Rejected);

    m_state = targetState;

    v8::HandleScope handleScope(m_isolate);
    size_t i = 0;
    while (i < m_wrappers.size()) {
        const OwnPtr<ScopedPersistent<v8::Object> >& persistent = m_wrappers[i];
        if (persistent->isEmpty()) {
            // wrapper has died.
            // Since v8 GC can run during the iteration and clear the reference,
            // we can't move this check out of the loop.
            m_wrappers.remove(i);
            continue;
        }
        v8::Local<v8::Object> wrapper = persistent->newLocal(m_isolate);
        ScriptState::Scope scope(ScriptState::from(wrapper->CreationContext()));

        v8::Local<v8::Promise::Resolver> resolver = V8HiddenValue::getHiddenValue(m_isolate, wrapper, resolverName()).As<v8::Promise::Resolver>();

        V8HiddenValue::deleteHiddenValue(m_isolate, wrapper, resolverName());
        resolveOrRejectInternal(resolver);
        ++i;
    }
}

void ScriptPromisePropertyBase::resetBase()
{
    clearWrappers();
    m_state = Pending;
}

void ScriptPromisePropertyBase::resolveOrRejectInternal(v8::Handle<v8::Promise::Resolver> resolver)
{
    switch (m_state) {
    case Pending:
        ASSERT_NOT_REACHED();
        break;
    case Resolved:
        resolver->Resolve(resolvedValue(m_isolate, resolver->CreationContext()->Global()));
        break;
    case Rejected:
        resolver->Reject(rejectedValue(m_isolate, resolver->CreationContext()->Global()));
        break;
    }
}

v8::Local<v8::Object> ScriptPromisePropertyBase::ensureHolderWrapper(ScriptState* scriptState)
{
    v8::Local<v8::Context> context = scriptState->context();
    size_t i = 0;
    while (i < m_wrappers.size()) {
        const OwnPtr<ScopedPersistent<v8::Object> >& persistent = m_wrappers[i];
        if (persistent->isEmpty()) {
            // wrapper has died.
            // Since v8 GC can run during the iteration and clear the reference,
            // we can't move this check out of the loop.
            m_wrappers.remove(i);
            continue;
        }

        v8::Local<v8::Object> wrapper = persistent->newLocal(m_isolate);
        if (wrapper->CreationContext() == context)
            return wrapper;
        ++i;
    }
    v8::Local<v8::Object> wrapper = holder(context->Global(), m_isolate);
    OwnPtr<ScopedPersistent<v8::Object> > weakPersistent = adoptPtr(new ScopedPersistent<v8::Object>);
    weakPersistent->set(m_isolate, wrapper);
    weakPersistent->setWeak(weakPersistent.get(), &clearHandle);
    m_wrappers.append(weakPersistent.release());
    return wrapper;
}

void ScriptPromisePropertyBase::clearWrappers()
{
    v8::HandleScope handleScope(m_isolate);
    for (WeakPersistentSet::iterator i = m_wrappers.begin(); i != m_wrappers.end(); ++i) {
        v8::Local<v8::Object> wrapper = (*i)->newLocal(m_isolate);
        if (!wrapper.IsEmpty()) {
            wrapper->DeleteHiddenValue(resolverName());
            wrapper->DeleteHiddenValue(promiseName());
        }
    }
    m_wrappers.clear();
}

v8::Handle<v8::String> ScriptPromisePropertyBase::promiseName()
{
    switch (m_name) {
#define P(Name)                                           \
    case Name:                                            \
        return V8HiddenValue::Name ## Promise(m_isolate);

        SCRIPT_PROMISE_PROPERTIES(P)

#undef P
    }
    ASSERT_NOT_REACHED();
    return v8::Handle<v8::String>();
}

v8::Handle<v8::String> ScriptPromisePropertyBase::resolverName()
{
    switch (m_name) {
#define P(Name)                                            \
    case Name:                                             \
        return V8HiddenValue::Name ## Resolver(m_isolate);

        SCRIPT_PROMISE_PROPERTIES(P)

#undef P
    }
    ASSERT_NOT_REACHED();
    return v8::Handle<v8::String>();
}

} // namespace blink
