/*
 * Copyright (C) 2016 Metrological Group B.V.
 * Copyright (C) 2016 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.
 */

#include "config.h"
#include "MediaKeyStatusMap.h"

#if ENABLE(ENCRYPTED_MEDIA)

#include "JSMediaKeyStatusMap.h"
#include "MediaKeySession.h"
#include "SharedBuffer.h"

namespace WebCore {

MediaKeyStatusMap::MediaKeyStatusMap(const MediaKeySession& session)
    : m_session(&session)
{
}

MediaKeyStatusMap::~MediaKeyStatusMap() = default;

void MediaKeyStatusMap::detachSession()
{
    m_session = nullptr;
}

unsigned long MediaKeyStatusMap::size()
{
    if (!m_session)
        return 0;
    return m_session->statuses().size();
}

static bool keyIdsMatch(const SharedBuffer& a, const BufferSource& b)
{
    auto length = a.size();
    if (!length || length != b.length())
        return false;
    return !std::memcmp(a.data(), b.data(), length);
}

bool MediaKeyStatusMap::has(const BufferSource& keyId)
{
    if (!m_session)
        return false;

    auto& statuses = m_session->statuses();
    return std::any_of(statuses.begin(), statuses.end(),
        [&keyId] (auto& it) { return keyIdsMatch(it.first, keyId); });
}

JSC::JSValue MediaKeyStatusMap::get(JSC::JSGlobalObject& state, const BufferSource& keyId)
{
    if (!m_session)
        return JSC::jsUndefined();

    auto& statuses = m_session->statuses();
    auto it = std::find_if(statuses.begin(), statuses.end(),
        [&keyId] (auto& it) { return keyIdsMatch(it.first, keyId); });

    if (it == statuses.end())
        return JSC::jsUndefined();
    return convertEnumerationToJS(state, it->second);
}

MediaKeyStatusMap::Iterator::Iterator(MediaKeyStatusMap& map)
    : m_map(map)
{
}

std::optional<KeyValuePair<BufferSource::VariantType, MediaKeyStatus>> MediaKeyStatusMap::Iterator::next()
{
    if (!m_map->m_session)
        return std::nullopt;

    auto& statuses = m_map->m_session->statuses();
    if (m_index >= statuses.size())
        return std::nullopt;

    auto& pair = statuses[m_index++];
    auto buffer = ArrayBuffer::create(pair.first->data(), pair.first->size());
    return KeyValuePair<BufferSource::VariantType, MediaKeyStatus> { RefPtr<ArrayBuffer>(WTFMove(buffer)), pair.second };
}

} // namespace WebCore

#endif // ENABLE(ENCRYPTED_MEDIA)
