/*Copyright 2003 Jacob Robbins*/
/*released under GPL*/

#include <stdio.h>
#include <stdlib.h>

#include "../include.h"

/*****SUBMAP OVERALL FUNCTIONS******/

event_submap_t* event_submap_create(char data_type, int test_type){
  event_submap_t* newmap;

  if ((data_type != EVENT_PARAMETER_DATA_TYPE_UCHAR)&&(data_type != EVENT_PARAMETER_DATA_TYPE_CHAR)&&\
      (data_type != EVENT_PARAMETER_DATA_TYPE_INT)&&(data_type != EVENT_PARAMETER_DATA_TYPE_FLOAT)) return 0;

  if ((data_type == EVENT_PARAMETER_DATA_TYPE_FLOAT)&&(! test_type)) return 0; /*don't test floats exact*/

  if (!(newmap = (event_submap_t*)malloc(sizeof(event_submap_t)))) return 0;
  newmap->event_parameter_offset = 0;
  newmap->event_parameter_data_type = data_type;
  if (test_type)
    newmap->event_parameter_test_type = SUBMAP_TEST_TYPE_RANGE;
  else
    newmap->event_parameter_test_type = SUBMAP_TEST_TYPE_EXACT;
    
  switch (newmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (newmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR: 
      newmap->test_array = generic_array_create(sizeof(triplet_uc_uc_i_t));
      break;
    case EVENT_PARAMETER_DATA_TYPE_CHAR:
      newmap->test_array = generic_array_create(sizeof(triplet_c_c_i_t));
      break;
    case EVENT_PARAMETER_DATA_TYPE_INT:
      newmap->test_array = generic_array_create(sizeof(triplet_i_i_i_t));
      break;
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:
      newmap->test_array = generic_array_create(sizeof(triplet_f_f_i_t));
      break;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    switch (newmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR: 
      newmap->test_array = generic_array_create(sizeof(pair_uc_i_t));
      break;
    case EVENT_PARAMETER_DATA_TYPE_CHAR:
      newmap->test_array = generic_array_create(sizeof(pair_c_i_t));
      break;
    case EVENT_PARAMETER_DATA_TYPE_INT:
      newmap->test_array = generic_array_create(sizeof(pair_i_i_t));
      break;
    }
    break;

  }

  if (!newmap->test_array) {free(newmap); return 0;}
  
  return newmap;
}


void event_submap_destroy(event_submap_t* sbmap){
  if (sbmap->test_array) generic_array_destroy(sbmap->test_array); 
  free(sbmap);
}


size_t event_submap_get_parameter_offset(event_submap_t* sbmap) {return sbmap->event_parameter_offset;}

void event_submap_set_parameter_offset(event_submap_t* sbmap, size_t newoffset) { 
  sbmap->event_parameter_offset = newoffset;
}


char event_submap_get_parameter_data_type(event_submap_t* sbmap) {return sbmap->event_parameter_data_type;}


int event_submap_get_parameter_test_type(event_submap_t* sbmap) {return sbmap->event_parameter_test_type;}



/****SUBMAP TEST ARRAY FUNCTIONS********/

int event_submap_get_test_array_size(event_submap_t* sbmap) {
  return generic_array_get_size(sbmap->test_array);
}

int event_submap_set_test_array_size(event_submap_t* sbmap, int newsize) {
  return generic_array_set_size(sbmap->test_array, newsize);
}


int event_submap_insert_test(event_submap_t* sbmap, int pos, void* min, void* max){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      tst.min = *((unsigned char*)min);
      tst.max = *((unsigned char*)max);      
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      tst.min = *((char*)min);
      tst.max = *((char*)max);      
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      tst.min = *((int*)min);
      tst.max = *((int*)max);      
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      tst.min = *((float*)min);
      tst.max = *((float*)max);      
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      tst.uc = *((unsigned char*)min);
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      tst.c = *((char*)min);
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      tst.i = *((int*)min);
      tst.action_list = 0;
      if ((generic_array_insert_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  }

  return 0;
}


int event_submap_remove_test(event_submap_t* sbmap, int pos){

  return generic_array_remove_element(sbmap->test_array, pos, 0);

}


int event_submap_append_test(event_submap_t* sbmap, void* min, void* max){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      tst.min = *((unsigned char*)min);
      tst.max = *((unsigned char*)max);      
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      tst.min = *((char*)min);
      tst.max = *((char*)max);      
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      tst.min = *((int*)min);
      tst.max = *((int*)max);      
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      tst.min = *((float*)min);
      tst.max = *((float*)max);      
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      tst.uc = *((unsigned char*)min);
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      tst.c = *((char*)min);
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      tst.i = *((int*)min);
      tst.action_list = 0;
      if ((generic_array_append_element(sbmap->test_array, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  }

  return 0;
}







int event_submap_get_test_min(event_submap_t* sbmap, int pos, void* set){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((unsigned char*)set) =  tst.min;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((char*)set) =  tst.min;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((int*)set) =  tst.min;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((float*)set) =  tst.min;
      break;
    }
    default:
      return -1;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    return event_submap_get_test_exact(sbmap,pos,set);
   
  }

  return 0;
}





int event_submap_set_test_min(event_submap_t* sbmap, int pos, void* set){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.min = *((unsigned char*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.min = *((char*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.min = *((int*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.min = *((float*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    return event_submap_set_test_exact(sbmap,pos,set);
    
  }

  return 0;
}


int event_submap_get_test_max(event_submap_t* sbmap, int pos, void* set){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((unsigned char*)set) =  tst.max;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((char*)set) =  tst.max;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((int*)set) =  tst.max;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((float*)set) =  tst.max;
      break;
    }
    default:
      return -1;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    return event_submap_get_test_exact(sbmap,pos,set);
   
  }

  return 0;
}




int event_submap_set_test_max(event_submap_t* sbmap, int pos, void* set){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.max = *((unsigned char*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.max = *((char*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.max = *((int*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.max = *((float*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  case SUBMAP_TEST_TYPE_EXACT:
    return event_submap_set_test_exact(sbmap,pos,set);
    
  }

  return 0;
}




int event_submap_get_test_exact(event_submap_t* sbmap, int pos, void* set){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    return -1;

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((unsigned char*)set) =  tst.uc;
      return 0;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((char*)set) =  tst.c;
      return 0;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      *((int*)set) =  tst.i;
      return 0;
    }
    default:
      return -1;
    }

  }

  return -1;
}


int event_submap_set_test_exact(event_submap_t* sbmap, int pos, void* set){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    return -1;

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.uc = *((unsigned char*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.c = *((char*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      tst.i = *((int*)set);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return -1;
      break;
    }
    default:
      return -1;
    }
    break;

  }

  return 0;
}



int event_submap_get_test_action_count(event_submap_t* sbmap, int pos){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return ll_get_size(&tst.action_list);
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return ll_get_size(&tst.action_list);
   }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return ll_get_size(&tst.action_list);
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return ll_get_size(&tst.action_list);
    }
    default:
      return 0;
    }

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      return ll_get_size(&tst.action_list);
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return ll_get_size(&tst.action_list);
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return ll_get_size(&tst.action_list);
    }
    default:
      return 0;
    }

  }

  return 0;
}


event_map_action_t* event_submap_get_test_action(event_submap_t* sbmap, int pos, int actionpos){

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
   }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
    }
    default:
      return 0;
    }

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)(ll_get_node(&tst.action_list,actionpos)->data);
    }
    default:
      return 0;
    }

  }

  return 0;
}




int event_submap_get_action_index(event_submap_t* sbmap, event_map_action_t* act){


  /*TODO */

  return -1;
}







/*************************APPEND***************************/
event_map_action_t* event_submap_append_test_action(event_submap_t* sbmap, int pos){
  node_t* nod;
  event_map_action_t* newact;

  /*make blank action to append*/
  if (!(newact = (event_map_action_t*)malloc(sizeof(event_map_action_t)))) return 0;
  event_map_action_zero(newact);
  

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
   }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    default:
      return 0;
    }

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_append(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    default:
      return 0;
    }

  }


      
  return 0;
}



/**************************PREPEND************************/
event_map_action_t* event_submap_prepend_test_action(event_submap_t* sbmap, int pos){
  node_t* nod;
  event_map_action_t* newact;

  /*make blank action to prepend*/
  newact = (event_map_action_t*)malloc(sizeof(event_map_action_t));
  event_map_action_zero(newact);
  

  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
   }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    default:
      return 0;
    }

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod =  ll_prepend(&tst.action_list, (void*)newact ))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    default:
      return 0;
    }

  }
      
  return 0; 
}

/***************************INSERT*************************/
event_map_action_t* event_submap_insert_test_action(event_submap_t* sbmap, int pos, int actpos){
  node_t* nod;
  event_map_action_t* newact;


  /*allow insert at one past last element = append*/
  if (actpos == event_submap_get_test_action_count(sbmap,pos))
    return event_submap_append_test_action(sbmap, pos);
 

  /*make blank action to insert*/
  newact = (event_map_action_t*)malloc(sizeof(event_map_action_t));
  event_map_action_zero(newact);
  
  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
   }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    default:
      return 0;
    }

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return 0;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      if (!(nod =  ll_insert_before(nod, (void*)newact, &tst.action_list))) return 0;
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      else return (event_map_action_t*)nod->data;
    }
    default:
      return 0;
    }

  }
      
  return 0; 
}

/***************************REMOVE*************************/
int event_submap_remove_test_action(event_submap_t* sbmap, int pos, int actpos){
  node_t* nod;
  
  switch (sbmap->event_parameter_test_type){

  case SUBMAP_TEST_TYPE_RANGE:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      triplet_uc_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      triplet_c_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
   }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      triplet_i_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
     }
    case EVENT_PARAMETER_DATA_TYPE_FLOAT:{
      triplet_f_f_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
    }
    default:
      return -1;
    }

  case SUBMAP_TEST_TYPE_EXACT:
    switch (sbmap->event_parameter_data_type){
    case EVENT_PARAMETER_DATA_TYPE_UCHAR:{
      pair_uc_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
    }
    case EVENT_PARAMETER_DATA_TYPE_CHAR:{
      pair_c_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
    }
    case EVENT_PARAMETER_DATA_TYPE_INT:{
      pair_i_i_t tst;
      if ((generic_array_get_element(sbmap->test_array, pos, &tst))<0) return -1;
      if (!(nod = ll_get_node(&tst.action_list, actpos))) return 0;
      ll_remove(nod, &tst.action_list);
      if ((generic_array_set_element(sbmap->test_array, pos, &tst))<0) return 0;
      return 0;
    }
    default:
      return -1;
    }

  }
      
  return -1; 
}


