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

#include "config.h"
#include "MediaCapabilities.h"

#include "ContentType.h"
#include "Document.h"
#include "JSMediaCapabilitiesDecodingInfo.h"
#include "JSMediaCapabilitiesEncodingInfo.h"
#include "MediaCapabilitiesDecodingInfo.h"
#include "MediaCapabilitiesEncodingInfo.h"
#include "MediaDecodingConfiguration.h"
#include "MediaEncodingConfiguration.h"
#include "MediaEngineConfigurationFactory.h"
#include "Settings.h"
#include <wtf/HashSet.h>

namespace WebCore {

static const HashSet<String>& bucketMIMETypes()
{
    // A "bucket" MIME types is one whose container type does not uniquely specify a codec.
    // See: https://tools.ietf.org/html/rfc6381
    static NeverDestroyed<HashSet<String>> bucketMIMETypes = HashSet<String>({
        "audio/3gpp",
        "video/3gpp",
        "audio/3gpp2",
        "video/3gpp2",
        "audio/mp4",
        "video/mp4",
        "application/mp4",
        "video/quicktime",
        "application/mp21",
        "audio/vnd.apple.mpegurl",
        "video/vnd.apple.mpegurl",
        "audio/ogg",
        "video/ogg",
        "video/webm",
        "audio/webm",
    });
    return bucketMIMETypes;
}

static bool isValidMediaMIMEType(const ContentType& contentType)
{
    // 2.1.4. MIME types
    // https://wicg.github.io/media-capabilities/#valid-media-mime-type
    // A valid media MIME type is a string that is a valid MIME type per [mimesniff]. If the MIME type does
    // not imply a codec, the string MUST also have one and only one parameter that is named codecs with a
    // value describing a single media codec. Otherwise, it MUST contain no parameters.
    if (contentType.isEmpty())
        return false;

    auto codecs = contentType.codecs();

    // FIXME: The spec requires that the "codecs" parameter is the only parameter present.
    if (bucketMIMETypes().contains(contentType.containerType()))
        return codecs.size() == 1;
    return !codecs.size();
}

static bool isValidVideoMIMEType(const ContentType& contentType)
{
    // 2.1.4 MIME Types
    // https://wicg.github.io/media-capabilities/#valid-video-mime-type
    // A valid video MIME type is a string that is a valid media MIME type and for which the type per [RFC7231]
    // is either video or application.
    if (!isValidMediaMIMEType(contentType))
        return false;

    auto containerType = contentType.containerType();
    if (!startsWithLettersIgnoringASCIICase(containerType, "video/") && !startsWithLettersIgnoringASCIICase(containerType, "application/"))
        return false;

    return true;
}

static bool isValidAudioMIMEType(const ContentType& contentType)
{
    // 2.1.4 MIME Types
    // https://wicg.github.io/media-capabilities/#valid-audio-mime-type
    // A valid audio MIME type is a string that is a valid media MIME type and for which the type per [RFC7231]
    // is either audio or application.
    if (!isValidMediaMIMEType(contentType))
        return false;

    auto containerType = contentType.containerType();
    if (!startsWithLettersIgnoringASCIICase(containerType, "audio/") && !startsWithLettersIgnoringASCIICase(containerType, "application/"))
        return false;

    return true;
}

static bool isValidVideoConfiguration(const VideoConfiguration& configuration)
{
    // 2.1.5. VideoConfiguration
    // https://wicg.github.io/media-capabilities/#valid-video-configuration
    // 1. If configuration’s contentType is not a valid video MIME type, return false and abort these steps.
    if (!isValidVideoMIMEType(ContentType(configuration.contentType)))
        return false;

    // 2. If none of the following is true, return false and abort these steps:
    //   o. Applying the rules for parsing floating-point number values to configuration’s framerate
    //      results in a number that is finite and greater than 0.
    if (!std::isfinite(configuration.framerate) || configuration.framerate <= 0)
        return false;

    // 3. Return true.
    return true;
}

static bool isValidAudioConfiguration(const AudioConfiguration& configuration)
{
    // 2.1.6. AudioConfiguration
    // https://wicg.github.io/media-capabilities/#audioconfiguration
    // 1. If configuration’s contentType is not a valid audio MIME type, return false and abort these steps.
    if (!isValidAudioMIMEType(ContentType(configuration.contentType)))
        return false;

    // 2. Return true.
    return true;
}

static bool isValidMediaConfiguration(const MediaConfiguration& configuration)
{
    // 2.1.1. MediaConfiguration
    // https://wicg.github.io/media-capabilities/#mediaconfiguration
    // For a MediaConfiguration to be a valid MediaConfiguration, audio or video MUST be present.
    if (!configuration.video && !configuration.audio)
        return false;

    if (configuration.video && !isValidVideoConfiguration(configuration.video.value()))
        return false;

    if (configuration.audio && !isValidAudioConfiguration(configuration.audio.value()))
        return false;

    return true;
}

void MediaCapabilities::decodingInfo(Document& document, MediaDecodingConfiguration&& configuration, Ref<DeferredPromise>&& promise)
{
    // 2.4 Media Capabilities Interface
    // https://wicg.github.io/media-capabilities/#media-capabilities-interface

    // 1. If configuration is not a valid MediaConfiguration, return a Promise rejected with a TypeError.
    // 2. If configuration.video is present and is not a valid video configuration, return a Promise rejected with a TypeError.
    // 3. If configuration.audio is present and is not a valid audio configuration, return a Promise rejected with a TypeError.
    if (!isValidMediaConfiguration(configuration)) {
        promise->reject(TypeError);
        return;
    }

    if (!document.settings().mediaCapabilitiesExtensionsEnabled() && configuration.video)
        configuration.video.value().alphaChannel.reset();

    // 4. Let p be a new promise.
    // 5. In parallel, run the create a MediaCapabilitiesInfo algorithm with configuration and resolve p with its result.
    // 6. Return p.
    m_taskQueue.enqueueTask([configuration = WTFMove(configuration), promise = WTFMove(promise)] () mutable {

        // 2.2.3 If configuration is of type MediaDecodingConfiguration, run the following substeps:
        MediaEngineConfigurationFactory::DecodingConfigurationCallback callback = [promise = WTFMove(promise)] (auto info) mutable {
            // 2.2.3.1. If the user agent is able to decode the media represented by
            // configuration, set supported to true. Otherwise set it to false.
            // 2.2.3.2. If the user agent is able to decode the media represented by
            // configuration at a pace that allows a smooth playback, set smooth to
            // true. Otherwise set it to false.
            // 2.2.3.3. If the user agent is able to decode the media represented by
            // configuration in a power efficient manner, set powerEfficient to
            // true. Otherwise set it to false. The user agent SHOULD NOT take into
            // consideration the current power source in order to determine the
            // decoding power efficiency unless the device’s power source has side
            // effects such as enabling different decoding modules.
            promise->resolve<IDLDictionary<MediaCapabilitiesDecodingInfo>>(WTFMove(info));
        };

        MediaEngineConfigurationFactory::createDecodingConfiguration(WTFMove(configuration), WTFMove(callback));
    });
}

void MediaCapabilities::encodingInfo(MediaEncodingConfiguration&& configuration, Ref<DeferredPromise>&& promise)
{
    // 2.4 Media Capabilities Interface
    // https://wicg.github.io/media-capabilities/#media-capabilities-interface

    // 1. If configuration is not a valid MediaConfiguration, return a Promise rejected with a TypeError.
    // 2. If configuration.video is present and is not a valid video configuration, return a Promise rejected with a TypeError.
    // 3. If configuration.audio is present and is not a valid audio configuration, return a Promise rejected with a TypeError.
    if (!isValidMediaConfiguration(configuration)) {
        promise->reject(TypeError);
        return;
    }

    // 4. Let p be a new promise.
    // 5. In parallel, run the create a MediaCapabilitiesInfo algorithm with configuration and resolve p with its result.
    // 6. Return p.
    m_taskQueue.enqueueTask([configuration = WTFMove(configuration), promise = WTFMove(promise)] () mutable {

        // 2.2.4. If configuration is of type MediaEncodingConfiguration, run the following substeps:
        MediaEngineConfigurationFactory::EncodingConfigurationCallback callback = [promise = WTFMove(promise)] (auto info) mutable {
            // 2.2.4.1. If the user agent is able to encode the media
            // represented by configuration, set supported to true. Otherwise
            // set it to false.
            // 2.2.4.2. If the user agent is able to encode the media
            // represented by configuration at a pace that allows encoding
            // frames at the same pace as they are sent to the encoder, set
            // smooth to true. Otherwise set it to false.
            // 2.2.4.3. If the user agent is able to encode the media
            // represented by configuration in a power efficient manner, set
            // powerEfficient to true. Otherwise set it to false. The user agent
            // SHOULD NOT take into consideration the current power source in
            // order to determine the encoding power efficiency unless the
            // device’s power source has side effects such as enabling different
            // encoding modules.
            promise->resolve<IDLDictionary<MediaCapabilitiesEncodingInfo>>(WTFMove(info));
        };

        MediaEngineConfigurationFactory::createEncodingConfiguration(WTFMove(configuration), WTFMove(callback));

    });
}

}
