/*
 * Copyright (C) 2018 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 "LibWebRTCUtils.h"

#if USE(LIBWEBRTC)

#include "LibWebRTCMacros.h"
#include "RTCPeerConnection.h"
#include "RTCRtpSendParameters.h"
#include <wtf/text/WTFString.h>

ALLOW_UNUSED_PARAMETERS_BEGIN

#include <webrtc/api/rtp_parameters.h>
#include <webrtc/api/rtp_transceiver_interface.h>

ALLOW_UNUSED_PARAMETERS_END

namespace WebCore {

static inline RTCRtpEncodingParameters toRTCEncodingParameters(const webrtc::RtpEncodingParameters& rtcParameters)
{
    RTCRtpEncodingParameters parameters;

    if (rtcParameters.ssrc)
        parameters.ssrc = *rtcParameters.ssrc;

    parameters.active = rtcParameters.active;
    if (rtcParameters.max_bitrate_bps)
        parameters.maxBitrate = *rtcParameters.max_bitrate_bps;
    if (rtcParameters.max_framerate)
        parameters.maxFramerate = *rtcParameters.max_framerate;
    parameters.rid = fromStdString(rtcParameters.rid);
    if (rtcParameters.scale_resolution_down_by)
        parameters.scaleResolutionDownBy = *rtcParameters.scale_resolution_down_by;

    return parameters;
}

static inline RTCRtpHeaderExtensionParameters toRTCHeaderExtensionParameters(const webrtc::RtpExtension& rtcParameters)
{
    RTCRtpHeaderExtensionParameters parameters;

    parameters.uri = fromStdString(rtcParameters.uri);
    parameters.id = rtcParameters.id;

    return parameters;
}

static inline webrtc::RtpExtension fromRTCHeaderExtensionParameters(const RTCRtpHeaderExtensionParameters& parameters)
{
    webrtc::RtpExtension rtcParameters;

    rtcParameters.uri = parameters.uri.utf8().data();
    rtcParameters.id = parameters.id;

    return rtcParameters;
}

static inline RTCRtpCodecParameters toRTCCodecParameters(const webrtc::RtpCodecParameters& rtcParameters)
{
    RTCRtpCodecParameters parameters;

    parameters.payloadType = rtcParameters.payload_type;
    parameters.mimeType = fromStdString(rtcParameters.mime_type());
    if (rtcParameters.clock_rate)
        parameters.clockRate = *rtcParameters.clock_rate;
    if (rtcParameters.num_channels)
        parameters.channels = *rtcParameters.num_channels;

    StringBuilder sdpFmtpLineBuilder;
    sdpFmtpLineBuilder.append("a=fmtp:", parameters.payloadType, ' ');

    bool isFirst = true;
    for (auto& keyValue : rtcParameters.parameters) {
        if (!isFirst)
            sdpFmtpLineBuilder.append(';');
        else
            isFirst = false;
        sdpFmtpLineBuilder.append(keyValue.first.c_str(), '=', keyValue.second.c_str());
    }
    parameters.sdpFmtpLine = sdpFmtpLineBuilder.toString();

    return parameters;
}

RTCRtpParameters toRTCRtpParameters(const webrtc::RtpParameters& rtcParameters)
{
    RTCRtpParameters parameters;

    for (auto& extension : rtcParameters.header_extensions)
        parameters.headerExtensions.append(toRTCHeaderExtensionParameters(extension));
    for (auto& codec : rtcParameters.codecs)
        parameters.codecs.append(toRTCCodecParameters(codec));

    return parameters;
}

RTCRtpSendParameters toRTCRtpSendParameters(const webrtc::RtpParameters& rtcParameters)
{
    RTCRtpSendParameters parameters { toRTCRtpParameters(rtcParameters) };

    parameters.transactionId = fromStdString(rtcParameters.transaction_id);
    for (auto& rtcEncoding : rtcParameters.encodings)
        parameters.encodings.append(toRTCEncodingParameters(rtcEncoding));

    if (rtcParameters.degradation_preference) {
        switch (*rtcParameters.degradation_preference) {
        // FIXME: Support DegradationPreference::DISABLED.
        case webrtc::DegradationPreference::DISABLED:
        case webrtc::DegradationPreference::MAINTAIN_FRAMERATE:
            parameters.degradationPreference = RTCDegradationPreference::MaintainFramerate;
            break;
        case webrtc::DegradationPreference::MAINTAIN_RESOLUTION:
            parameters.degradationPreference = RTCDegradationPreference::MaintainResolution;
            break;
        case webrtc::DegradationPreference::BALANCED:
            parameters.degradationPreference = RTCDegradationPreference::Balanced;
            break;
        };
    }
    return parameters;
}

void updateRTCRtpSendParameters(const RTCRtpSendParameters& parameters, webrtc::RtpParameters& rtcParameters)
{
    rtcParameters.transaction_id = parameters.transactionId.utf8().data();

    if (parameters.encodings.size() != rtcParameters.encodings.size()) {
        // If encodings size is different, setting parameters will fail. Let's make it so.
        rtcParameters.encodings.clear();
        return;
    }

    // We copy all current encodings parameters and only update parameters that can actually be usefully updated.
    for (size_t i = 0; i < parameters.encodings.size(); ++i) {
        rtcParameters.encodings[i].active = parameters.encodings[i].active;
        if (parameters.encodings[i].maxBitrate)
            rtcParameters.encodings[i].max_bitrate_bps = parameters.encodings[i].maxBitrate;
        if (parameters.encodings[i].maxFramerate)
            rtcParameters.encodings[i].max_framerate = parameters.encodings[i].maxFramerate;
    }

    rtcParameters.header_extensions.clear();
    for (auto& extension : parameters.headerExtensions)
        rtcParameters.header_extensions.push_back(fromRTCHeaderExtensionParameters(extension));
    // Codecs parameters are readonly

    switch (parameters.degradationPreference) {
    case RTCDegradationPreference::MaintainFramerate:
        rtcParameters.degradation_preference = webrtc::DegradationPreference::MAINTAIN_FRAMERATE;
        break;
    case RTCDegradationPreference::MaintainResolution:
        rtcParameters.degradation_preference = webrtc::DegradationPreference::MAINTAIN_RESOLUTION;
        break;
    case RTCDegradationPreference::Balanced:
        rtcParameters.degradation_preference = webrtc::DegradationPreference::BALANCED;
        break;
    }
}

RTCRtpTransceiverDirection toRTCRtpTransceiverDirection(webrtc::RtpTransceiverDirection rtcDirection)
{
    switch (rtcDirection) {
    case webrtc::RtpTransceiverDirection::kSendRecv:
        return RTCRtpTransceiverDirection::Sendrecv;
    case webrtc::RtpTransceiverDirection::kSendOnly:
        return RTCRtpTransceiverDirection::Sendonly;
    case webrtc::RtpTransceiverDirection::kRecvOnly:
        return RTCRtpTransceiverDirection::Recvonly;
    case webrtc::RtpTransceiverDirection::kInactive:
    case webrtc::RtpTransceiverDirection::kStopped:
        return RTCRtpTransceiverDirection::Inactive;
    };

    RELEASE_ASSERT_NOT_REACHED();
}

webrtc::RtpTransceiverDirection fromRTCRtpTransceiverDirection(RTCRtpTransceiverDirection direction)
{
    switch (direction) {
    case RTCRtpTransceiverDirection::Sendrecv:
        return webrtc::RtpTransceiverDirection::kSendRecv;
    case RTCRtpTransceiverDirection::Sendonly:
        return webrtc::RtpTransceiverDirection::kSendOnly;
    case RTCRtpTransceiverDirection::Recvonly:
        return webrtc::RtpTransceiverDirection::kRecvOnly;
    case RTCRtpTransceiverDirection::Inactive:
        return webrtc::RtpTransceiverDirection::kInactive;
    };

    RELEASE_ASSERT_NOT_REACHED();
}

webrtc::RtpTransceiverInit fromRtpTransceiverInit(const RTCRtpTransceiverInit& init)
{
    webrtc::RtpTransceiverInit rtcInit;
    rtcInit.direction = fromRTCRtpTransceiverDirection(init.direction);
    for (auto& stream : init.streams)
        rtcInit.stream_ids.push_back(stream->id().utf8().data());
    return rtcInit;
}

ExceptionCode toExceptionCode(webrtc::RTCErrorType type)
{
    switch (type) {
    case webrtc::RTCErrorType::INVALID_PARAMETER:
        return InvalidAccessError;
    case webrtc::RTCErrorType::INVALID_RANGE:
        return RangeError;
    case webrtc::RTCErrorType::SYNTAX_ERROR:
        return SyntaxError;
    case webrtc::RTCErrorType::INVALID_STATE:
        return InvalidStateError;
    case webrtc::RTCErrorType::INVALID_MODIFICATION:
        return InvalidModificationError;
    case webrtc::RTCErrorType::NETWORK_ERROR:
        return NetworkError;
    default:
        return OperationError;
    }
}

Exception toException(const webrtc::RTCError& error)
{
    ASSERT(!error.ok());

    return Exception { toExceptionCode(error.type()), error.message() };
}

} // namespace WebCore

#endif // USE(LIBWEBRTC)
