/** 
 * \fn init_device_extra_data(PESRV p)
 * \brief initialize the device's extra data set.
 * \param[in,out] PESRV Pointer to an esrv data structure.
 * \return ESRV_SUCCESS status code: ok.
 * \return ESRV_FAILURE status code: erreur.
 */
ESRV_API int init_device_extra_data(PESRV p) {
  /**
   * The device data structure is allocated in this function and 
   * is static.  The address of this structure is linked into the server's
   * data structure at the end of the first call of this function.
   */
  
  static DEVICE_DATA data;
  static int f_first_init_call = 0;
  PDEVICE_DATA px = NULL;
  if(!p) { 
    goto init_device_extra_data_error; 
  }
  
  if(f_first_init_call == 0){
    /// <h1>I - First call from driver - before device option string parsing</h1>
    memset(&data,0,sizeof(DEVICE_DATA));
    px = (void *)&data;
    
    /** 
     * Add all initializations the device may require.  Add
     * the additional data into the definition of the DEVICE_DATA
     * structure (defined in template_device_dynamic_library.h file). 
     *
     * Use statically allocated data or dynamically allocated data.
     * If the data is dynamically allocated, then it can be done either
     * at first or second call of this function.  If using dynamically 
     * allocated data, it *must* be de-allocated at program end.  There
     * is an opportunity to do so in the delete_template_device_extra_data
     * function which is called at the server's end.
     */
    
    /// <h2> a. Initialization </h2>
    /* CONFIGURATION */
    px->nbConfigurations                = 0;
    px->tabConfigurations               = NULL;
    px->chosenConfiguration             = 0;
    px->nb_circles                      = 0;
    // racine SDK : TO DELETE from files
    // px->racineSDK                       = "";
    px->tabMAC                          = NULL;
    px->counters_names                  = NULL; // The name of each counter is stored in an array of strings
    
    Plugwise initPlugwise               = {"Mac address"};
    Plugwise *pInitPlugwise             = &initPlugwise; 
    px->plugwise                        = pInitPlugwise;
            
    /* PROGRAM EXECUTION TIME */
    px->nbrAnalysesParSecondes          = 0.0 ;   
    
    // sprintf(px->commande,"");
    
    /* MENU */
    px->menuChoice			= 0 ;
    /** 
     * Set the default virtual device count (1 based).  If the device
     * integrates 3 independent power readers sharing the same interface 
     * (source), then set this variable (virtual_devices) to 3.
     * Later on, the server will use this information to query each virtual
     *  device independently, by providing the virtual device's id (0 based)
     * in the call to the read_device_power function.
     */ 
    p->device_data.virtual_devices = 1 ;
    /// The number of virtual devices is changed between the first and second call, during the parsing function
    
    /// <h2> b. Plugwise configuration loading </h2>
    /// * We get the number and configuration names
    px->nbConfigurations = nb_configurations();
    allocation_configurations_names(px->nbConfigurations, &(px->tabConfigurations));
    save_configurations_names(px->nbConfigurations,px->tabConfigurations);
    
    /*
     * Set the f_hw_energy_integration_provided flag if the device can 
     * provide  hardware power integration.  If this flag is set, then 
     * read_device_energy is called at the update frequency (1Hz by default)
     * by the server.  As for the read_device_power function, the virtual
     * device's id is provided during the read_device_energy function.
     */
    p->f_hw_energy_integration_provided = 0;
    
    
    /// (Link of the data structure into the server's data structure before the parsing function)
    p->device_data.p_device_data = (void *)&data;
    
    /* a library supported device may use a proprietary interface to 
     * communicate with the server (for example the Yokogawa WT500 uses a 
     * modified TCP/IP interface).  In this case, the device - in the 
     * init_device_extra_data library function - sets the device_interface 
     * to ESRV_DEVICE_INTERFACE_PROPRIETARY, overwriting the default 
     * ESRV_DEVICE_INTERFACE_SERIAL. It is then the device's responsibility
     * to manage its interface.  This is done in the open_device and 
     * close_device functions.  Note that the device can still use the 
     * interface_options to collect device specific options (and therefore
     * allow for the proprietary interface configuration). */
    p->device_interface = ESRV_DEVICE_INTERFACE_PROPRIETARY;
    
    // Set the first call flag to 1.  This flag is used to distinguish 
    // the first from the second call in this function.
    f_first_init_call = 1;
  } else {
    /// <h1> II - Second call from the driver - post device option string parsing </h1>
    /** 
     * Add all additional initializations the device may require.  Add
     * the additional data into the definition of the DEVICE_DATA
     * structure (defined in template_device_dynamic_library.h file).
     * Use statically allocated data or dynamically allocated data.
     * If using dynamically allocated data, it *must* be de-allocated at 
     * program end.
     * There is an opportunity to do so in the 
     * delete_template_device_extra_data function which is called at the 
     * server's end.
     */ 
    
    PDEVICE_DATA pd = NULL;  
    pd = (void *)&data;
    if (pd == NULL){
      goto init_device_extra_data_error;
    }

    /// *  we get data from configuration
    pd->menuChoice = 1;
    static_data_recovery(pd->menuChoice,pd->chosenConfiguration, pd->tabConfigurations, pd->racinePython,&(pd->nb_circles));
    mac_adress_dynamic_allocation(pd->nb_circles,&(pd->tabMAC));
    counters_names_dynamic_allocation(pd->nb_circles,&(pd->counters_names)); 
    dynamic_data_recovery(pd->chosenConfiguration,pd->nb_circles,pd->tabMAC,pd->counters_names);
    configuration_display(pd->chosenConfiguration,pd->tabConfigurations,pd->racinePython,pd->nb_circles,pd->counters_names,pd->tabMAC);
    
    p->device_data.virtual_devices = pd->nb_circles ;
    /// * We free tabConfigurations </h3>
    free(pd->tabConfigurations);
    //free(pd);
  }    
  
  return(ESRV_SUCCESS);
 init_device_extra_data_error:
  return(ESRV_FAILURE);
}
/**
 * \fn main (void)
 * \brief Configuration creation and deletion. 
 * \return EXIT_SUCCESS status code: ok. 
 * \return EXIT_FAILURE status code: error.
 */
int main (void){ // char *arge[] permet d'utiliser les redirections avec la fonction popen
  /* BOUCLES */
  int i=0;
  
  /* CONFIGURATION */
  int nbConfigurations                = 0;
  ConfigurationName *tabConfigurations = NULL;
  int configurationChoisie            = 0;
  int nb_circles                      = 0;
  char racinePython[ROOT_SIZE]        = "";
  MACaddress *tabMAC                  = NULL;
  char **counters_names               = NULL; // Le nom de chaque compteurs est stocké dans un tableau de chaine de caractères 
  
  /* MENU */
  int choixMenu                       = 0;
  
  printf("Management of the plugwise configurations :\n");
  printf("\n");
  
  // MENU CONFIGURATIONS
  printf("What do you want to do?\n");
  printf("1: Create a new configuration\n");
  printf("2: Delete a configuration\n");
  
  printf("Your choice: ");
  scanf("%d",&choixMenu);
  printf("\n");
  
  if ((choixMenu != 1) && (choixMenu !=2))
    {
      perror("Error : your choice is not possible !\n");
      return EXIT_FAILURE;
    } 
  
  // Because the source code was make for another program
  choixMenu++;
  
  /// CHOIX 1 : CREATION D'UNE NOUVELLE CONFIGURATION :
  if(choixMenu==2)
    {
      allocation_configurations_names(1, &tabConfigurations);
      write_static_data(choixMenu, 1, tabConfigurations, racinePython, &nb_circles);      
      
      mac_adress_dynamic_allocation(nb_circles,&tabMAC);
      counters_names_dynamic_allocation(nb_circles,&counters_names); 
      write_dynamic_data(choixMenu, nb_circles, tabMAC, counters_names);
      
      free(tabConfigurations);
      deallocation(nb_circles, &tabMAC, &counters_names);
    }
  
  /// CHOIX 2 : SUPPRIMER UNE CONFIGURATION :
  else
    { 
      /// 1. On récupère le nombre et les noms des configurations
      nbConfigurations = nb_configurations();
      allocation_configurations_names(nbConfigurations, &tabConfigurations);
      save_configurations_names(nbConfigurations, tabConfigurations);
      
      /// 2. On demande à l'utilisateur de choisir la configuration à supprimer
      configurationChoisie = configuration_choice(choixMenu, nbConfigurations, tabConfigurations);
      
      /// 3. On récupère les données de la configuration
      system("touch configurations.tmp");
      i=1;
      while(i <= nbConfigurations){
	if(i != configurationChoisie){
	  
	  // Récupération des données
	  static_data_recovery(choixMenu, i, tabConfigurations, racinePython,&nb_circles);
	  mac_adress_dynamic_allocation(nb_circles,&tabMAC);
	  counters_names_dynamic_allocation(nb_circles,&counters_names); 
	  dynamic_data_recovery(i, nb_circles, tabMAC, counters_names);
	  
	  // Permutation fichiers
	  system("mv configurations.txt configurations.txt.tmp");
	  system("mv configurations.tmp configurations.txt");
	  
	  // Ecriture des données
	  write_static_data(choixMenu, i, tabConfigurations, racinePython, &nb_circles);      
	  write_dynamic_data(choixMenu, nb_circles, tabMAC, counters_names);
	  
	  system("mv configurations.txt configurations.tmp");
	  system("mv configurations.txt.tmp configurations.txt");
	}
	i++;
      }
      
      /// 4. On libère la mémoire et renomme le fichier temporaire en configurations.txt
      free(tabConfigurations);
      deallocation(nb_circles, &tabMAC, &counters_names);
      system("rm configurations.txt");
      system("mv configurations.tmp configurations.txt");
    } 

  return EXIT_SUCCESS;
}
/**
 * \fn main (void)
 * \brief Configuration creation and deletion. 
 * \return EXIT_SUCCESS status code: ok. 
 * \return EXIT_FAILURE status code: error.
 */
int main (void){ 
  /* BOUCLES */
  int i=0;
  
  /* CONFIGURATION */
  int nbConfigurations                = 0;
  ConfigurationName *tabConfigurations = NULL;
  int chosenConfiguration             = 0;
  int nb_circles                      = 0;
  char pythonRoot[ROOT_SIZE]        = "";
  MACaddress *tabMAC                  = NULL;
  char **counters_names               = NULL; // the name of each counters is saved in a table of strings
  
  /* MENU */
  int menuChoice                       = 0;
  
  printf("Management of the plugwise configurations :\n");
  printf("\n");
  
  // MENU CONFIGURATIONS
  printf("What do you want to do?\n");
  printf("1: Create a new configuration\n");
  printf("2: Delete a configuration\n");
  
  printf("Your choice: ");
  scanf("%d",&menuChoice);
  printf("\n");
  
  if ((menuChoice != 1) && (menuChoice !=2))
    {
      perror("Error : your choice is not possible !\n");
      return EXIT_FAILURE;
    } 
  
  // Because the source code was made for another program (TO CHANGE)
  menuChoice++;
  
  /// <h2>CHOICE 1 : CREATION OF A NEW CONFIGURATION :</h2>
  if(menuChoice==2)
    {
      allocation_configurations_names(1, &tabConfigurations);
      write_static_data(menuChoice, 1, tabConfigurations, pythonRoot, &nb_circles);      
      
      mac_adress_dynamic_allocation(nb_circles,&tabMAC);
      counters_names_dynamic_allocation(nb_circles,&counters_names); 
      write_dynamic_data(menuChoice, nb_circles, tabMAC, counters_names);
      
      free(tabConfigurations);
      deallocation(nb_circles, &tabMAC, &counters_names);
    }
  
  /// <h2>CHOICE 2 : DELETE A CONFIGURATION:</h2>
  else
    { 
      /// <h3>1. We save the number and the name of the configurations</h3>
      nbConfigurations = nb_configurations();
      allocation_configurations_names(nbConfigurations, &tabConfigurations);
      save_configurations_names(nbConfigurations, tabConfigurations);
      
      /// <h3>2. We ask the user to chose the configuration to delete</h3>
      chosenConfiguration = configuration_choice(menuChoice, nbConfigurations, tabConfigurations);
      
      /// <h3>3. We save the configuration data</h3>
      system("touch configurations.tmp");
      i=1;
      while(i <= nbConfigurations){
	if(i != chosenConfiguration){
	  
	  // Data recovery
	  static_data_recovery(menuChoice, i, tabConfigurations, pythonRoot,&nb_circles);
	  mac_adress_dynamic_allocation(nb_circles,&tabMAC);
	  counters_names_dynamic_allocation(nb_circles,&counters_names); 
	  dynamic_data_recovery(i, nb_circles, tabMAC, counters_names);
	  
	  // Files permutation
	  system("mv configurations.txt configurations.txt.tmp");
	  system("mv configurations.tmp configurations.txt");
	  
	  // Data writing
	  write_static_data(menuChoice, i, tabConfigurations, pythonRoot, &nb_circles);      
	  write_dynamic_data(menuChoice, nb_circles, tabMAC, counters_names);
	  
	  system("mv configurations.txt configurations.tmp");
	  system("mv configurations.txt.tmp configurations.txt");
	}
	i++;
      }
      
      /// <h3>4. We release the memory and rename the temporary file in configurations.txt</h3>
      free(tabConfigurations);
      deallocation(nb_circles, &tabMAC, &counters_names);
      system("rm configurations.txt");
      system("mv configurations.tmp configurations.txt");
    } 
  
  return EXIT_SUCCESS;
}