/*
 * 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(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"; }
    bool shouldPreventEnteringBackForwardCache_DEPRECATED() const final;
    void stop() 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)
