#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <string.h>


#include <cstdlib>
#include <iostream>
#define THREAD_POOL_PARAM_T     dispatch_context_t
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>



//  define THREAD_POOL_PARAM_T such that we can avoid a compiler
//  warning when we use the dispatch_*() functions below

// Constants:
//-----------

#define THREAD_POOL_PARAM_T dispatch_context_t

#include <sys/iofunc.h>
#include <sys/dispatch.h>

const int THREAD_POOL_LOW_WATER = 5;
const int THREAD_POOL_HIGH_WATER = 10;
const int THREAD_POOL_MAX = 50;

static resmgr_connect_funcs_t    connect_funcs;
static resmgr_io_funcs_t         io_funcs;
static iofunc_attr_t             attr;

char const SDI_PATHNAME[] = "/dev/sdi1";

void *SdiThread(void *Arg)
{
    dispatch_t *dpp;
    thread_pool_attr_t pool_attr;
    thread_pool_t *tpp;
    pthread_attr_t      ThreadAttr;

//    int ReturnValue;
//    int PulseCode = 0;

    //Resmgr Stuff
    resmgr_attr_t ResmgrAttr;
    int ResmgrId = 0;


    if((dpp = dispatch_create()) == NULL)
    {
        return NULL;
    }

    pthread_attr_init(&ThreadAttr);
   	pthread_attr_setstacklazy(&ThreadAttr, PTHREAD_STACK_NOTLAZY);

    memset(&pool_attr, 0, sizeof pool_attr);
    pool_attr.handle = dpp;

    pool_attr.context_alloc = dispatch_context_alloc;
    pool_attr.block_func = dispatch_block;
    pool_attr.handler_func = dispatch_handler;
    pool_attr.context_free = dispatch_context_free;
    pool_attr.lo_water = THREAD_POOL_LOW_WATER;
    pool_attr.hi_water = THREAD_POOL_HIGH_WATER;
    pool_attr.increment = 1;
    pool_attr.maximum = THREAD_POOL_MAX ;
    pool_attr.attr = &ThreadAttr;

    printf("I am here before pool\n");

    if((tpp = thread_pool_create(&pool_attr,POOL_FLAG_EXIT_SELF )) == NULL)
    {
        return NULL;
    }

    printf("I am here after pool\n");
    memset(&ResmgrAttr, 0, sizeof ResmgrAttr);
    ResmgrAttr.nparts_max = 1;
    ResmgrAttr.msg_max_size = 2048;

    // initialize functions for handling messages
    iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
                     _RESMGR_IO_NFUNCS, &io_funcs);


    // initialize attribute structure used by the device
    iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);

    //attach our device name
    ResmgrId = resmgr_attach(dpp,            // dispatch handle
                       &ResmgrAttr,   // resource manager attrs
                       SDI_PATHNAME,     // device name
                       _FTYPE_ANY,     // open type
                       0,              // flags
                       &connect_funcs, // connect routines
                       &io_funcs,      // I/O routines
                       &attr);         // handle
    if(ResmgrId == -1)
    {
        return NULL;
    }

    printf("I am here before pool start\n");
    // Never returns
    thread_pool_start(tpp);
    return NULL;
}


int main(int argc, char *argv[])
{
	std::cout << "Welcome to the QNX Momentics IDE" << std::endl;

    pthread_attr_t attr;
    pthread_t Tid;
    pthread_attr_init(&attr);
   	pthread_attr_setstacklazy(&attr, PTHREAD_STACK_NOTLAZY);
    pthread_create( &Tid, &attr, &SdiThread, NULL );

    printf("Thread cretaed\n");
    while(1);
//	SdiThread();


	return EXIT_SUCCESS;
}
