/******************************************************************************
 * io_element.cpp
 * comments added later
 *****************************************************************************/
#include <stdio.h>
#include "io_element.h"
#include "int_to_hex.h"
#include "vehicle.h"



IOElement io_element;



IOElement::IOElement()	throw() 
{ 
   next_out = NULL;

   usedAutoCalibrate = -1;
   analog_value_ = 0.0;
   digital_value_ = 0;
   analog_gain_ = 0.0;
   analog_offset_ = 0.0;
   max_ = 0.0;
   min_ = 0.0;
   
   tmpMax = -100.0;
   tmpMin = 100;
   

   graphics_.type_= "None";
   graphics_.type2_= "None";

   graphics_.x_ = 0;
   graphics_.y_ = 0;
   graphics_.x2_ = 0;
   graphics_.y2_ = 0;

   out_string = "\0";
}


IOElement::~IOElement()	throw() {  }


void 
IOElement::make(int	surfVehicle,
		int	digAnalog, 
		int	element_num,
		string	element_name,
   	      	string 	defaults,
		int 	default_level,	
   		bool 	enable_channel,
		bool	auto_calibrate_enable,
   		bool 	enable_graphics,
		int 	digital_value,
   		float 	analog_value,
		float 	analog_raw,
		float	analog_offset,
		float	gain,
 		float	max,
   		float	min,
   	        string	graphic_type,
		int	color,
		int	x,
		int	y,
		int 	vga_screen ) throw(bad_alloc)
{
                                                                             	
   iotype_ = findIOtype(surfVehicle, digAnalog);

   //cout <<"what about the io type here : "<<iotype_<<endl;
   element_num_ = element_num;
   element_name_ = element_name;
   defaults_ = defaults;	
   default_level_ = default_level;
   enable_channel_ = enable_channel;
   auto_calibrate_enable_ = auto_calibrate_enable;
   enable_graphics_ = enable_graphics;
   digital_value_ = digital_value;
   analog_value_ = analog_value;
   analog_raw_ = analog_raw;
   analog_offset_ = analog_offset;
   analog_gain_ = gain;
   max_ = max;
   min_ = min;
   //graphics_.type_= graphic_type;
   graphics_.color_ = color;
   graphics_.vga_screen_ = vga_screen;
   findDigitalInfo();
   next_out = NULL;

   if (vga_screen == 1)
   {
   	graphics_.type_= graphic_type;
   	graphics_.x_ = x;
   	graphics_.y_ = y;
   	
   }

   else
   {
   	graphics_.type2_= graphic_type;
      	graphics_.x2_ = x;
   	graphics_.y2_ = y;

   }


	
}






DigitalInput
IOElement::digital_input_info()
{
   DigitalInput temp;
   temp.group = digital_input_.group;
   temp.port = digital_input_.port;
   temp.channel = digital_input_.channel;
   return temp;
}

int	
IOElement::autoCalibrateMax(int surfVehicle, int digAnalog, int elem_num, 
			    float maxAnalog)
{
	max_ = maxAnalog;
	return 1;
       	
}


int	
IOElement::autoCalibrateMin(int afds, int afdws, int adfasfd, float afsdafsa)
{ return 1;}


/************************** getAllInfo(int...) **********************************/

void
IOElement::getAllInfo(int surfVehicle, int digAnalog, 
                      int element_num, int screen, char retString[])
{
   // do one level of error checking, should always be the same
   if (element_num_ != element_num)
      surfVehicle = -1;

   //cout <<"io_element.cpp : defaults_ "<<defaults_<<endl;

   if (screen == 1)
   {
   	snprintf(retString, 512,
    	"%d|%d|%d|%s|%s|%d|%d|%d|%d|%d|%f|%f|%f|%f|%f|%f|%s|%d|%d|%d|%d",
        surfVehicle, digAnalog, element_num,
   	element_name_.c_str(), defaults_.c_str(),	
        default_level_, enable_channel_,
        auto_calibrate_enable_, enable_graphics_,
   	digital_value_, analog_value_,
        analog_raw_, analog_offset_,
	analog_gain_, max_, min_,
  	graphics_.type_.c_str(), graphics_.color_,
        graphics_.x_, graphics_.y_,
        1);
	
   }

   else
   {
   	snprintf(retString, 512,
    	"%d|%d|%d|%s|%s|%d|%d|%d|%d|%d|%f|%f|%f|%f|%f|%f|%s|%d|%d|%d|%d",
        surfVehicle, digAnalog, element_num,
   	element_name_.c_str(), defaults_.c_str(),	
        default_level_, enable_channel_,
        auto_calibrate_enable_, enable_graphics_,
   	digital_value_, analog_value_,
        analog_raw_, analog_offset_,
	analog_gain_, max_, min_,
  	graphics_.type2_.c_str(), graphics_.color_,    	// different here
        graphics_.x2_, graphics_.y2_,                     	// and here compared to the first screen
        2);
	


   }




}


/************************** getAllInfo(int) **********************************/

void
IOElement::getAllInfo(char retString[]) 
{
   int surfVehicle;
   int digAnalog;

   typeToSD(iotype_, surfVehicle, digAnalog);

   if (graphics_.vga_screen_ == 1 )
   {
 
   	sprintf(retString,
        	"%d|%d|%d|%s|%s|%d|%d|%d|%d|%d|%f|%f|%f|%f|%f|%f|%s|%d|%d|%d|%d",
        	surfVehicle, digAnalog, element_num_,
   		element_name_.c_str(), defaults_.c_str(),	
        	default_level_, enable_channel_,
        	auto_calibrate_enable_, enable_graphics_,
   		digital_value_, analog_value_,
        	analog_raw_, analog_offset_,
		analog_gain_, max_, min_,
  		graphics_.type_.c_str(), graphics_.color_,
        	graphics_.x_, graphics_.y_,
        	graphics_.vga_screen_);
        	return;
   }

   else
   {
   	sprintf(retString,
        	"%d|%d|%d|%s|%s|%d|%d|%d|%d|%d|%f|%f|%f|%f|%f|%f|%s|%d|%d|%d|%d",
        	surfVehicle, digAnalog, element_num_,
   		element_name_.c_str(), defaults_.c_str(),	
        	default_level_, enable_channel_,
        	auto_calibrate_enable_, enable_graphics_,
   		digital_value_, analog_value_,
        	analog_raw_, analog_offset_,
		analog_gain_, max_, min_,
  		graphics_.type2_.c_str(), graphics_.color_,
        	graphics_.x2_, graphics_.y2_,
        	graphics_.vga_screen_);

         	return;
   }


}





/******************************* helper functions *****************************/

int 
IOElement::findIOtype(int surfVehicle, int digAnalog)
{
   int iotype;

   /* surfVehicle: 	0 - vehicle
    * 		   	1 - surface
    * digitalAnalog:	0 - Analog
    * 			1 - digital
    */
                                         \

   // cout <<"------------ surfVehicle : "<<surfVehicle<<endl;
    //cout <<"------------ digAnalog : "<<digAnalog<<endl;


   if (surfVehicle == 0) {
	// vehicle - sub
	switch (digAnalog) {
		case 0:
			iotype = subAnalogIn;
			break;
		case 1:
			iotype = subDigIn;	
			break;
	}
   }

   else if (surfVehicle == 1)
   {
	// surface - top
	switch (digAnalog)
	{
		case 0:
			iotype = topAnalogIn;
			break;
		case 1:
			iotype = topDigIn;	
			break;
   		case 3:
   			iotype = topAnalogOut;
   			break;
  	}

   }

   //cout <<"io_element.cpp : iotype is : "<<iotype<<endl;

   return iotype;

}

int
IOElement::typeToSD(int iotype_, int &surfVehicle, int &digAnalog)
{
   switch(iotype_) {
     case 1:          // topDigitalIn
          surfVehicle = 1;
          digAnalog = 1;
          return 1;  
     case 2:
          surfVehicle = 1;
          digAnalog = 1;
          return 1;
     case 3:    	//topAnalogIn
          surfVehicle = 1;
          digAnalog = 0;
          return 1;
     case 4:      // topAnalogOut
          surfVehicle = 1;
          digAnalog = 3;
          return 1;

     case 5:   	// subDigitalIn
          surfVehicle = 0;
          digAnalog = 1;
          return 1;
     case 6:
          surfVehicle = 0;
          digAnalog = 1;
          return 1;

     case 7:       	// subAnalogIn
          surfVehicle = 0;
          digAnalog = 0;
          return 1;

     case 8:
          surfVehicle = 0;
          digAnalog = 0;
          return 1;

   }

   return -1;
}

/******************************* findDigitalInfo *****************************/

void 
IOElement::findDigitalInfo()
{
 // printf("iotype: %d \n" , iotype_ );

   if (!(iotype_ == topDigIn || iotype_ == topDigOut)) 
      cerr <<"";
      //cerr << "io_element.cpp: element is not of type surface Digital In\n";

   else {
      if (0 < element_num_ && element_num_ <= 24) {
         digital_input_.group = 0;
	 if (element_num_ <= 8) 
            digital_input_.port = 0;
         else if (8 < element_num_ && element_num_ <= 16)
            digital_input_.port = 1;
         else if (16 < element_num_ && element_num_ <= 24)
            digital_input_.port = 2;
         else
            cerr << "io_element.cpp: digital input error on: " << element_num_ << "\n";
      
      } else if (24 < element_num_ && element_num_ <= 48) {
     	 digital_input_.group = 1;      
	 if (element_num_ <= 32) 
            digital_input_.port = 0;
         else if (32 < element_num_ && element_num_ <= 40)
            digital_input_.port = 1;
         else if (40 < element_num_ && element_num_ <= 48)
            digital_input_.port = 2;
         else
            cerr << "digital input error on: " << element_num_ << "\n";

      } else if (48 <  element_num_ && element_num_ <= 72) {
	 digital_input_.group = 2;
	 if (element_num_ <= 56) 
            digital_input_.port = 0;
         else if (56 < element_num_ && element_num_ <= 64)
            digital_input_.port = 1;
         else if (64 < element_num_ && element_num_ <= 72)
            digital_input_.port = 2;
         else
            cerr << "digital input error on: " << element_num_ << "\n";

      } else if (72 < element_num_ && element_num_ <= 96) {
         digital_input_.group = 3;
	 if (element_num_ <= 80) 
            digital_input_.port = 0;
         else if (80 < element_num_ && element_num_ <= 88)
            digital_input_.port = 1;
         else if (88 < element_num_ && element_num_ <= 96)
            digital_input_.port = 2;
         else
            cerr << "digital input error on: " << element_num_ << "\n";
      
      } else { 
         //cerr << "ERROR*** no such digital channel on surface: "
              //<< element_num_ << "\n";
         return;
      }
      
      digital_input_.channel = inttohex((int)pow(2.0, ((element_num_-1) % 8)));
   }


}


/******************************* test() ******************************************/

void
IOElement::test()
{
   cout<<"-------------------------------------------\n";
   printf("Element name : %s \n" , element_name_.c_str() );
   printf("Element number : %d \n" , element_num_ );
   //printf("Graph type on screen 1 is: %s \n" , graphics_.type_.c_str() );
   //printf("Graph type on screen 2 is: %s \n" , graphics_.type2_.c_str() );
   cout<<"Defaults : "<<defaults_<<endl;
   cout<<"-------------------------------------------\n";
}

/******************************************************************************/




void
IOElement::get_graph_info( char graph_string[] )
{
   sprintf (graph_string, "%s|%d|%d|%s|%d|%d|%d",
   		graphics_.type_.c_str(), graphics_.x_, graphics_.y_,
                          graphics_.type2_.c_str(), graphics_.x2_, graphics_.y2_,
                          element_num_  );

    // test();

}


