#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "../dthres.h"

#define ONE_SECOND_IN_HECTONANOSECONDS  10000000UL

#ifdef _WIN64
    #pragma comment(lib,"../dthres64.lib")
#else
    #pragma comment(lib,"../dthres32.lib")
#endif

HANDLE      hEvents[2]  = {NULL,NULL};

void NotifyThread()
{
    static DWORD    dwLastStatus = 0;
    DWORD           dwEvent;
    DWORD           dwStatus;
    
    do
    {
        dwEvent = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
        if (dwEvent == WAIT_OBJECT_0 + 1)
        {
            GetDomainTimeStatus(&dwStatus);
            if (dwStatus != dwLastStatus)
            {
                dwLastStatus = dwStatus;
                switch (dwStatus)
                {
                case SYNC_STATUS_INVALID:   printf("Sync Status invalid\n");        break;
                case SYNC_STATUS_UNKNOWN:   printf("Sync Status unknown\n");        break;
                case SYNC_STATUS_CHECKING:  printf("Sync Status checking/synchronizing\n");       break;
                case SYNC_STATUS_SYNCED:    printf("Sync Status synchronized\n");   break;
                case SYNC_STATUS_UNSYNCED:  printf("Sync Status unsynchronized\n"); break;
                }
            }
        }
    } while (dwEvent != WAIT_OBJECT_0);

}

void PrintTest(DWORD dwReps)
{
    DWORD       x;
    FILETIME    ft;
    FILETIME    dt;
    SYSTEMTIME  st1;
    SYSTEMTIME  st2;
    BOOL        bHiRes;

    for (x = 0; x < dwReps; x++)
    {
        GetSystemTimeAsFileTime(&ft);
        bHiRes = GetDomainTimeAsFileTime(&dt);

        FileTimeToSystemTime(&ft,&st1);
        FileTimeToSystemTime(&dt,&st2);
        /*
        printf("OS=%02d:%02d:%02d.%03d   DT=%02d:%02d:%02d:%03d - %s resolution\n",
            st1.wHour,st1.wMinute,st1.wSecond,st1.wMilliseconds,
            st2.wHour,st2.wMinute,st2.wSecond,st2.wMilliseconds,
            bHiRes ? "high" : "system");
        */
        printf("OS=%u:%u   DT=%u:%u  - %s resolution\n",
            ft.dwHighDateTime,ft.dwLowDateTime,
            dt.dwHighDateTime,dt.dwLowDateTime,
            bHiRes ? "high" : "system");
    }
}

void SpeedTest()
{
    LARGE_INTEGER       liFreq;
    LARGE_INTEGER       liStart;
    LARGE_INTEGER       liNow;
    LARGE_INTEGER       liElapsed;
    unsigned __int64    iCount;
    DWORD               dwLoop;
    double              d;
    FILETIME            dt;

    SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);

    QueryPerformanceFrequency   (&liFreq);
    QueryPerformanceCounter     (&liStart);

    iCount = 0;
    do
    {
        iCount++;
        GetSystemTimeAsFileTime(&dt);
        QueryPerformanceCounter(&liNow);
        liElapsed.QuadPart = liNow.QuadPart - liStart.QuadPart;
        liElapsed.QuadPart /= liFreq.QuadPart;

    } while (liElapsed.QuadPart < 1);
    printf(" GetSystemTimeAsFileTime: %I64d checks in 1 second\n",iCount);

    QueryPerformanceCounter     (&liStart);
    iCount = 0;
    do
    {
        iCount++;
        GetDomainTimeAsFileTime(&dt);
        QueryPerformanceCounter(&liNow);
        liElapsed.QuadPart = liNow.QuadPart - liStart.QuadPart;
        liElapsed.QuadPart /= liFreq.QuadPart;

    } while (liElapsed.QuadPart < 1);
    printf(" GetDomainTimeAsFileTime: %I64d checks in 1 second\n",iCount);

    QueryPerformanceCounter     (&liStart);
    for (dwLoop = 0; dwLoop < 10000; dwLoop++)
    {
        GetSystemTimeAsFileTime(&dt);
    }
    QueryPerformanceCounter(&liNow);
    d = (  ( (double)liNow.QuadPart - (double)liStart.QuadPart) / (double)liFreq.QuadPart);

    printf(" GetSystemTimeAsFileTime: 10,000 calls took %0.7f seconds\n",d);

    QueryPerformanceCounter     (&liStart);
    for (dwLoop = 0; dwLoop < 10000; dwLoop++)
    {
        GetDomainTimeAsFileTime(&dt);
    }
    QueryPerformanceCounter(&liNow);
    d = (  ( (double)liNow.QuadPart - (double)liStart.QuadPart) / (double)liFreq.QuadPart);

    printf(" GetDomainTimeAsFileTime: 10,000 calls took %0.7f seconds\n",d);
    printf("\n");

}


void main()
{
    DWORD   dwError;
    char    ch;

    printf("Domain Time Demo - C\n\n");

    SpeedTest();

    hEvents[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
    hEvents[1] = GetDomainTimeNotifyHandle();

    if (hEvents[1] == NULL)
    {
        dwError = GetLastError();
        printf("Unable to obtain notify handle; error %d\n",dwError);
        return;
    }
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)NotifyThread,NULL,0,NULL);
    printf("Asynch status notification thread running.\n\n");

    do
    {
        PrintTest(15);
        printf("Press X to end, any other key to run test\n");
        ch = _getch();
    } while (ch != 'x' && ch != 'X');

    SetEvent(hEvents[0]);
    CloseHandle(hEvents[0]);
    CloseHandle(hEvents[1]);
}



