/*
 * 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 "MediaPlayerPrivate.h"
#include "SharedBuffer.h"
#include <wtf/Condition.h>
#include <wtf/VectorHash.h>

namespace WebCore {

class Key : public RefCounted<Key> {
public:
    using KeyStatus = CDMInstanceSession::KeyStatus;

    static RefPtr<Key> create(KeyStatus status, Vector<uint8_t>&& keyID, Vector<uint8_t>&& keyValue)
    {
        return adoptRef(*new Key(status, WTFMove(keyID), WTFMove(keyValue)));
    }
    Ref<SharedBuffer> idAsSharedBuffer() const { return SharedBuffer::create(m_id.data(), m_id.size()); }

    const Vector<uint8_t>& id() const { return m_id; }
    const Vector<uint8_t>& value() const { return m_value; }
    Vector<uint8_t>& value() { return m_value; }
    KeyStatus status() const { return m_status; }

    String idAsString() const;
    String valueAsString() const;

    // Two keys are equal if they have the same ID, ignoring key value and status.
    friend bool operator==(const Key &k1, const Key &k2) { return k1.m_id == k2.m_id; }
    friend bool operator==(const Key &k, const Vector<uint8_t>& keyID) { return k.m_id == keyID; }
    friend bool operator==(const Vector<uint8_t>& keyID, const Key &k) { return k == keyID; }

private:
    void addSessionReference() { ASSERT(isMainThread()); m_numSessionReferences++; }
    void removeSessionReference() { ASSERT(isMainThread()); m_numSessionReferences--; }
    unsigned numSessionReferences() const { ASSERT(isMainThread()); return m_numSessionReferences; }
    friend class KeyStore;

    Key(KeyStatus status, Vector<uint8_t>&& keyID, Vector<uint8_t>&& keyValue)
        : m_status(status), m_id(WTFMove(keyID)), m_value(WTFMove(keyValue)) { }

    KeyStatus m_status;
    Vector<uint8_t> m_id;
    Vector<uint8_t> m_value;
    unsigned m_numSessionReferences { 0 };
};

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

    bool containsKeyID(const Vector<uint8_t>& keyID) const;
    void merge(const KeyStore& other);
    void removeAllKeysFrom(const KeyStore& other);
    void removeAllKeys() { m_keys.clear(); }
    bool addKeys(Vector<RefPtr<Key>>&&);
    bool add(RefPtr<Key>&&);
    bool remove(const RefPtr<Key>&);
    unsigned numKeys() const { return m_keys.size(); }
    const Vector<uint8_t>& keyValue(const Vector<uint8_t>& keyID) const;
    KeyStatusVector allKeysAsReleased() const;
    KeyStatusVector convertToJSKeyStatusVector() 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<Key>> m_keys;
};

class CDMInstanceProxy;

// 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 = 5_s;

    virtual ~CDMProxy() = default;

    void updateKeyStore(const KeyStore& newKeyStore);
    void setInstance(CDMInstanceProxy*);

protected:
    Vector<uint8_t> keyValue(const Vector<uint8_t>& keyID) const;
    bool keyAvailable(const Vector<uint8_t>& keyID) const;
    bool keyAvailableUnlocked(const Vector<uint8_t>& keyID) const;
    Optional<Vector<uint8_t>> tryWaitForKey(const Vector<uint8_t>& keyID) const;
    Optional<Vector<uint8_t>> getOrWaitForKey(const Vector<uint8_t>& keyID) const;
    void startedWaitingForKey() const;
    void stoppedWaitingForKey() const;

private:
    mutable Lock m_instanceMutex;
    CDMInstanceProxy* m_instance;

    mutable Lock m_keysMutex;
    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.
    KeyStore m_keyStore;
};

// Base class for common session management code and for communicating messages
// from "real CDM" state changes to JS.
class CDMInstanceProxy : public CDMInstance {
public:
    CDMInstanceProxy() = default;
    virtual ~CDMInstanceProxy() = default;

    // Main-thread only.
    void setProxy(Ref<CDMProxy>&& proxy)
    {
        m_cdmProxy = WTFMove(proxy);
        m_cdmProxy->setInstance(this);
    }
    void mergeKeysFrom(const KeyStore&);
    void removeAllKeysFrom(const KeyStore&);

    // Media player query methods - main thread only.
    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();

protected:
    void trackSession(const RefPtr<CDMInstanceSession> session) { m_sessions.append(session); }

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;
    Vector<RefPtr<CDMInstanceSession>> m_sessions;

    KeyStore m_keyStore;
};

} // namespace WebCore

#endif // ENABLE(ENCRYPTED_MEDIA)
