// Copyright 2016 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 "modules/payments/PaymentRequest.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/JSONValuesForV8.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/ScriptState.h"
#include "bindings/modules/v8/V8PaymentDetails.h"
#include "core/EventTypeNames.h"
#include "core/dom/DOMException.h"
#include "core/dom/ExceptionCode.h"
#include "core/events/Event.h"
#include "core/events/EventQueue.h"
#include "modules/EventTargetModulesNames.h"
#include "modules/payments/PaymentAddress.h"
#include "modules/payments/PaymentItem.h"
#include "modules/payments/PaymentRequestUpdateEvent.h"
#include "modules/payments/PaymentResponse.h"
#include "modules/payments/PaymentShippingOption.h"
#include "modules/payments/PaymentsValidators.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/wtf_array.h"
#include "platform/mojo/MojoHelper.h"
#include "public/platform/ServiceRegistry.h"
#include <utility>

namespace mojo {

using blink::mojom::blink::PaymentCurrencyAmount;
using blink::mojom::blink::PaymentCurrencyAmountPtr;
using blink::mojom::blink::PaymentDetails;
using blink::mojom::blink::PaymentDetailsPtr;
using blink::mojom::blink::PaymentItem;
using blink::mojom::blink::PaymentItemPtr;
using blink::mojom::blink::PaymentMethodData;
using blink::mojom::blink::PaymentMethodDataPtr;
using blink::mojom::blink::PaymentOptions;
using blink::mojom::blink::PaymentOptionsPtr;
using blink::mojom::blink::PaymentShippingOption;
using blink::mojom::blink::PaymentShippingOptionPtr;

template <>
struct TypeConverter<PaymentCurrencyAmountPtr, blink::PaymentCurrencyAmount> {
    static PaymentCurrencyAmountPtr Convert(const blink::PaymentCurrencyAmount& input)
    {
        PaymentCurrencyAmountPtr output = PaymentCurrencyAmount::New();
        output->currency = input.currency();
        output->value = input.value();
        return output;
    }
};

template <>
struct TypeConverter<PaymentItemPtr, blink::PaymentItem> {
    static PaymentItemPtr Convert(const blink::PaymentItem& input)
    {
        PaymentItemPtr output = PaymentItem::New();
        output->label = input.label();
        output->amount = PaymentCurrencyAmount::From(input.amount());
        return output;
    }
};

template <>
struct TypeConverter<PaymentShippingOptionPtr, blink::PaymentShippingOption> {
    static PaymentShippingOptionPtr Convert(const blink::PaymentShippingOption& input)
    {
        PaymentShippingOptionPtr output = PaymentShippingOption::New();
        output->id = input.id();
        output->label = input.label();
        output->amount = PaymentCurrencyAmount::From(input.amount());
        output->selected = input.hasSelected() && input.selected();
        return output;
    }
};

template <>
struct TypeConverter<PaymentDetailsPtr, blink::PaymentDetails> {
    static PaymentDetailsPtr Convert(const blink::PaymentDetails& input)
    {
        PaymentDetailsPtr output = PaymentDetails::New();
        output->total = PaymentItem::From(input.total());

        if (input.hasDisplayItems())
            output->display_items = mojo::WTFArray<PaymentItemPtr>::From(input.displayItems());
        else
            output->display_items = mojo::WTFArray<PaymentItemPtr>::New(0);

        if (input.hasShippingOptions())
            output->shipping_options = mojo::WTFArray<PaymentShippingOptionPtr>::From(input.shippingOptions());
        else
            output->shipping_options = mojo::WTFArray<PaymentShippingOptionPtr>::New(0);

        return output;
    }
};

template <>
struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> {
    static PaymentOptionsPtr Convert(const blink::PaymentOptions& input)
    {
        PaymentOptionsPtr output = PaymentOptions::New();
        output->request_shipping = input.requestShipping();
        return output;
    }
};

template <>
struct TypeConverter<WTFArray<PaymentMethodDataPtr>, WTF::Vector<blink::PaymentRequest::MethodData>> {
    static WTFArray<PaymentMethodDataPtr> Convert(const WTF::Vector<blink::PaymentRequest::MethodData>& input)
    {
        WTFArray<PaymentMethodDataPtr> output(input.size());
        for (size_t i = 0; i < input.size(); ++i) {
            output[i] = PaymentMethodData::New();
            output[i]->supported_methods = WTF::Vector<WTF::String>(input[i].supportedMethods);
            output[i]->stringified_data = input[i].stringifiedData;
        }
        return output;
    }
};

} // namespace mojo

namespace blink {
namespace {

// Validates ShippingOption or PaymentItem, which happen to have identical fields,
// except for "id", which is present only in ShippingOption.
template <typename T>
void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptionState)
{
    if (!item.hasLabel() || item.label().isEmpty()) {
        exceptionState.throwTypeError("Item label required");
        return;
    }

    if (!item.hasAmount()) {
        exceptionState.throwTypeError("Currency amount required");
        return;
    }

    if (!item.amount().hasCurrency()) {
        exceptionState.throwTypeError("Currency code required");
        return;
    }

    if (!item.amount().hasValue()) {
        exceptionState.throwTypeError("Currency value required");
        return;
    }

    String errorMessage;
    if (!PaymentsValidators::isValidCurrencyCodeFormat(item.amount().currency(), &errorMessage)) {
        exceptionState.throwTypeError(errorMessage);
        return;
    }

    if (!PaymentsValidators::isValidAmountFormat(item.amount().value(), &errorMessage)) {
        exceptionState.throwTypeError(errorMessage);
        return;
    }
}

void validateDisplayItems(const HeapVector<PaymentItem>& items, ExceptionState& exceptionState)
{
    for (const auto& item : items) {
        validateShippingOptionOrPaymentItem(item, exceptionState);
        if (exceptionState.hadException())
            return;
    }
}

void validateShippingOptions(const HeapVector<PaymentShippingOption>& options, ExceptionState& exceptionState)
{
    for (const auto& option : options) {
        if (!option.hasId() || option.id().isEmpty()) {
            exceptionState.throwTypeError("ShippingOption id required");
            return;
        }

        validateShippingOptionOrPaymentItem(option, exceptionState);
        if (exceptionState.hadException())
            return;
    }
}

void validatePaymentDetails(const PaymentDetails& details, ExceptionState& exceptionState)
{
    if (!details.hasTotal()) {
        exceptionState.throwTypeError("Must specify total");
        return;
    }

    validateShippingOptionOrPaymentItem(details.total(), exceptionState);
    if (exceptionState.hadException())
        return;

    if (details.total().amount().value()[0] == '-') {
        exceptionState.throwTypeError("Total amount value should be non-negative");
        return;
    }

    if (details.hasDisplayItems()) {
        validateDisplayItems(details.displayItems(), exceptionState);
        if (exceptionState.hadException())
            return;
    }

    if (details.hasShippingOptions()) {
        validateShippingOptions(details.shippingOptions(), exceptionState);
    }
}

void validateAndConvertPaymentMethodData(const HeapVector<PaymentMethodData>& paymentMethodData, Vector<PaymentRequest::MethodData>* methodData, ExceptionState& exceptionState)
{
    if (paymentMethodData.isEmpty()) {
        exceptionState.throwTypeError("Must specify at least one payment method identifier");
        return;
    }

    for (const auto& pmd : paymentMethodData) {
        if (pmd.supportedMethods().isEmpty()) {
            exceptionState.throwTypeError("Must specify at least one payment method identifier");
            return;
        }

        String stringifiedData = "";
        if (pmd.hasData() && !pmd.data().isEmpty()) {
            RefPtr<JSONValue> value = toJSONValue(pmd.data().context(), pmd.data().v8Value());
            if (!value) {
                exceptionState.throwTypeError("Unable to parse payment method specific data");
                return;
            }
            if (!value->isNull()) {
                if (value->getType() != JSONValue::TypeObject) {
                    exceptionState.throwTypeError("Data should be a JSON-serializable object");
                    return;
                }
                stringifiedData = JSONObject::cast(value)->toJSONString();
            }
        }
        methodData->append(PaymentRequest::MethodData(pmd.supportedMethods(), stringifiedData));
    }
}

String getSelectedShippingOption(const PaymentDetails& details)
{
    String result;
    if (!details.hasShippingOptions())
        return result;

    for (size_t i = 0; i < details.shippingOptions().size(); ++i) {
        if (details.shippingOptions()[i].hasSelected() && details.shippingOptions()[i].selected()) {
            result = details.shippingOptions()[i].id();
        }
    }

    return result;
}

} // namespace

PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVector<PaymentMethodData>& methodData, const PaymentDetails& details, ExceptionState& exceptionState)
{
    return new PaymentRequest(scriptState, methodData, details, PaymentOptions(), exceptionState);
}

PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVector<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& options, ExceptionState& exceptionState)
{
    return new PaymentRequest(scriptState, methodData, details, options, exceptionState);
}

PaymentRequest::~PaymentRequest()
{
}

ScriptPromise PaymentRequest::show(ScriptState* scriptState)
{
    if (m_showResolver)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Already called show() once"));

    if (!scriptState->domWindow() || !scriptState->domWindow()->frame())
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Cannot show the payment request"));

    DCHECK(!m_paymentProvider.is_bound());
    scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_paymentProvider));
    m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&PaymentRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this))));
    m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
    m_paymentProvider->Show(mojo::WTFArray<mojom::blink::PaymentMethodDataPtr>::From(m_methodData), mojom::blink::PaymentDetails::From(m_details), mojom::blink::PaymentOptions::From(m_options));

    m_showResolver = ScriptPromiseResolver::create(scriptState);
    return m_showResolver->promise();
}

ScriptPromise PaymentRequest::abort(ScriptState* scriptState)
{
    if (m_abortResolver)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Cannot abort() again until the previous abort() has resolved or rejected"));

    if (!m_showResolver)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Never called show(), so nothing to abort"));

    m_abortResolver = ScriptPromiseResolver::create(scriptState);
    m_paymentProvider->Abort();
    return m_abortResolver->promise();
}

const AtomicString& PaymentRequest::interfaceName() const
{
    return EventTargetNames::PaymentRequest;
}

ExecutionContext* PaymentRequest::getExecutionContext() const
{
    return ContextLifecycleObserver::getExecutionContext();
}

ScriptPromise PaymentRequest::complete(ScriptState* scriptState, PaymentComplete result)
{
    if (m_completeResolver)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Already called complete() once"));

    // The payment provider should respond in PaymentRequest::OnComplete().
    m_paymentProvider->Complete(mojom::blink::PaymentComplete(result));

    m_completeResolver = ScriptPromiseResolver::create(scriptState);
    return m_completeResolver->promise();
}

void PaymentRequest::onUpdatePaymentDetails(const ScriptValue& detailsScriptValue)
{
    if (!m_showResolver || !m_paymentProvider)
        return;

    PaymentDetails details;
    TrackExceptionState exceptionState;
    V8PaymentDetails::toImpl(detailsScriptValue.isolate(), detailsScriptValue.v8Value(), details, exceptionState);
    if (exceptionState.hadException()) {
        m_showResolver->reject(DOMException::create(SyntaxError, exceptionState.message()));
        clearResolversAndCloseMojoConnection();
        return;
    }

    validatePaymentDetails(details, exceptionState);
    if (exceptionState.hadException()) {
        m_showResolver->reject(DOMException::create(SyntaxError, exceptionState.message()));
        clearResolversAndCloseMojoConnection();
        return;
    }

    if (m_options.requestShipping())
        m_shippingOption = getSelectedShippingOption(details);

    m_paymentProvider->UpdateWith(mojom::blink::PaymentDetails::From(details));
}

void PaymentRequest::onUpdatePaymentDetailsFailure(const ScriptValue& error)
{
    if (m_showResolver)
        m_showResolver->reject(error);
    if (m_completeResolver)
        m_completeResolver->reject(error);
    clearResolversAndCloseMojoConnection();
}

DEFINE_TRACE(PaymentRequest)
{
    visitor->trace(m_details);
    visitor->trace(m_options);
    visitor->trace(m_shippingAddress);
    visitor->trace(m_showResolver);
    visitor->trace(m_completeResolver);
    visitor->trace(m_abortResolver);
    EventTargetWithInlineData::trace(visitor);
    ContextLifecycleObserver::trace(visitor);
}

PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& options, ExceptionState& exceptionState)
    : ContextLifecycleObserver(scriptState->getExecutionContext())
    , ActiveScriptWrappable(this)
    , m_options(options)
    , m_clientBinding(this)
{
    validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionState);
    if (exceptionState.hadException())
        return;

    if (!scriptState->getExecutionContext()->isSecureContext()) {
        exceptionState.throwSecurityError("Must be in a secure context");
        return;
    }

    if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame()->isMainFrame()) {
        exceptionState.throwSecurityError("Must be in a top-level browsing context");
        return;
    }

    validatePaymentDetails(details, exceptionState);
    if (exceptionState.hadException())
        return;
    m_details = details;

    if (m_options.requestShipping())
        m_shippingOption = getSelectedShippingOption(details);
}

void PaymentRequest::contextDestroyed()
{
    clearResolversAndCloseMojoConnection();
}

bool PaymentRequest::hasPendingActivity() const
{
    return m_showResolver || m_completeResolver;
}

void PaymentRequest::OnShippingAddressChange(mojom::blink::PaymentAddressPtr address)
{
    DCHECK(m_showResolver);
    DCHECK(!m_completeResolver);

    String errorMessage;
    if (!PaymentsValidators::isValidShippingAddress(address, &errorMessage)) {
        m_showResolver->reject(DOMException::create(SyntaxError, errorMessage));
        clearResolversAndCloseMojoConnection();
        return;
    }

    m_shippingAddress = new PaymentAddress(std::move(address));
    PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::create(EventTypeNames::shippingaddresschange);
    event->setTarget(this);
    event->setPaymentDetailsUpdater(this);
    bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event);
    DCHECK(success);
    ALLOW_UNUSED_LOCAL(success);
}

void PaymentRequest::OnShippingOptionChange(const String& shippingOptionId)
{
    DCHECK(m_showResolver);
    DCHECK(!m_completeResolver);
    m_shippingOption = shippingOptionId;
    PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::create(EventTypeNames::shippingoptionchange);
    event->setTarget(this);
    event->setPaymentDetailsUpdater(this);
    bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event);
    DCHECK(success);
    ALLOW_UNUSED_LOCAL(success);
}

void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response)
{
    DCHECK(m_showResolver);
    DCHECK(!m_completeResolver);

    if (m_options.requestShipping()) {
        if (!response->shipping_address || response->shipping_option.isEmpty()) {
            m_showResolver->reject(DOMException::create(SyntaxError));
            clearResolversAndCloseMojoConnection();
            return;
        }

        String errorMessage;
        if (!PaymentsValidators::isValidShippingAddress(response->shipping_address, &errorMessage)) {
            m_showResolver->reject(DOMException::create(SyntaxError, errorMessage));
            clearResolversAndCloseMojoConnection();
            return;
        }

        m_shippingAddress = new PaymentAddress(response->shipping_address.Clone());
        m_shippingOption = response->shipping_option;
    } else {
        if (response->shipping_address || !response->shipping_option.isNull()) {
            m_showResolver->reject(DOMException::create(SyntaxError));
            clearResolversAndCloseMojoConnection();
            return;
        }
    }

    if ((m_options.requestPayerEmail() && response->payer_email.isEmpty())
        || (m_options.requestPayerPhone() && response->payer_phone.isEmpty())
        || (!m_options.requestPayerEmail() && !response->payer_email.isNull())
        || (!m_options.requestPayerPhone() && !response->payer_phone.isNull())) {
        m_showResolver->reject(DOMException::create(SyntaxError));
        clearResolversAndCloseMojoConnection();
        return;
    }

    m_showResolver->resolve(new PaymentResponse(std::move(response), this));

    // Do not close the mojo connection here. The merchant website should call
    // PaymentResponse::complete(boolean), which will be forwarded over the mojo
    // connection to display a success or failure message to the user.
    m_showResolver.clear();
}

void PaymentRequest::OnError()
{
    if (m_completeResolver)
        m_completeResolver->reject(DOMException::create(SyntaxError, "Request cancelled"));
    if (m_showResolver)
        m_showResolver->reject(DOMException::create(SyntaxError, "Request cancelled"));
    if (m_abortResolver)
        m_abortResolver->reject(DOMException::create(SyntaxError, "Request cancelled"));
    clearResolversAndCloseMojoConnection();
}

void PaymentRequest::OnComplete()
{
    DCHECK(m_completeResolver);
    m_completeResolver->resolve();
    clearResolversAndCloseMojoConnection();
}

void PaymentRequest::OnAbort(bool abortedSuccessfully)
{
    DCHECK(m_abortResolver);
    DCHECK(m_showResolver);

    if (!abortedSuccessfully) {
        m_abortResolver->reject(DOMException::create(InvalidStateError));
        m_abortResolver.clear();
        return;
    }

    m_showResolver->reject(DOMException::create(AbortError));
    m_abortResolver->resolve();
    clearResolversAndCloseMojoConnection();
}

void PaymentRequest::clearResolversAndCloseMojoConnection()
{
    m_completeResolver.clear();
    m_showResolver.clear();
    m_abortResolver.clear();
    if (m_clientBinding.is_bound())
        m_clientBinding.Close();
    m_paymentProvider.reset();
}

} // namespace blink
