/*
 * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "PaymentCoordinator.h"

#if ENABLE(APPLE_PAY)

#include "ApplePayCouponCodeUpdate.h"
#include "ApplePayPaymentMethodUpdate.h"
#include "ApplePayShippingContactUpdate.h"
#include "ApplePayShippingMethod.h"
#include "ApplePayShippingMethodUpdate.h"
#include "Document.h"
#include "ExceptionDetails.h"
#include "LinkIconCollector.h"
#include "Logging.h"
#include "Page.h"
#include "PaymentCoordinatorClient.h"
#include "PaymentSession.h"
#include "UserContentProvider.h"
#include <wtf/CompletionHandler.h>
#include <wtf/URL.h>

#define PAYMENT_COORDINATOR_RELEASE_LOG_ERROR(fmt, ...) RELEASE_LOG_ERROR(ApplePay, "%p - PaymentCoordinator::" fmt, this, ##__VA_ARGS__)
#define PAYMENT_COORDINATOR_RELEASE_LOG(fmt, ...) RELEASE_LOG(ApplePay, "%p - PaymentCoordinator::" fmt, this, ##__VA_ARGS__)

namespace WebCore {

PaymentCoordinator::PaymentCoordinator(PaymentCoordinatorClient& client)
    : m_client { client }
{
}

PaymentCoordinator::~PaymentCoordinator()
{
    m_client.paymentCoordinatorDestroyed();
}

bool PaymentCoordinator::supportsVersion(Document&, unsigned version) const
{
    auto supportsVersion = m_client.supportsVersion(version);
    PAYMENT_COORDINATOR_RELEASE_LOG("supportsVersion(%d) -> %d", version, supportsVersion);
    return supportsVersion;
}

bool PaymentCoordinator::canMakePayments()
{
    auto canMakePayments = m_client.canMakePayments();
    PAYMENT_COORDINATOR_RELEASE_LOG("canMakePayments() -> %d", canMakePayments);
    return canMakePayments;
}

void PaymentCoordinator::canMakePaymentsWithActiveCard(Document& document, const String& merchantIdentifier, Function<void(bool)>&& completionHandler)
{
    m_client.canMakePaymentsWithActiveCard(merchantIdentifier, document.domain(), [this, weakThis = WeakPtr { *this }, document = WeakPtr { document }, completionHandler = WTFMove(completionHandler)](bool canMakePayments) {
        if (!weakThis)
            return completionHandler(false);

        PAYMENT_COORDINATOR_RELEASE_LOG("canMakePaymentsWithActiveCard() -> %d", canMakePayments);

        if (!canMakePayments)
            return completionHandler(false);

        if (!document)
            return completionHandler(false);

        completionHandler(true);
    });
}

void PaymentCoordinator::openPaymentSetup(Document& document, const String& merchantIdentifier, Function<void(bool)>&& completionHandler)
{
    PAYMENT_COORDINATOR_RELEASE_LOG("openPaymentSetup()");
    m_client.openPaymentSetup(merchantIdentifier, document.domain(), WTFMove(completionHandler));
}

bool PaymentCoordinator::beginPaymentSession(Document& document, PaymentSession& paymentSession, const ApplePaySessionPaymentRequest& paymentRequest)
{
    ASSERT(!m_activeSession);

    auto linkIconURLs = LinkIconCollector { document }.iconsOfTypes({ LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon }).map([](auto& icon) {
        return icon.url;
    });
    auto showPaymentUI = m_client.showPaymentUI(document.url(), WTFMove(linkIconURLs), paymentRequest);
    PAYMENT_COORDINATOR_RELEASE_LOG("beginPaymentSession() -> %d", showPaymentUI);
    if (!showPaymentUI)
        return false;

    m_activeSession = &paymentSession;
    return true;
}

void PaymentCoordinator::completeMerchantValidation(const PaymentMerchantSession& paymentMerchantSession)
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("completeMerchantValidation()");
    m_client.completeMerchantValidation(paymentMerchantSession);
}

void PaymentCoordinator::completeShippingMethodSelection(std::optional<ApplePayShippingMethodUpdate>&& update)
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("completeShippingMethodSelection()");
    m_client.completeShippingMethodSelection(WTFMove(update));
}

void PaymentCoordinator::completeShippingContactSelection(std::optional<ApplePayShippingContactUpdate>&& update)
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("completeShippingContactSelection()");
    m_client.completeShippingContactSelection(WTFMove(update));
}

void PaymentCoordinator::completePaymentMethodSelection(std::optional<ApplePayPaymentMethodUpdate>&& update)
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("completePaymentMethodSelection()");
    m_client.completePaymentMethodSelection(WTFMove(update));
}

#if ENABLE(APPLE_PAY_COUPON_CODE)

void PaymentCoordinator::completeCouponCodeChange(std::optional<ApplePayCouponCodeUpdate>&& update)
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("completeCouponCodeChange()");
    m_client.completeCouponCodeChange(WTFMove(update));
}

#endif // ENABLE(APPLE_PAY_COUPON_CODE)

void PaymentCoordinator::completePaymentSession(ApplePayPaymentAuthorizationResult&& result)
{
    ASSERT(m_activeSession);

    bool isFinalState = result.isFinalState();
    PAYMENT_COORDINATOR_RELEASE_LOG("completePaymentSession() (isFinalState: %d)", isFinalState);
    m_client.completePaymentSession(WTFMove(result));

    if (!isFinalState)
        return;

    m_activeSession = nullptr;
}

void PaymentCoordinator::abortPaymentSession()
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("abortPaymentSession()");
    m_client.abortPaymentSession();
    m_activeSession = nullptr;
}

void PaymentCoordinator::cancelPaymentSession()
{
    ASSERT(m_activeSession);
    PAYMENT_COORDINATOR_RELEASE_LOG("cancelPaymentSession()");
    m_client.cancelPaymentSession();
}

void PaymentCoordinator::validateMerchant(URL&& validationURL)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("validateMerchant()");
    m_activeSession->validateMerchant(WTFMove(validationURL));
}

void PaymentCoordinator::didAuthorizePayment(const Payment& payment)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("didAuthorizePayment()");
    m_activeSession->didAuthorizePayment(payment);
}

void PaymentCoordinator::didSelectPaymentMethod(const PaymentMethod& paymentMethod)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("didSelectPaymentMethod()");
    m_activeSession->didSelectPaymentMethod(paymentMethod);
}

void PaymentCoordinator::didSelectShippingMethod(const ApplePayShippingMethod& shippingMethod)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("didSelectShippingMethod()");
    m_activeSession->didSelectShippingMethod(shippingMethod);
}

void PaymentCoordinator::didSelectShippingContact(const PaymentContact& shippingContact)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("didSelectShippingContact()");
    m_activeSession->didSelectShippingContact(shippingContact);
}

#if ENABLE(APPLE_PAY_COUPON_CODE)

void PaymentCoordinator::didChangeCouponCode(String&& couponCode)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("didChangeCouponCode()");
    m_activeSession->didChangeCouponCode(WTFMove(couponCode));
}

#endif // ENABLE(APPLE_PAY_COUPON_CODE)

void PaymentCoordinator::didCancelPaymentSession(PaymentSessionError&& error)
{
    if (!m_activeSession) {
        // It's possible that the payment has been aborted already.
        return;
    }

    PAYMENT_COORDINATOR_RELEASE_LOG("didCancelPaymentSession()");
    m_activeSession->didCancelPaymentSession(WTFMove(error));
    m_activeSession = nullptr;
}

std::optional<String> PaymentCoordinator::validatedPaymentNetwork(Document&, unsigned version, const String& paymentNetwork) const
{
    if (version < 2 && equalLettersIgnoringASCIICase(paymentNetwork, "jcb"_s))
        return std::nullopt;

    if (version < 3 && equalIgnoringASCIICase(paymentNetwork, "carteBancaire"_s))
        return std::nullopt;

    return m_client.validatedPaymentNetwork(paymentNetwork);
}

void PaymentCoordinator::getSetupFeatures(const ApplePaySetupConfiguration& configuration, const URL& url, CompletionHandler<void(Vector<Ref<ApplePaySetupFeature>>&&)>&& completionHandler)
{
    PAYMENT_COORDINATOR_RELEASE_LOG("getSetupFeatures()");
    m_client.getSetupFeatures(configuration, url, [this, weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler)](Vector<Ref<ApplePaySetupFeature>>&& features) mutable {
        if (!weakThis)
            return;
        PAYMENT_COORDINATOR_RELEASE_LOG("getSetupFeatures() completed (features: %zu)", features.size());
        completionHandler(WTFMove(features));
    });
}

void PaymentCoordinator::beginApplePaySetup(const ApplePaySetupConfiguration& configuration, const URL& url, Vector<RefPtr<ApplePaySetupFeature>>&& features, CompletionHandler<void(bool)>&& completionHandler)
{
    PAYMENT_COORDINATOR_RELEASE_LOG("beginApplePaySetup()");
    m_client.beginApplePaySetup(configuration, url, WTFMove(features), [this, weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler)](bool success) mutable {
        if (!weakThis)
            return;
        PAYMENT_COORDINATOR_RELEASE_LOG("beginApplePaySetup() completed (success: %d)", success);
        completionHandler(success);
    });
}

void PaymentCoordinator::endApplePaySetup()
{
    PAYMENT_COORDINATOR_RELEASE_LOG("endApplePaySetup()");
    m_client.endApplePaySetup();
}

} // namespace WebCore

#undef PAYMENT_COORDINATOR_RELEASE_LOG_ERROR
#undef PAYMENT_COORDINATOR_RELEASE_LOG

#endif // ENABLE(APPLE_PAY)
