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

#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "VREye.h"
#include "VRLayerInit.h"
#include "VRPlatformDisplayClient.h"
#include <wtf/RefCounted.h>

namespace WebCore {

enum ExceptionCode;
class DeferredPromise;
class RequestAnimationFrameCallback;
class ScriptedAnimationController;
class VRDisplayCapabilities;
class VREyeParameters;
class VRFrameData;
class VRPlatformDisplay;
class VRPose;
class VRStageParameters;

class VRDisplay final : public RefCounted<VRDisplay>, public VRPlatformDisplayClient, public EventTargetWithInlineData, public ActiveDOMObject {
    WTF_MAKE_ISO_ALLOCATED(VRDisplay);
public:
    static Ref<VRDisplay> create(ScriptExecutionContext&, WeakPtr<VRPlatformDisplay>&&);

    virtual ~VRDisplay();

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

    bool isConnected() const;
    bool isPresenting() const { return !!m_presentingLayer; };

    const VRDisplayCapabilities& capabilities() const;
    RefPtr<VRStageParameters> stageParameters() const;

    const VREyeParameters& getEyeParameters(VREye) const;

    const String& displayName() const { return m_displayName; }
    uint32_t displayId() const { return m_displayId; }

    bool getFrameData(VRFrameData&) const;

    Ref<VRPose> getPose() const;
    void resetPose();

    double depthNear() const { return m_depthNear; }
    void setDepthNear(double depthNear) { m_depthNear = depthNear; }
    double depthFar() const { return m_depthFar; }
    void setDepthFar(double depthFar) { m_depthFar = depthFar; }

    uint32_t requestAnimationFrame(Ref<RequestAnimationFrameCallback>&&);
    void cancelAnimationFrame(uint32_t);

    void requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&);
    void exitPresent(Ref<DeferredPromise>&&);

    Vector<VRLayerInit> getLayers() const;

    void submitFrame();

    // VRPlatformDisplayClient
    void platformDisplayConnected() override;
    void platformDisplayDisconnected() override;
    void platformDisplayMounted() override;
    void platformDisplayUnmounted() override;

    // ActiveDOMObject
    bool hasPendingActivity() const override;

private:
    VRDisplay(ScriptExecutionContext&, WeakPtr<VRPlatformDisplay>&&);

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

    // ActiveDOMObject
    const char* activeDOMObjectName() const override;
    bool shouldPreventEnteringBackForwardCache_DEPRECATED() const override;
    void stop() override;

    void stopPresenting();

    Document* document() { return downcast<Document>(scriptExecutionContext()); }

    WeakPtr<VRPlatformDisplay> m_display;

    RefPtr<VRDisplayCapabilities> m_capabilities;
    // We could likely store just one of the two following ones as the values should be identical
    // (except the sign of the eye to head transform offset).
    RefPtr<VREyeParameters> m_leftEyeParameters;
    RefPtr<VREyeParameters> m_rightEyeParameters;
    RefPtr<VRStageParameters> m_stageParameters;

    String m_displayName;
    uint32_t m_displayId;

    double m_depthNear { 0.01 }; // Default value from the specs.
    double m_depthFar { 10000 }; // Default value from the specs.

    RefPtr<ScriptedAnimationController> m_scriptedAnimationController;

    Optional<VRLayerInit> m_presentingLayer;
};

} // namespace WebCore
