#include "common.h"
uint32_t val_uint32;
uint8_t val_uint8;
static void duckinitialize(dag_card_ref_t card_ref,dag_component_t duck,bool mode);
static void duckconfig (int argc, char *argv[],dag_card_ref_t card_ref,dag_component_t duck);
static void print_version()
{
}
static void print_usage(ClArgPtr clarg)
{
    print_version();
    printf("DUCK - Endace DAG clock using Config & Status API\n");
    printf("Usage: dagclock [-hvVxk] [-d dag] [-K <timeout>] [-l <threshold>] [options]\n");
    dagclarg_display_usage(clarg, stdout);
    printf("\nThe following duck configuration options are available:\n");
    printf("        default    RS422 in, none out\n");
    printf("        none       None in, none out\n");
    printf("        rs422in    RS422 input\n");
    printf("        hostin     Host input (unused)\n");
    printf("        overin     Internal input (synchronise to host clock)\n");
    printf("        auxin      Aux input (unused)\n");
    printf("        rs422out   Output the rs422 input signal\n");
    printf("        loop       Output the selected input\n");
    printf("        hostout    Output from host (unused)\n");
    printf("        overout    Internal output (master card)\n");
    printf("        set        Set DAG Clock to PC clock\n");
    printf("        reset      Full clock reset: Clock set from PC, RS422 in, none out\n");
    printf("        sync       Wait for duck to sync before exiting\n");
}
static int set_duck_component_attributes(int argc,char *argv[])
{
        ClArgPtr clarg = NULL;
        int clarg_result;
        FILE *errorfile = NULL;
        int argindex;
        int code;
        int dagfd;
        int dagstream;
        uint32_t threshold;
        int32_t timeout;
        
        attr_uuid_t attr = 0;

        dag_component_t root_component = 0;
        dag_component_t duck = 0;
        dag_card_ref_t card_ref = NULL;
        
        dagutil_set_progname("DAG Universal Clock");
        
        /* Set up default DAG device. */
        if (-1 == dag_parse_name(dagname_buf, dagname, DAGNAME_BUFSIZE, &dagstream))
        {
            dagutil_panic("dag_parse_name(%s): %s\n", dagname_buf, strerror(errno));
        }
        /*Basic Initialization and getting card descriptor - to be done only when device changes*/
        card_ref= dag_config_init(dagname_buf);
        if(card_ref == NULL)
        {
              printf("Failed to get Card Handle \n");
              return EXIT_FAILURE;
        }
        dagfd = dag_open(dagname);
        root_component = dag_config_get_root_component(card_ref);
        if(!root_component)
        {
            printf("Failed to get root component \n");
            exit(1);
        }
        duck = dag_component_get_subcomponent(root_component,kComponentDUCK, 0);
        if(!duck)
        {
            printf("Failed to get the duck component \n");
            exit(1);
        }
        /*Basic Initialization and getting card descriptor - to be done only when device changes*/ 
        
        dagutil_set_progname("DAG Universal Clock");

        /* Set up the command line options. */
        clarg = dagclarg_init(argc, (const char * const *)argv);
        dagclarg_add(clarg, "display help (this page)", "--help", 'h', CLA_HELP);
        dagclarg_add_long_option(clarg, CLA_HELP, "--usage");
        dagclarg_add_short_option(clarg, CLA_HELP, '?');
        dagclarg_add(clarg, "display version information", "--version", 'V', CLA_VERSION);
        dagclarg_add(clarg, "increase verbosity", "--verbose", 'v', CLA_VERBOSE);
        dagclarg_add(clarg, "clear clock statistics", "--clearstats", 'x', CLA_CLRSTATS);
        dagclarg_add(clarg, "wait for duck to sync before exiting", "--sync", 'k', CLA_SYNC);
        dagclarg_add_int(clarg, "sync timeout in seconds, default 60", "--timeout", 'K', "timeout", &timeout, CLA_TIMEOUT);
        dagclarg_add_uint(clarg, "health threshold in ns, default 596", "--threshold", 'l', "threshold", &threshold, CLA_THRESHOLD);
        dagclarg_add_string(clarg, "DAG device to use.", "--device", 'd', "device", dagname_buf, DAGNAME_BUFSIZE, CLA_DEVICE);

        
        /* Parse the command line options. */
        clarg_result = dagclarg_parse(clarg, errorfile, &argindex, &code);
        while (1 == clarg_result)
        {
            switch (code)
            {
                case CLA_HELP:
                    print_usage(clarg);
                    return EXIT_SUCCESS;
                    break;
                case CLA_VERBOSE:
                    dagutil_inc_verbosity();
                    duckread(card_ref,duck);
                    break;
                case CLA_VERSION:
                    print_version();
                    return EXIT_SUCCESS;
                    break;
                case CLA_CLRSTATS:
                    /*Status and Config API to clear the clock statistics*/
                    attr = dag_component_get_attribute_uuid(duck,kNullAttributeDUCKClearStats);
                    if(attr != kAttributeInvalid)
                    {
                        dag_config_set_null_attribute(card_ref,attr);
                    }
                    break;
                case CLA_TIMEOUT:
                     attr = dag_component_get_attribute_uuid(duck,kUint32AttributeDUCKSyncTimeout);
                     if(attr != kAttributeInvalid)
                     {
                            dag_config_set_uint32_attribute(card_ref,attr,timeout);
                     }
                    break;
                case CLA_SYNC:
                    attr = dag_component_get_attribute_uuid(duck,kUint32AttributeDUCKSyncTimeout);
                    if(attr != kAttributeInvalid)
                    {
                            int val = dag_config_get_uint32_attribute(card_ref,attr);
                            printf("sync timeout = %d\n",val);
                    }
                    attr = dag_component_get_attribute_uuid(duck,kUint32AttributeDUCKThreshold);
                    attr = dag_component_get_attribute_uuid(duck,kNullAttributeDUCKSync);
                    if (attr != kAttributeInvalid)
                    {
                           dag_config_set_null_attribute(card_ref,attr);
                    }
                    break;
               case CLA_THRESHOLD:
                    attr = dag_component_get_attribute_uuid(duck,kUint32AttributeDUCKThreshold);
                    if(attr != kAttributeInvalid)
                    {
                         dag_config_set_uint32_attribute(card_ref,attr,threshold);
                    }
                    break;
               case CLA_DEVICE:
                    if (-1 == dag_parse_name(dagname_buf, dagname, DAGNAME_BUFSIZE, &dagstream))
                    {
                           dagutil_panic("dag_parse_name(%s): %s\n", dagname_buf, strerror(errno));
                    }
                    /*Need to do the initialization for the new card*/
                    card_ref= dag_config_init(dagname_buf);
                    if(card_ref == NULL)
                    {
                           printf("Failed to get Card Handle \n");
                           return EXIT_FAILURE;
                    }
                    dagfd = dag_open(dagname);
                    root_component = dag_config_get_root_component(card_ref);
                    if(!root_component)
                    {
                           printf("Failed to get root component check card initialization \n");
                           exit(1);
                    }
                    duck = dag_component_get_subcomponent(root_component,kComponentDUCK, 0);
                    if(!duck)
                    {
                            printf("Not able to get the duck component \n");
                            exit(1);
                    }
                    break;
               default:
                    if (argv[argindex][0] == '-')
                    {
                        dagutil_error("unknown option %s\n", argv[argindex]);
                        print_usage(clarg);
                        return EXIT_FAILURE;
                    }
                    break;
            }
            clarg_result = dagclarg_parse(clarg, errorfile, &argindex, &code);
        }
        if (-1 == clarg_result)
        {
              if (argindex < argc)
              {
                     dagutil_error("while processing option %s\n", argv[argindex]);
              }
              dagclarg_display_usage(clarg, stderr);
              return EXIT_FAILURE;
        }

        argv = (char**) dagclarg_get_unprocessed_args(clarg, &argc);
        if(argc > 0)
        {        
                duckconfig((int)argc, (char**)argv,card_ref,duck);
        }
        else
        {
           duckread(card_ref,duck);
        }
		return EXIT_SUCCESS;
}
void duckconfig(int argc, char *argv[],dag_card_ref_t card_ref,dag_component_t duck)
{
      int     opt, len, i, reset = 0;
      char    *p;
      uint32_t magic = DAGRESET_DUCK;
      
      attr_uuid_t attr = 0;

#if defined(_WIN32)
      DWORD BytesTransfered = 0;
#endif
       for( opt = 0 ; opt < argc ; opt++ ) 
       {
            for( p = argv[opt]; *p ; p++ )
                    *p = tolower(*p);
            p = argv[opt];
            for( i = 0 ; configtab[i].key != NULL ; i++ ) 
            {
                    len = strlen(p);
                if(len < configtab[i].mlen)
                {
                        continue;  
                }
                if(!strncmp(p, configtab[i].key, strlen(p)))
                {
                        break;
                }
           }  
            if(configtab[i].key == NULL)
                    dagutil_panic("unsupported configuration option '%s'\n", argv[opt]);

            switch(configtab[i].inst) 
            {
                    case INST_DEFAULT:
            	        duckinitialize(card_ref,duck,0);	        
                        break;
                    case INST_NONE:
                        duckinitialize(card_ref,duck,1);	  		
                        break;
                    case INST_RS422IN:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKRS422Input);
                        if(attr != kAttributeInvalid)
                        {   
                            dag_config_set_boolean_attribute(card_ref,attr,1);                                                              		
		                }
                        break;
                    case INST_HOSTIN:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKHostInput);
                        if(attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
                        break;
                    case INST_OVERIN:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKOverInput );
                        if(attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
                        break;
                    case INST_AUXIN:
                        attr = dag_component_get_attribute_uuid(duck, kBooleanAttributeDUCKAuxInput );
                        if (attr != kAttributeInvalid)
                        {  
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
                        break;
                    case INST_RS422OUT:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKRS422Output );
                        if (attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
                        break;
                    case INST_LOOP:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKLoop);
                        if(attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
                        break;
                    case INST_HOSTOUT:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKHostOutput);
                        if (attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
                        break;
                    case INST_OVEROUT:
                        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKOverOutput );
                        if (attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }   
                        break;
                    case INST_SET:
                        attr = dag_component_get_attribute_uuid(duck,kNullAttributeDUCKSetToHost);
                        if (attr != kAttributeInvalid)
                        {
                           dag_config_set_null_attribute(card_ref,attr);
                        }
                        break;
                    case INST_RESET:
                        /*RESET - Set the clock statistics*/
		                attr = dag_component_get_attribute_uuid(duck,kNullAttributeDUCKSetToHost);
                        if (attr != kAttributeInvalid)
                        {
                          dag_config_set_null_attribute(card_ref,attr);
                        }
		                /*and set the io configuration to default*/
		                duckinitialize(card_ref,duck,1);
                        break;
                    case INST_SYNC:
                        attr = dag_component_get_attribute_uuid(duck,kNullAttributeDUCKSync);
                        if (attr != kAttributeInvalid)
                        {
                            dag_config_set_null_attribute(card_ref,attr);
                        }
                        break;
            }
       }
       duckread(card_ref,duck);
       dag_config_dispose(card_ref);
}
void 
duckinitialize(dag_card_ref_t card_ref,dag_component_t duck,bool mode)
{
		       attr_uuid_t attr = 0;

                    /*4 Input values*/
		            if(mode == 0)/*set to default rs422in none out*/
		            {
		    	        attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKRS422Input);	                    
		    	        if(attr != kAttributeInvalid)
                        {
                            dag_config_set_boolean_attribute(card_ref,attr,1);
                        }
		            }
		            else /*set to none: none in none out*/
		            {
        			    attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKRS422Input);	                    
		        	    if(attr != kAttributeInvalid)
                        {
                             dag_config_set_boolean_attribute(card_ref,attr,0);
                        }
		            }	
		            attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKHostInput);
                    if(attr != kAttributeInvalid)
                    {
                          dag_config_set_boolean_attribute(card_ref,attr,0);
                    }
                    attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKOverInput );
                    if(attr != kAttributeInvalid)
                    {
                           dag_config_set_boolean_attribute(card_ref,attr,0);
                    }
                    attr = dag_component_get_attribute_uuid(duck, kBooleanAttributeDUCKAuxInput );
                    if (attr != kAttributeInvalid)
                    { 
                           dag_config_set_boolean_attribute(card_ref,attr,0);
                    }
                    /*4 Output values*/
                    attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKRS422Output );
                    if (attr != kAttributeInvalid)
                    {
                            dag_config_set_boolean_attribute(card_ref,attr,0);
                    }
                    attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKLoop);
                    if(attr != kAttributeInvalid)
                    {
                             dag_config_set_boolean_attribute(card_ref,attr,0);
                    }
                    attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKHostOutput);
                    if (attr != kAttributeInvalid)
                    {
                              dag_config_set_boolean_attribute(card_ref,attr,0);
                    }
                    attr = dag_component_get_attribute_uuid(duck,kBooleanAttributeDUCKOverOutput );
                    if (attr != kAttributeInvalid)
                    {
                             dag_config_set_boolean_attribute(card_ref,attr,0);
                    }

}
/*DAG Clock Function Entry Point*/
int main(int argc,char *argv[])
{
    set_duck_component_attributes(argc,argv);
}


