// 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 "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/PaymentItem.h"
#include "modules/payments/PaymentResponse.h"
#include "modules/payments/PaymentsValidators.h"
#include "modules/payments/ShippingAddress.h"
#include "modules/payments/ShippingOption.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/wtf_array.h"
#include "platform/MojoHelper.h"
#include "public/platform/ServiceRegistry.h"
#include <utility>

namespace mojo {

using blink::mojom::wtf::CurrencyAmount;
using blink::mojom::wtf::CurrencyAmountPtr;
using blink::mojom::wtf::PaymentDetails;
using blink::mojom::wtf::PaymentDetailsPtr;
using blink::mojom::wtf::PaymentItem;
using blink::mojom::wtf::PaymentItemPtr;
using blink::mojom::wtf::PaymentOptions;
using blink::mojom::wtf::PaymentOptionsPtr;
using blink::mojom::wtf::ShippingOption;
using blink::mojom::wtf::ShippingOptionPtr;

template <>
struct TypeConverter<CurrencyAmountPtr, blink::CurrencyAmount> {
    static CurrencyAmountPtr Convert(const blink::CurrencyAmount& input)
    {
        CurrencyAmountPtr output = CurrencyAmount::New();
        output->currency_code = input.currencyCode();
        output->value = input.value();
        return output;
    }
};

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

template <>
struct TypeConverter<ShippingOptionPtr, blink::ShippingOption> {
    static ShippingOptionPtr Convert(const blink::ShippingOption& input)
    {
        ShippingOptionPtr output = ShippingOption::New();
        output->id = input.id();
        output->label = input.label();
        output->amount = CurrencyAmount::From(input.amount());
        return output;
    }
};

template <>
struct TypeConverter<PaymentDetailsPtr, blink::PaymentDetails> {
    static PaymentDetailsPtr Convert(const blink::PaymentDetails& input)
    {
        PaymentDetailsPtr output = PaymentDetails::New();
        output->items = mojo::WTFArray<PaymentItemPtr>::From(input.items());
        if (input.hasShippingOptions())
            output->shipping_options = mojo::WTFArray<ShippingOptionPtr>::From(input.shippingOptions());
        else
            output->shipping_options = mojo::WTFArray<ShippingOptionPtr>::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;
    }
};

} // namespace mojo

namespace blink {
namespace {

// Validates ShippingOption and PaymentItem dictionaries, which happen to have identical fields.
template <typename T>
void validateShippingOptionsOrPaymentItems(HeapVector<T> items, ExceptionState& exceptionState)
{
    String errorMessage;
    for (const auto& item : items) {
        if (!item.hasId()) {
            exceptionState.throwTypeError("Item id required");
            return;
        }

        if (!item.hasLabel()) {
            exceptionState.throwTypeError("Item label required");
            return;
        }

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

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

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

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

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

} // namespace

PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<String>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptionState)
{
    return new PaymentRequest(scriptState, supportedMethods, details, PaymentOptions(), ScriptValue(), exceptionState);
}

PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<String>& supportedMethods, const PaymentDetails& details, const PaymentOptions& options, ExceptionState& exceptionState)
{
    return new PaymentRequest(scriptState, supportedMethods, details, options, ScriptValue(), exceptionState);
}

PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<String>& supportedMethods, const PaymentDetails& details, const PaymentOptions& options, const ScriptValue& data, ExceptionState& exceptionState)
{
    return new PaymentRequest(scriptState, supportedMethods, details, options, data, 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(sameThreadBindForMojo(&PaymentRequest::OnError, this));
    m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
    m_paymentProvider->Show(std::move(m_supportedMethods), mojom::wtf::PaymentDetails::From(m_details), mojom::wtf::PaymentOptions::From(m_options), m_stringifiedData.isNull() ? "" : m_stringifiedData);

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

void PaymentRequest::abort(ExceptionState& exceptionState)
{
    if (!m_showResolver) {
        exceptionState.throwDOMException(InvalidStateError, "Never called show(), so nothing to abort");
        return;
    }

    m_paymentProvider->Abort();
}

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

ExecutionContext* PaymentRequest::getExecutionContext() const
{
    return m_scriptState->getExecutionContext();
}

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

    m_completeResolver = ScriptPromiseResolver::create(scriptState);
    m_paymentProvider->Complete(success);

    return m_completeResolver->promise();
}

DEFINE_TRACE(PaymentRequest)
{
    visitor->trace(m_details);
    visitor->trace(m_options);
    visitor->trace(m_shippingAddress);
    visitor->trace(m_showResolver);
    visitor->trace(m_completeResolver);
    RefCountedGarbageCollectedEventTargetWithInlineData<PaymentRequest>::trace(visitor);
}

PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& supportedMethods, const PaymentDetails& details, const PaymentOptions& options, const ScriptValue& data, ExceptionState& exceptionState)
    : m_scriptState(scriptState)
    , m_supportedMethods(supportedMethods)
    , m_details(details)
    , m_options(options)
    , m_clientBinding(this)
{
    // TODO(rouslan): Also check for a top-level browsing context.
    // https://github.com/w3c/browser-payment-api/issues/2
    if (!scriptState->getExecutionContext()->isSecureContext()) {
        exceptionState.throwSecurityError("Must be in a secure context");
        return;
    }

    if (supportedMethods.isEmpty()) {
        exceptionState.throwTypeError("Must specify at least one payment method identifier");
        return;
    }

    if (!details.hasItems()) {
        exceptionState.throwTypeError("Must specify items");
        return;
    }

    if (details.items().isEmpty()) {
        exceptionState.throwTypeError("Must specify at least one item");
        return;
    }

    validateShippingOptionsOrPaymentItems(details.items(), exceptionState);
    if (exceptionState.hadException())
        return;

    if (details.hasShippingOptions()) {
        validateShippingOptionsOrPaymentItems(details.shippingOptions(), exceptionState);
        if (exceptionState.hadException())
            return;
    }

    if (!data.isEmpty()) {
        RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value());
        if (!value) {
            exceptionState.throwTypeError("Unable to parse payment method specific data");
            return;
        }
        if (!value->isNull()) {
            if (value->getType() != JSONValue::TypeObject) {
                exceptionState.throwTypeError("Payment method specific data should be a JSON-serializable object");
                return;
            }

            RefPtr<JSONObject> jsonData = JSONObject::cast(value);
            for (const auto& paymentMethodSpecificKeyValue : *jsonData) {
                if (!supportedMethods.contains(paymentMethodSpecificKeyValue.key)) {
                    exceptionState.throwTypeError("'" + paymentMethodSpecificKeyValue.key + "' should match one of the payment method identifiers");
                    return;
                }
                if (paymentMethodSpecificKeyValue.value->getType() != JSONValue::TypeObject) {
                    exceptionState.throwTypeError("Data for '" + paymentMethodSpecificKeyValue.key + "' should be a JSON-serializable object");
                    return;
                }
            }

            m_stringifiedData = jsonData->toJSONString();
        }
    }

    // Set the currently selected option if only one option was passed.
    if (details.hasShippingOptions() && details.shippingOptions().size() == 1)
        m_shippingOption = details.shippingOptions().begin()->id();
}

void PaymentRequest::OnShippingAddressChange(mojom::wtf::ShippingAddressPtr address)
{
    DCHECK(m_showResolver);
    DCHECK(!m_completeResolver);

    String errorMessage;
    if (!PaymentsValidators::isValidRegionCodeFormat(address->region_code, &errorMessage)
        || !PaymentsValidators::isValidLanguageCodeFormat(address->language_code, &errorMessage)
        || !PaymentsValidators::isValidScriptCodeFormat(address->script_code, &errorMessage)) {
        m_showResolver->reject(DOMException::create(SyntaxError, errorMessage));
        cleanUp();
        return;
    }

    if (address->language_code.isEmpty() && !address->script_code.isEmpty()) {
        m_showResolver->reject(DOMException::create(SyntaxError, "If language code is empty, then script code should also be empty"));
        cleanUp();
        return;
    }

    m_shippingAddress = new ShippingAddress(std::move(address));
    RawPtr<Event> event = Event::create(EventTypeNames::shippingaddresschange);
    event->setTarget(this);
    getExecutionContext()->getEventQueue()->enqueueEvent(event);
}

void PaymentRequest::OnShippingOptionChange(const String& shippingOptionId)
{
    DCHECK(m_showResolver);
    DCHECK(!m_completeResolver);
    m_shippingOption = shippingOptionId;
    RawPtr<Event> event = Event::create(EventTypeNames::shippingoptionchange);
    event->setTarget(this);
    getExecutionContext()->getEventQueue()->enqueueEvent(event);
}

void PaymentRequest::OnPaymentResponse(mojom::wtf::PaymentResponsePtr response)
{
    DCHECK(m_showResolver);
    DCHECK(!m_completeResolver);
    m_showResolver->resolve(new PaymentResponse(std::move(response), this));
}

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"));
    cleanUp();
}

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

void PaymentRequest::cleanUp()
{
    m_completeResolver.clear();
    m_showResolver.clear();
    m_clientBinding.Close();
    m_paymentProvider.reset();
}

} // namespace blink
