/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/test/channel_transport/traffic_control_win.h"

#include <assert.h>

#include "webrtc/system_wrappers/include/trace.h"

namespace webrtc {
namespace test {

TrafficControlWindows* TrafficControlWindows::instance = NULL;
uint32_t TrafficControlWindows::refCounter = 0;

TrafficControlWindows::TrafficControlWindows(const int32_t id)
{
}

TrafficControlWindows* TrafficControlWindows::GetInstance(
    const int32_t id)
{
    if(instance != NULL)
    {
        WEBRTC_TRACE(
            kTraceDebug,
            kTraceTransport,
            id,
            "TrafficControlWindows - Returning already created object");
        refCounter++;
        return instance;
    }

    WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
                 "TrafficControlWindows - Creating new object");
    instance = new TrafficControlWindows(id);
    if(instance == NULL)
    {
        WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
                     "TrafficControlWindows - Error allocating memory");
        return NULL;
    }

    instance->tcRegister = NULL;
    instance->tcDeregister = NULL;

    instance->tcEnumerate = NULL;
    instance->tcOpenInterface = NULL;
    instance->tcCloseInterface = NULL;

    instance->tcAddFlow = NULL;
    instance->tcDeleteFlow = NULL;

    instance->tcAddFilter = NULL;
    instance->tcDeleteFilter = NULL;

    HMODULE trafficLib = LoadLibrary(TEXT("traffic.dll"));
    if(trafficLib == NULL)
    {
        WEBRTC_TRACE(
            kTraceWarning,
            kTraceTransport,
            id,
            "TrafficControlWindows - No QOS support, LoadLibrary returned NULL,\
 last error: %d\n",
            GetLastError());
        delete instance;
        instance = NULL;
        return NULL;
    }

    instance->tcRegister = (registerFn)GetProcAddress(trafficLib,
                                                      "TcRegisterClient");
    instance->tcDeregister = (deregisterFn)GetProcAddress(trafficLib,
                                                          "TcDeregisterClient");
    instance->tcEnumerate = (enumerateFn)GetProcAddress(
        trafficLib,
        "TcEnumerateInterfaces");
    instance->tcOpenInterface = (openInterfaceFn)GetProcAddress(
        trafficLib,
        "TcOpenInterfaceW");
    instance->tcCloseInterface = (closeInterfaceFn)GetProcAddress(
        trafficLib,
        "TcCloseInterface");
    instance->tcAddFlow = (flowAddFn)GetProcAddress(trafficLib,
                                                    "TcAddFlow");
    instance->tcDeleteFlow = (flowDeleteFn)GetProcAddress(trafficLib,
                                                          "TcDeleteFlow");

    instance->tcAddFilter = (filterAddFn)GetProcAddress(trafficLib,
                                                        "TcAddFilter");
    instance->tcDeleteFilter = (filterDeleteFn)GetProcAddress(trafficLib,
                                                              "TcDeleteFilter");

    if(instance->tcRegister       == NULL ||
       instance->tcDeregister     == NULL ||
       instance->tcEnumerate      == NULL ||
       instance->tcOpenInterface  == NULL ||
       instance->tcCloseInterface == NULL ||
       instance->tcAddFlow        == NULL ||
       instance->tcAddFilter      == NULL ||
       instance->tcDeleteFlow     == NULL ||
       instance->tcDeleteFilter   == NULL)
    {
        delete instance;
        instance = NULL;
        WEBRTC_TRACE(
            kTraceError,
            kTraceTransport,
            id,
            "TrafficControlWindows - Could not find function pointer for\
 traffic control functions");
        WEBRTC_TRACE(
            kTraceError,
            kTraceTransport,
            id,
            "Tcregister    : %x, tcDeregister: %x, tcEnumerate: %x,\
 tcOpenInterface: %x, tcCloseInterface: %x, tcAddFlow: %x, tcAddFilter: %x,\
 tcDeleteFlow: %x, tcDeleteFilter: %x",
            instance->tcRegister,
            instance->tcDeregister,
            instance->tcEnumerate,
            instance->tcOpenInterface,
            instance->tcCloseInterface,
            instance->tcAddFlow,
            instance->tcAddFilter,
            instance->tcDeleteFlow,
            instance->tcDeleteFilter );
        return NULL;
    }
    refCounter++;
    return instance;
}

void TrafficControlWindows::Release(TrafficControlWindows* gtc)
{
    if (0 == refCounter)
    {
        WEBRTC_TRACE(kTraceError, kTraceTransport, -1,
                     "TrafficControlWindows - Cannot release, refCounter is 0");
        return;
    }
    if (NULL == gtc)
    {
        WEBRTC_TRACE(kTraceDebug, kTraceTransport, -1,
                     "TrafficControlWindows - Not releasing, gtc is NULL");
        return;
    }

    WEBRTC_TRACE(kTraceDebug, kTraceTransport, -1,
                 "TrafficControlWindows - Releasing object");
    refCounter--;
    if ((0 == refCounter) && instance)
    {
        WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
                     "TrafficControlWindows - Deleting object");
        delete instance;
        instance = NULL;
    }
}

ULONG TrafficControlWindows::TcRegisterClient(
    ULONG TciVersion,
    HANDLE ClRegCtx,
    PTCI_CLIENT_FUNC_LIST ClientHandlerList,
    PHANDLE pClientHandle)
{
    assert(tcRegister != NULL);

    return tcRegister(TciVersion, ClRegCtx, ClientHandlerList, pClientHandle);
}

ULONG TrafficControlWindows::TcDeregisterClient(HANDLE clientHandle)
{
    assert(tcDeregister != NULL);

    return tcDeregister(clientHandle);
}


ULONG TrafficControlWindows::TcEnumerateInterfaces(
    HANDLE ClientHandle,
    PULONG pBufferSize,
    PTC_IFC_DESCRIPTOR interfaceBuffer)
{
    assert(tcEnumerate != NULL);

    return tcEnumerate(ClientHandle, pBufferSize, interfaceBuffer);
}


ULONG TrafficControlWindows::TcOpenInterfaceW(LPWSTR pInterfaceName,
                                              HANDLE ClientHandle,
                                              HANDLE ClIfcCtx,
                                              PHANDLE pIfcHandle)
{
    assert(tcOpenInterface != NULL);

    return tcOpenInterface(pInterfaceName, ClientHandle, ClIfcCtx, pIfcHandle);

}

ULONG TrafficControlWindows::TcCloseInterface(HANDLE IfcHandle)
{
    assert(tcCloseInterface != NULL);

    return tcCloseInterface(IfcHandle);
}

ULONG TrafficControlWindows::TcAddFlow(HANDLE IfcHandle, HANDLE ClFlowCtx,
                                       ULONG  Flags, PTC_GEN_FLOW pGenericFlow,
                                       PHANDLE pFlowHandle)
{
    assert(tcAddFlow != NULL);
    return tcAddFlow(IfcHandle, ClFlowCtx, Flags, pGenericFlow, pFlowHandle);
}

ULONG TrafficControlWindows::TcAddFilter(HANDLE FlowHandle,
                                         PTC_GEN_FILTER pGenericFilter,
                                         PHANDLE pFilterHandle)
{
    assert(tcAddFilter != NULL);
    return tcAddFilter(FlowHandle, pGenericFilter, pFilterHandle);
}

ULONG TrafficControlWindows::TcDeleteFlow(HANDLE FlowHandle)
{
    assert(tcDeleteFlow != NULL);
    return tcDeleteFlow(FlowHandle);

}

ULONG TrafficControlWindows::TcDeleteFilter(HANDLE FilterHandle)
{
    assert(tcDeleteFilter != NULL);
    return tcDeleteFilter(FilterHandle);
}

void MyClNotifyHandler(HANDLE ClRegCtx, HANDLE ClIfcCtx, ULONG Event,
                       HANDLE SubCode, ULONG BufSize, PVOID Buffer)
{
}

}  // namespace test
}  // namespace webrtc
