// 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/Platform.h"
#include <utility>

namespace mojo {

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

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

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

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

template <>
struct TypeConverter<mojom::wtf::PaymentOptionsPtr, blink::PaymentOptions> {
    static mojom::wtf::PaymentOptionsPtr Convert(const blink::PaymentOptions& input)
    {
        mojom::wtf::PaymentOptionsPtr output = mojom::wtf::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"));

    DCHECK(!m_paymentProvider.is_bound());
    blink::Platform::current()->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));
    RefPtrWillBeRawPtr<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;
    RefPtrWillBeRawPtr<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
