/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "channels/audio-input/audio-buffer.h"
#include "plugins/guacai/guacai-messages.h"
#include "rdp.h"

#include <freerdp/dvc.h>
#include <guacamole/client.h>
#include <winpr/stream.h>

#include <stdlib.h>

/**
 * Reads AUDIO_FORMAT data from the given stream into the given struct.
 *
 * @param stream
 *     The stream to read AUDIO_FORMAT data from.
 *
 * @param format
 *     The structure to populate with data from the stream.
 */
static void guac_rdp_ai_read_format(wStream* stream,
        guac_rdp_ai_format* format) {

    /* Read audio format into structure */
    Stream_Read_UINT16(stream, format->tag); /* wFormatTag */
    Stream_Read_UINT16(stream, format->channels); /* nChannels */
    Stream_Read_UINT32(stream, format->rate); /* nSamplesPerSec */
    Stream_Read_UINT32(stream, format->bytes_per_sec); /* nAvgBytesPerSec */
    Stream_Read_UINT16(stream, format->block_align); /* nBlockAlign */
    Stream_Read_UINT16(stream, format->bps); /* wBitsPerSample */
    Stream_Read_UINT16(stream, format->data_size); /* cbSize */

    /* Read arbitrary data block (if applicable) */
    if (format->data_size != 0) {
        format->data = Stream_Pointer(stream); /* data */
        Stream_Seek(stream, format->data_size);
    }

}

/**
 * Writes AUDIO_FORMAT data to the given stream from the given struct.
 *
 * @param stream
 *     The stream to write AUDIO_FORMAT data to.
 *
 * @param format
 *     The structure containing the data that should be written to the stream.
 */
static void guac_rdp_ai_write_format(wStream* stream,
        guac_rdp_ai_format* format) {

    /* Write audio format into structure */
    Stream_Write_UINT16(stream, format->tag); /* wFormatTag */
    Stream_Write_UINT16(stream, format->channels); /* nChannels */
    Stream_Write_UINT32(stream, format->rate); /* nSamplesPerSec */
    Stream_Write_UINT32(stream, format->bytes_per_sec); /* nAvgBytesPerSec */
    Stream_Write_UINT16(stream, format->block_align); /* nBlockAlign */
    Stream_Write_UINT16(stream, format->bps); /* wBitsPerSample */
    Stream_Write_UINT16(stream, format->data_size); /* cbSize */

    /* Write arbitrary data block (if applicable) */
    if (format->data_size != 0)
        Stream_Write(stream, format->data, format->data_size);

}

/**
 * Sends a Data Incoming PDU along the given channel. A Data Incoming PDU is
 * used by the client to indicate to the server that format or audio data is
 * about to be sent.
 *
 * @param channel
 *     The channel along which the PDU should be sent.
 */
static void guac_rdp_ai_send_incoming_data(IWTSVirtualChannel* channel) {

    /* Build data incoming PDU */
    wStream* stream = Stream_New(NULL, 1);
    Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_DATA_INCOMING); /* MessageId */

    /* Send stream */
    channel->Write(channel, (UINT32) Stream_GetPosition(stream),
            Stream_Buffer(stream), NULL);
    Stream_Free(stream, TRUE);

}

/**
 * Sends a Data PDU along the given channel. A Data PDU is used by the client
 * to send actual audio data following a Data Incoming PDU.
 *
 * @param channel
 *     The channel along which the PDU should be sent.
 *
 * @param buffer
 *     The audio data to send.
 *
 * @param length
 *     The number of bytes of audio data to send.
 */
static void guac_rdp_ai_send_data(IWTSVirtualChannel* channel,
        char* buffer, int length) {

    /* Build data PDU */
    wStream* stream = Stream_New(NULL, length + 1);
    Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_DATA); /* MessageId */
    Stream_Write(stream, buffer, length); /* Data */

    /* Send stream */
    channel->Write(channel, (UINT32) Stream_GetPosition(stream),
            Stream_Buffer(stream), NULL);
    Stream_Free(stream, TRUE);

}

/**
 * Sends a Sound Formats PDU along the given channel. A Sound Formats PDU is
 * used by the client to indicate to the server which formats of audio it
 * supports (in response to the server sending exactly the same type of PDU).
 * This PDU MUST be preceded by the Data Incoming PDU.
 *
 * @param channel
 *     The channel along which the PDU should be sent.
 *
 * @param formats
 *     An array of all supported formats.
 *
 * @param num_formats
 *     The number of entries in the formats array.
 */
static void guac_rdp_ai_send_formats(IWTSVirtualChannel* channel,
        guac_rdp_ai_format* formats, int num_formats) {

    int index;
    int packet_size = 9;

    /* Calculate packet size */
    for (index = 0; index < num_formats; index++)
        packet_size += 18 + formats[index].data_size;

    wStream* stream = Stream_New(NULL, packet_size);

    /* Write header */
    Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_FORMATS); /* MessageId */
    Stream_Write_UINT32(stream, num_formats); /* NumFormats */
    Stream_Write_UINT32(stream, packet_size); /* cbSizeFormatsPacket  */

    /* Write all formats */
    for (index = 0; index < num_formats; index++)
        guac_rdp_ai_write_format(stream, &(formats[index]));

    /* Send PDU */
    channel->Write(channel, (UINT32) Stream_GetPosition(stream),
            Stream_Buffer(stream), NULL);
    Stream_Free(stream, TRUE);

}

/**
 * Sends an Open Reply PDU along the given channel. An Open Reply PDU is
 * used by the client to acknowledge the successful opening of the AUDIO_INPUT
 * channel.
 *
 * @param channel
 *     The channel along which the PDU should be sent.
 *
 * @param result
 *     The HRESULT code to send to the server indicating success, failure, etc.
 */
static void guac_rdp_ai_send_open_reply(IWTSVirtualChannel* channel,
        UINT32 result) {

    /* Build open reply PDU */
    wStream* stream = Stream_New(NULL, 5);
    Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_OPEN_REPLY); /* MessageId */
    Stream_Write_UINT32(stream, result); /* Result */

    /* Send stream */
    channel->Write(channel, (UINT32) Stream_GetPosition(stream),
            Stream_Buffer(stream), NULL);
    Stream_Free(stream, TRUE);

}

/**
 * Sends a Format Change PDU along the given channel. A Format Change PDU is
 * used by the client to acknowledge the format being used for data sent
 * along the AUDIO_INPUT channel.
 *
 * @param channel
 *     The channel along which the PDU should be sent.
 *
 * @param format
 *     The index of the format being acknowledged, which must be the index of
 *     the format within the original Sound Formats PDU received from the
 *     server.
 */
static void guac_rdp_ai_send_formatchange(IWTSVirtualChannel* channel,
        UINT32 format) {

    /* Build format change PDU */
    wStream* stream = Stream_New(NULL, 5);
    Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_FORMATCHANGE); /* MessageId */
    Stream_Write_UINT32(stream, format); /* NewFormat */

    /* Send stream */
    channel->Write(channel, (UINT32) Stream_GetPosition(stream),
            Stream_Buffer(stream), NULL);
    Stream_Free(stream, TRUE);

}

void guac_rdp_ai_process_version(guac_client* client,
        IWTSVirtualChannel* channel, wStream* stream) {

    UINT32 version;
    Stream_Read_UINT32(stream, version);

    /* Warn if server's version number is incorrect */
    if (version != 1)
        guac_client_log(client, GUAC_LOG_WARNING,
                "Server reports AUDIO_INPUT version %i, not 1", version);

    /* Build response version PDU */
    wStream* response = Stream_New(NULL, 5);
    Stream_Write_UINT8(response,  GUAC_RDP_MSG_SNDIN_VERSION); /* MessageId */
    Stream_Write_UINT32(response, 1); /* Version */

    /* Send response */
    channel->Write(channel, (UINT32) Stream_GetPosition(response),
            Stream_Buffer(response), NULL);
    Stream_Free(response, TRUE);

}

void guac_rdp_ai_process_formats(guac_client* client,
        IWTSVirtualChannel* channel, wStream* stream) {

    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
    guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input;

    UINT32 num_formats;
    Stream_Read_UINT32(stream, num_formats); /* NumFormats */
    Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */

    UINT32 index;
    for (index = 0; index < num_formats; index++) {

        guac_rdp_ai_format format;
        guac_rdp_ai_read_format(stream, &format);

        /* Ignore anything but WAVE_FORMAT_PCM */
        if (format.tag != GUAC_RDP_WAVE_FORMAT_PCM)
            continue;

        /* Set output format of internal audio buffer to match RDP server */
        guac_rdp_audio_buffer_set_output(audio_buffer, format.rate,
                format.channels, format.bps / 8);

        /* Accept single format */
        guac_rdp_ai_send_incoming_data(channel);
        guac_rdp_ai_send_formats(channel, &format, 1);
        return;

    }

    /* No formats available */
    guac_client_log(client, GUAC_LOG_WARNING, "AUDIO_INPUT: No WAVE format.");
    guac_rdp_ai_send_incoming_data(channel);
    guac_rdp_ai_send_formats(channel, NULL, 0);

}

void guac_rdp_ai_flush_packet(char* buffer, int length, void* data) {

    IWTSVirtualChannel* channel = (IWTSVirtualChannel*) data;

    /* Send data over channel */
    guac_rdp_ai_send_incoming_data(channel);
    guac_rdp_ai_send_data(channel, buffer, length);

}

void guac_rdp_ai_process_open(guac_client* client,
        IWTSVirtualChannel* channel, wStream* stream) {

    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
    guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input;

    UINT32 packet_frames;
    UINT32 initial_format;

    Stream_Read_UINT32(stream, packet_frames); /* FramesPerPacket */
    Stream_Read_UINT32(stream, initial_format); /* InitialFormat */

    guac_client_log(client, GUAC_LOG_DEBUG, "RDP server is accepting audio "
            "input as %i-channel, %i Hz PCM audio at %i bytes/sample.",
            audio_buffer->out_format.channels,
            audio_buffer->out_format.rate,
            audio_buffer->out_format.bps);

    /* Success */
    guac_rdp_ai_send_formatchange(channel, initial_format);
    guac_rdp_ai_send_open_reply(channel, 0);

    /* Begin receiving audio data */
    guac_rdp_audio_buffer_begin(audio_buffer, packet_frames,
            guac_rdp_ai_flush_packet, channel);

}

void guac_rdp_ai_process_formatchange(guac_client* client,
        IWTSVirtualChannel* channel, wStream* stream) {

    /* Should not be called as we only accept one format */
    guac_client_log(client, GUAC_LOG_DEBUG,
            "RDP server requesting AUDIO_INPUT format change despite only one "
            "format available.");

}

