/*
 * Copyright (C) 2017-2018 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.
 */

#pragma once

#if ENABLE(PAYMENT_REQUEST)

#include "ActiveDOMObject.h"
#include "ContextDestructionObserver.h"
#include "EventTarget.h"
#include "JSValueInWrappedObject.h"
#include "PaymentAddress.h"
#include "PaymentComplete.h"
#include <wtf/WeakPtr.h>

namespace WebCore {

class Document;
class PaymentRequest;
struct PaymentValidationErrors;

template<typename IDLType> class DOMPromiseDeferred;

class PaymentResponse final : public ActiveDOMObject, public EventTargetWithInlineData, public RefCounted<PaymentResponse> {
    WTF_MAKE_ISO_ALLOCATED(PaymentResponse);
public:
    using DetailsFunction = Function<JSC::Strong<JSC::JSObject>(JSC::JSGlobalObject&)>;

    static Ref<PaymentResponse> create(ScriptExecutionContext* context, PaymentRequest& request)
    {
        auto response = adoptRef(*new PaymentResponse(context, request));
        response->finishConstruction();
        return response;
    }

    ~PaymentResponse();

    const String& requestId() const { return m_requestId; }
    void setRequestId(const String& requestId) { m_requestId = requestId; }

    const String& methodName() const { return m_methodName; }
    void setMethodName(const String& methodName) { m_methodName = methodName; }

    const DetailsFunction& detailsFunction() const { return m_detailsFunction; }
    void setDetailsFunction(DetailsFunction&&);

    JSValueInWrappedObject& cachedDetails() { return m_cachedDetails; }

    PaymentAddress* shippingAddress() const { return m_shippingAddress.get(); }
    void setShippingAddress(PaymentAddress* shippingAddress) { m_shippingAddress = shippingAddress; }

    const String& shippingOption() const { return m_shippingOption; }
    void setShippingOption(const String& shippingOption) { m_shippingOption = shippingOption; }

    const String& payerName() const { return m_payerName; }
    void setPayerName(const String& payerName) { m_payerName = payerName; }

    const String& payerEmail() const { return m_payerEmail; }
    void setPayerEmail(const String& payerEmail) { m_payerEmail = payerEmail; }

    const String& payerPhone() const { return m_payerPhone; }
    void setPayerPhone(const String& payerPhone) { m_payerPhone = payerPhone; }

    void complete(std::optional<PaymentComplete>&&, DOMPromiseDeferred<void>&&);
    void retry(PaymentValidationErrors&&, DOMPromiseDeferred<void>&&);
    void abortWithException(Exception&&);
    bool hasRetryPromise() const { return !!m_retryPromise; }
    void settleRetryPromise(ExceptionOr<void>&& = { });

    using RefCounted<PaymentResponse>::ref;
    using RefCounted<PaymentResponse>::deref;

private:
    PaymentResponse(ScriptExecutionContext*, PaymentRequest&);
    void finishConstruction();

    // ActiveDOMObject
    const char* activeDOMObjectName() const final { return "PaymentResponse"; }
    void stop() final;
    void suspend(ReasonForSuspension) final;

    // EventTarget
    EventTargetInterface eventTargetInterface() const final { return PaymentResponseEventTargetInterfaceType; }
    ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
    void refEventTarget() final { ref(); }
    void derefEventTarget() final { deref(); }

    enum class State {
        Created,
        Completed,
        Stopped,
    };

    WeakPtr<PaymentRequest> m_request;
    String m_requestId;
    String m_methodName;
    DetailsFunction m_detailsFunction;
    JSValueInWrappedObject m_cachedDetails;
    RefPtr<PaymentAddress> m_shippingAddress;
    String m_shippingOption;
    String m_payerName;
    String m_payerEmail;
    String m_payerPhone;
    State m_state { State::Created };
    std::unique_ptr<DOMPromiseDeferred<void>> m_retryPromise;
    RefPtr<PendingActivity<PaymentResponse>> m_pendingActivity;
};

} // namespace WebCore

#endif // ENABLE(PAYMENT_REQUEST)
