/*
 * Copyright (C) 2020 Metrological Group B.V.
 * Copyright (C) 2020 Igalia S.L.
 *
 * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * HOLDER OR 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(ENCRYPTED_MEDIA)

#include "CDMInstance.h"
#include "CDMInstanceSession.h"
#include "SharedBuffer.h"
#include <wtf/BoxPtr.h>
#include <wtf/Condition.h>
#include <wtf/Lock.h>

#if ENABLE(THUNDER)
#include "CDMOpenCDMTypes.h"
#endif

namespace WebCore {

class MediaPlayer;

using KeyIDType = Vector<uint8_t>;
using KeyHandleValueVariant = std::variant<
    Vector<uint8_t>
#if ENABLE(THUNDER)
    , BoxPtr<OpenCDMSession>
#endif
>;

class KeyHandle : public ThreadSafeRefCounted<KeyHandle> {
public:
    using KeyStatus = CDMInstanceSession::KeyStatus;

    static RefPtr<KeyHandle> create(KeyStatus status, KeyIDType&& keyID, KeyHandleValueVariant&& keyHandleValue)
    {
        return adoptRef(*new KeyHandle(status, WTFMove(keyID), WTFMove(keyHandleValue)));
    }
    Ref<SharedBuffer> idAsSharedBuffer() const { return SharedBuffer::create(m_id.data(), m_id.size()); }

    bool takeValueIfDifferent(KeyHandleValueVariant&&);

    const KeyIDType& id() const { return m_id; }
    const KeyHandleValueVariant& value() const { return m_value; }
    KeyHandleValueVariant& value() { return m_value; }
    KeyStatus status() const { return m_status; }
    void mergeKeyInto(RefPtr<KeyHandle>&& other)
    {
        m_status = other->m_status;
        m_value = other->m_value;
        m_numSessionReferences += other->m_numSessionReferences;
    }
    bool isStatusCurrentlyValid()
    {
        return m_status == CDMInstanceSession::KeyStatus::Usable || m_status == CDMInstanceSession::KeyStatus::OutputRestricted
            || m_status == CDMInstanceSession::KeyStatus::OutputDownscaled;
    }

    String idAsString() const;

    // Two keys are equal if they have the same ID, ignoring key value and status.
    friend bool operator==(const KeyHandle &k1, const KeyHandle &k2) { return k1.m_id == k2.m_id; }
    friend bool operator==(const KeyHandle &k, const KeyIDType& keyID) { return k.m_id == keyID; }
    friend bool operator==(const KeyIDType& keyID, const KeyHandle &k) { return k == keyID; }
    friend bool operator<(const KeyHandle& k1, const KeyHandle& k2)
    {
        // Key IDs are compared as follows: For key IDs A of length m and
        // B of length n, assigned such that m <= n, let A < B if and only
        // if the m octets of A are less in lexicographical order than the
        // first m octets of B or those octets are equal and m < n.
        // 6.1 https://www.w3.org/TR/encrypted-media/
        int isDifference = memcmp(k1.m_id.data(), k2.m_id.data(), std::min(k1.m_id.size(), k2.m_id.size()));
        if (isDifference)
            return isDifference < 0;
        // The keys are equal to the shared length, the shorter string
        // is therefore less than the longer one in a lexicographical
        // ordering.
        return k1.m_id.size() < k2.m_id.size();
    }

private:
    void addSessionReference() { ASSERT(isMainThread()); m_numSessionReferences++; }
    void removeSessionReference() { ASSERT(isMainThread()); m_numSessionReferences--; }
    int numSessionReferences() const { ASSERT(isMainThread()); return m_numSessionReferences; }
    bool hasReferences() const { ASSERT(isMainThread()); return m_numSessionReferences > 0; }
    friend class KeyStore;
    friend class ReferenceAwareKeyStore;

    KeyHandle(KeyStatus status, KeyIDType&& keyID, KeyHandleValueVariant&& keyHandleValue)
        : m_status(status), m_id(WTFMove(keyID)), m_value(WTFMove(keyHandleValue)) { }

    KeyStatus m_status;
    KeyIDType m_id;
    KeyHandleValueVariant m_value;
    int m_numSessionReferences { 0 };
};

class KeyStore {
public:
    using KeyStatusVector = CDMInstanceSession::KeyStatusVector;

    KeyStore() = default;
    virtual ~KeyStore() = default;

    bool containsKeyID(const KeyIDType&) const;
    void merge(const KeyStore&);
    void unrefAllKeysFrom(const KeyStore&);
    void unrefAllKeys();
    bool addKeys(Vector<RefPtr<KeyHandle>>&&);
    bool add(RefPtr<KeyHandle>&&);
    bool unref(const RefPtr<KeyHandle>&);
    bool hasKeys() const { return m_keys.size(); }
    unsigned numKeys() const { return m_keys.size(); }
    const RefPtr<KeyHandle>& keyHandle(const KeyIDType&) const;
    KeyStatusVector allKeysAs(CDMInstanceSession::KeyStatus) const;
    KeyStatusVector convertToJSKeyStatusVector() const;
    bool isEmpty() const { return m_keys.isEmpty(); }
    virtual void addSessionReferenceTo(const RefPtr<KeyHandle>&) const { }
    virtual void removeSessionReferenceFrom(const RefPtr<KeyHandle>&) const { };

    auto begin() { return m_keys.begin(); }
    auto begin() const { return m_keys.begin(); }
    auto end() { return m_keys.end(); }
    auto end() const { return m_keys.end(); }
    auto rbegin() { return m_keys.rbegin(); }
    auto rbegin() const { return m_keys.rbegin(); }
    auto rend() { return m_keys.rend(); }
    auto rend() const { return m_keys.rend(); }

private:
    Vector<RefPtr<KeyHandle>> m_keys;
};

class ReferenceAwareKeyStore : public KeyStore {
public:
    virtual ~ReferenceAwareKeyStore() = default;
    void addSessionReferenceTo(const RefPtr<KeyHandle>& key) const final { key->addSessionReference(); }
    void removeSessionReferenceFrom(const RefPtr<KeyHandle>& key) const final { key->removeSessionReference(); }
};

class CDMInstanceProxy;
class CDMProxyDecryptionClient;

// Handle to a "real" CDM, not the JavaScript facade. This can be used
// from background threads (i.e. decryptors).
class CDMProxy : public ThreadSafeRefCounted<CDMProxy> {
public:
    static constexpr Seconds MaxKeyWaitTimeSeconds = 7_s;

    virtual ~CDMProxy() = default;

    void updateKeyStore(const KeyStore&);
    void unrefAllKeysFrom(const KeyStore&);
    void setInstance(CDMInstanceProxy*);
    void abortWaitingForKey() const;

protected:
    RefPtr<KeyHandle> keyHandle(const KeyIDType&) const;
    bool keyAvailable(const KeyIDType&) const;
    bool keyAvailableUnlocked(const KeyIDType&) const WTF_REQUIRES_LOCK(m_keysLock);
    std::optional<Ref<KeyHandle>> tryWaitForKeyHandle(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
    std::optional<Ref<KeyHandle>> getOrWaitForKeyHandle(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
    std::optional<KeyHandleValueVariant> getOrWaitForKeyValue(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
    void startedWaitingForKey() const;
    void stoppedWaitingForKey() const;
    const CDMInstanceProxy* instance() const;

private:
    mutable Lock m_instanceLock;
    CDMInstanceProxy* m_instance WTF_GUARDED_BY_LOCK(m_instanceLock);

    mutable Lock m_keysLock;
    mutable Condition m_keysCondition;
    // FIXME: Duplicated key stores in the instance and the proxy are probably not needed, but simplified
    // the initial implementation in terms of threading invariants.
    ReferenceAwareKeyStore m_keyStore WTF_GUARDED_BY_LOCK(m_keysLock);
};

class CDMProxyFactory {
public:
    virtual ~CDMProxyFactory()
    {
        unregisterFactory(*this);
    };

    WEBCORE_EXPORT static void registerFactory(CDMProxyFactory&);
    WEBCORE_EXPORT static void unregisterFactory(CDMProxyFactory&);
    WEBCORE_EXPORT static WARN_UNUSED_RETURN RefPtr<CDMProxy> createCDMProxyForKeySystem(const String&);

protected:
    virtual RefPtr<CDMProxy> createCDMProxy(const String&) = 0;
    virtual bool supportsKeySystem(const String&) = 0;

private:
    // Platform-specific function that's called when the list of
    // registered CDMProxyFactory objects is queried for the first time.
    static Vector<CDMProxyFactory*> platformRegisterFactories();
    WEBCORE_EXPORT static Vector<CDMProxyFactory*>& registeredFactories();
};

class CDMInstanceProxy;

class CDMInstanceSessionProxy : public CDMInstanceSession, public CanMakeWeakPtr<CDMInstanceSessionProxy, WeakPtrFactoryInitialization::Eager> {
protected:
    CDMInstanceSessionProxy(CDMInstanceProxy&);
    const WeakPtr<CDMInstanceProxy>& cdmInstanceProxy() const { return m_instance; }

private:
    WeakPtr<CDMInstanceProxy> m_instance;
};

// Base class for common session management code and for communicating messages
// from "real CDM" state changes to JS.
class CDMInstanceProxy : public CDMInstance, public CanMakeWeakPtr<CDMInstanceProxy> {
public:
    explicit CDMInstanceProxy(const String& keySystem)
    {
        ASSERT(isMainThread());
        m_cdmProxy = CDMProxyFactory::createCDMProxyForKeySystem(keySystem);
        if (m_cdmProxy)
            m_cdmProxy->setInstance(this);
    }
    virtual ~CDMInstanceProxy() = default;

    // Main-thread only.
    void mergeKeysFrom(const KeyStore&);
    void unrefAllKeysFrom(const KeyStore&);

    // Media player query methods - main thread only.
    const RefPtr<CDMProxy>& proxy() const { ASSERT(isMainThread()); return m_cdmProxy; }
    virtual bool isWaitingForKey() const { ASSERT(isMainThread()); return m_numDecryptorsWaitingForKey > 0; }
    void setPlayer(MediaPlayer* player) { ASSERT(isMainThread()); m_player = player; }

    // Proxy methods - must be thread-safe.
    void startedWaitingForKey();
    void stoppedWaitingForKey();

private:
    RefPtr<CDMProxy> m_cdmProxy;
    // FIXME: WeakPtr for the m_player? This is accessed from background and main threads, it's
    // concerning we could be accessing it in the middle of a shutdown on the main-thread, eh?
    // As a CDMProxy, we ***should*** be turned off before this pointer ever goes bad.
    MediaPlayer* m_player { nullptr }; // FIXME: MainThread<T>?

    std::atomic<int> m_numDecryptorsWaitingForKey { 0 };
};

class CDMProxyDecryptionClient : public CanMakeWeakPtr<CDMProxyDecryptionClient, WeakPtrFactoryInitialization::Eager> {
public:
    virtual bool isAborting() = 0;
    virtual ~CDMProxyDecryptionClient() = default;
};

} // namespace WebCore

#endif // ENABLE(ENCRYPTED_MEDIA)
