/*
 * 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/rdpei.h"
#include "common/surface.h"
#include "plugins/channels.h"
#include "rdp.h"
#include "settings.h"

#include <freerdp/client/rdpei.h>
#include <freerdp/freerdp.h>
#include <freerdp/event.h>
#include <guacamole/client.h>
#include <guacamole/timestamp.h>

#include <stdlib.h>
#include <string.h>

guac_rdp_rdpei* guac_rdp_rdpei_alloc() {

    guac_rdp_rdpei* rdpei = malloc(sizeof(guac_rdp_rdpei));

    /* Not yet connected */
    rdpei->rdpei = NULL;

    /* No active touches */
    for (int i = 0; i < GUAC_RDP_RDPEI_MAX_TOUCHES; i++)
        rdpei->touch[i].active = 0;

    return rdpei;

}

void guac_rdp_rdpei_free(guac_rdp_rdpei* rdpei) {
    free(rdpei);
}

/**
 * Callback which associates handlers specific to Guacamole with the
 * RdpeiClientContext instance allocated by FreeRDP to deal with received
 * RDPEI (multi-touch input) messages.
 *
 * This function is called whenever a channel connects via the PubSub event
 * system within FreeRDP, but only has any effect if the connected channel is
 * the RDPEI channel. This specific callback is registered with the
 * PubSub system of the relevant rdpContext when guac_rdp_rdpei_load_plugin() is
 * called.
 *
 * @param context
 *     The rdpContext associated with the active RDP session.
 *
 * @param e
 *     Event-specific arguments, mainly the name of the channel, and a
 *     reference to the associated plugin loaded for that channel by FreeRDP.
 */
static void guac_rdp_rdpei_channel_connected(rdpContext* context,
        ChannelConnectedEventArgs* e) {

    guac_client* client = ((rdp_freerdp_context*) context)->client;
    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
    guac_rdp_rdpei* guac_rdpei = rdp_client->rdpei;

    /* Ignore connection event if it's not for the RDPEI channel */
    if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) != 0)
        return;

    /* Store reference to the RDPEI plugin once it's connected */
    RdpeiClientContext* rdpei = (RdpeiClientContext*) e->pInterface;
    guac_rdpei->rdpei = rdpei;

    /* Declare level of multi-touch support */
    guac_common_surface_set_multitouch(rdp_client->display->default_surface,
            GUAC_RDP_RDPEI_MAX_TOUCHES);

    guac_client_log(client, GUAC_LOG_DEBUG, "RDPEI channel will be used for "
            "multi-touch support.");

}

void guac_rdp_rdpei_load_plugin(rdpContext* context) {

    /* Subscribe to and handle channel connected events */
    PubSub_SubscribeChannelConnected(context->pubSub,
        (pChannelConnectedEventHandler) guac_rdp_rdpei_channel_connected);

    /* Add "rdpei" channel */
    guac_freerdp_dynamic_channel_collection_add(context->settings, "rdpei", NULL);

}

int guac_rdp_rdpei_touch_update(guac_rdp_rdpei* rdpei, int id, int x, int y,
        double force) {

    int contact_id; /* Ignored */

    /* Track touches only if channel is connected */
    RdpeiClientContext* context = rdpei->rdpei;
    if (context == NULL)
        return 1;

    /* Locate active touch having provided ID */
    guac_rdp_rdpei_touch* touch = NULL;
    for (int i = 0; i < GUAC_RDP_RDPEI_MAX_TOUCHES; i++) {
        if (rdpei->touch[i].active && rdpei->touch[i].id == id) {
            touch = &rdpei->touch[i];
            break;
        }
    }

    /* If no such touch exists, add it */
    if (touch == NULL) {
        for (int i = 0; i < GUAC_RDP_RDPEI_MAX_TOUCHES; i++) {
            if (!rdpei->touch[i].active) {
                touch = &rdpei->touch[i];
                touch->id = id;
                break;
            }
        }
    }

    /* If the touch couldn't be added, we're already at maximum touch capacity.
     * Drop the event. */
    if (touch == NULL)
        return 1;

    /* Signal the end of an established touch if touch force has become zero
     * (this should be a safe comparison, as zero has an exact representation
     * in floating point, and the client side will use an exact value to
     * represent the absence of a touch) */
    if (force == 0.0) {

        /* Ignore release of touches that we aren't tracking */
        if (!touch->active)
            return 1;

        context->TouchEnd(context, id, x, y, &contact_id);
        touch->active = 0;

    }

    /* Signal the start of a touch if this is the first we've seen it */
    else if (!touch->active) {
        context->TouchBegin(context, id, x, y, &contact_id);
        touch->active = 1;
    }

    /* Established touches need only be updated */
    else
        context->TouchUpdate(context, id, x, y, &contact_id);

    return 0;

}

