#include <automation.h>
#include "parcelize.h"

extern FLASH_STRUCT Flash;


void ActuatorParcelize( char* out, int id )
{
	char buf[256] = {0};
	WATERING_ACTUATOR* wa;

	wa = &Flash.settings.actuators[id];

	sprintf(buf,"(%02d%1d[%03d%03d]%1d%04.1f)",
			wa->outputNum,
			wa->autoRunEnabled ? 1 : 0,
			wa->setpoints[0], wa->setpoints[1],
			wa->autoRunFeature,
			wa->avgCurrentConsumption);
	strcat(out,buf);
}

void ActuatorUnparcelize( char* in, WATERING_ACTUATOR* o  )
{
	o->outputNum = toInt(in,0,2);
	o->autoRunEnabled = toBool(in,2);
	o->setpoints[0] = toInt(in,4,7);
	o->setpoints[1] = toInt(in,7,10);
	o->autoRunFeature = toInt(in,11,12);
	o->avgCurrentConsumption = toFloat(in,12,16);
}

void SequenceParcelize( char* out, int id )
{
	char buf[50] = {0};
	WATERING_VALVE* wa;

	wa = &Flash.settings.valves[id];

	for( int s = 0; s < 4; s++ )
	{
		WATERING_SEQUENCE* ws = &wa->sequence[s];
		sprintf(buf,"(%03d%03d%03d[%03d%03d%03d%03d])",
				ws->startYearDay,
				ws->cycleTime,
				ws->soakTime,
				ws->runTime[0],ws->runTime[1],ws->runTime[2],ws->runTime[3]);
		strcat(out,buf);
	}
}

void SequenceUnparcelize( char* in, WATERING_SEQUENCE* o  )
{
	o->startYearDay = toInt(in,0,3);
	o->cycleTime = toInt(in,3,6);
	o->soakTime = toInt(in,6,9);
	o->runTime[0] = toInt(in,10,13);
	o->runTime[1] = toInt(in,13,16);
	o->runTime[2] = toInt(in,16,19);
	o->runTime[3] = toInt(in,19,22);
}

void ValveParcelize( char* buff, int id )
{
	char buf[1024] = { 0 };
	WATERING_VALVE* wv;

	wv = &Flash.settings.valves[id];

	sprintf((char*)buf,"(%1d%1d%1d%1d",
			wv->id,
			wv->MV_Pump ? 1 : 0,
			wv->sensorsOverride ? 1 : 0,
			wv->dummy ? 1 : 0);
	strcat(buff,(char*)buf);

	strcat(buff,"S[");

	SequenceParcelize(buff, id );

	sprintf((char*)buf,"]%03d)",wv->pumpAdjust);
	strcat(buff,(char*)buf);
}

void ValveUnparcelize( char* in, WATERING_VALVE* o  )
{
	o->id = toInt(in,0,1);
	o->MV_Pump = toBool(in,1);
	o->sensorsOverride = toBool(in,2);
	o->dummy = toBool(in,3);
	int index = 7;
	for( int s=0; s < 4; s++ )
	{
		SequenceUnparcelize( &in[index+(s*25)], &o->sequence[s]  );
	}
	index += 100;
	o->pumpAdjust = toInt(in,index,index+3);
}

void ProgramParcelize( char* buff, int id )
{
	char buf[1024];
	WATERING_PROGRAM* wp;

	wp = &Flash.settings.programs[id];

	sprintf(buf,"(%1d%03d%1d000%1d",
			wp->id,
			wp->wateringWeekDay,
			wp->period,
			wp->nStartTimes);
	strcat(buff,buf);

	strcat(buff,"T[");
	for( int d=0; d < wp->nStartTimes; d++ )
	{
		sprintf(buf,"%04d",wp->startTimes[d]);
		strcat(buff,buf);
	}
	strcat(buff,"]");


	sprintf(buf,"%03d%1d%03d)",
			wp->seasonalAdjust,
			wp->monthlySeasonalAdjust ? 1 : 0,
			wp->valveDelay);
	strcat(buff,buf);
}

void ProgramUnparcelize( char* in, WATERING_PROGRAM* o  )
{
	o->id = toInt(in,0,1);
	o->wateringWeekDay = toInt(in,1,4);
	o->period = toInt(in,4,5);
	//int dummy = toInt(in,5,8);
	o->nStartTimes = toInt(in,8,9);
	for( int t=0; t < o->nStartTimes; t++ )
	{
		o->startTimes[t] = toInt(in,11+(t*4),15+(t*4));
	}
	int index = 12 + (o->nStartTimes*4);
	o->seasonalAdjust = toInt(in,index,index+3);
	o->monthlySeasonalAdjust = toBool(in,index+3);
	o->valveDelay = toInt(in,index+4,index+7);
}

int GeneralParcelize( char* buff )
{
	char buf[SETTINGS_BUFFER_SIZE];
	WATERING_GENERAL* wg;

	wg = &Flash.settings;

	sprintf(buf,"%08X%03d%03d%03d%04d%04d%03d",
			DATA_VERSION,
			wg->PumpStartDelay,
			wg->PumpStopDelay,
			wg->FlushingTime,
			wg->auxStartTime,
			wg->auxEndTime,
			wg->timeZoneOffset);
	strcat(buff,buf);
	strcat(buff,"A[");
	for( int a=0; a<5; a++ )
		ActuatorParcelize( buff, a );
	strcat(buff,"]P[");
	for( int p=0; p<4; p++ )
		ProgramParcelize( buff, p );
	strcat(buff,"]V[");
	for( int v=0; v<8; v++ )
		ValveParcelize( buff, v );
	strcat(buff,"]M[");
	for( int m=0; m<12; m++ )
	{
		sprintf(buf,"%03d",wg->seasonalMonthlyParam[m]);
		strcat(buff,buf);
	}
	strcat(buff,"]");

	return strlen(buff);
}

bool GeneralUnparcelize( char* in, WATERING_GENERAL* o  )
{
	char out[128];

	substring(in,out,0,8);
	long version = DATA_VERSION;
	if( !memcmp((void*)out,(void*)&version,4) )
		return false;

	o->versionID = DATA_VERSION;
	o->PumpStartDelay = toInt(in,8,11);
	o->PumpStopDelay = toInt(in,11,14);
	o->FlushingTime = toInt(in,14,17);
	o->auxStartTime = toInt(in,17,21);
	o->auxEndTime = toInt(in,21,25);
	o->timeZoneOffset = toInt(in,25,28);
	int endIndex = 0;
	for( int a = 0; a < 5; a++ )
	{
		endIndex = 47 + ( a * 18 );
		substring(in,out,31+(a*18),endIndex);
		ActuatorUnparcelize( out, &(o->actuators[a]) );
	}
	endIndex += 5;
	for( int p = 0; p < 4; p++ )
	{
		char *pos = strchr (&in[endIndex], ')');
		int endIndexPgm = pos ? pos - in : -1;
		substring(in,out,endIndex,endIndexPgm);
		ProgramUnparcelize( out, &(o->programs[p]) );
		endIndex = endIndexPgm + 2;
	}
	endIndex += 3;
	for( int v = 0; v < 8; v++ )
	{
		substring(in,out,endIndex,endIndex+110);
		ValveUnparcelize( out, &(o->valves[v]) );
		endIndex += 112;
	}
	endIndex += 2;
	for( int m = 0; m < 12; m++ )
	{
		substring(in,out,endIndex,endIndex+3);
		Flash.settings.seasonalMonthlyParam[m] = atoi(out);
		endIndex += 3;
	}
	return true;
}

void EnvSensorsParcelize( char* buff )
{
	char buf[25];

	sprintf(buf,"%02d",env_sensors_tab.nbr);
	for( int i = 0; i < ENV_SENSORS_NBR; i++ )
	{
		env_sensors_t* es = &env_sensors_tab.env_sensors[i];
		sprintf(buf,"%04d%02d",es->can_address,es->param_id);
		strcat(buff,buf);
	}
}

void EnvSensorsUnparcelize( char* in, FLASH_ENV_SENSORS* o  )
{
	memset(o,0,sizeof(FLASH_ENV_SENSORS));
	o->nbr = toInt(in,0,2);
	for( int ev = 0; ev < o->nbr; ev++ )
	{
		int offset = 7 * ev;
		env_sensors_t* es = &o->env_sensors[ev];
		es->can_address = toInt(in,2+offset,6+offset);
		es->param_id = toInt(in,6+offset,9+offset);
	}
}

