#include "Fille.h"
#include "PCF8574.h"
#include "tim.h"

Actionneur Osmolateur;
Actionneur Brassage1;
Actionneur Brassage2;
Actionneur Chauffage;
Actionneur Ecumeur;
Actionneur Remonter;
Actionneur LumiereDec;

uint8_t IntervalBrassage;
uint8_t numPompe; //Variable savoir qu'elle pompe est en marche quand alternance ON 1 = 1 0 = 2
uint8_t gl_timerInter;

uint8_t gl_powerVentil1,gl_powerVentil2;

uint8_t ListeFille[NBFILLE];

enum EtatNourrisage Nourrisage;
enum Etat BrassageGeneral;

enum Etat gl_Ventil1,gl_Ventil2;

void init_Fille() {

	Nourrisage = Nour_Normal;
	BrassageGeneral = Marche;
	IntervalBrassage = 0;
	ListeFille[0] = 0;

	/*
	 * Emplacement 0 => OUT 1
	 * 12V
	 * Contact NO
	 */
	Osmolateur.N_CarteFille = ListeFille[0];
	Osmolateur.Emplacement = 0;
	Osmolateur.Contact = NO;
	Osmolateur.On = Marche;

	/*
	 * Emplacement 2 => OUT 3
	 * 230V
	 * Contact NC
	 */
	Brassage1.N_CarteFille = ListeFille[0];
	Brassage1.Emplacement = 2;
	Brassage1.Contact = NC;
	Brassage1.On = Marche;

	/*
	 * Emplacement 3  => OUT 4
	 * 230V
	 * Contact NC
	 */
	Brassage2.N_CarteFille = ListeFille[0];
	Brassage2.Emplacement = 3;
	Brassage2.Contact = NC;
	Brassage2.On = Marche;

	/*
	 * Emplacement  4 => OUT 5
	 * 230V
	 * Contact NC
	 */
	Chauffage.N_CarteFille = ListeFille[0];
	Chauffage.Emplacement = 4;
	Chauffage.Contact = NC;
	Chauffage.On = Marche;

	/*
	 * Emplacement 5 => OUT 6
	 * 230V
	 * Contact NC
	 */
	Ecumeur.N_CarteFille = ListeFille[0];
	Ecumeur.Emplacement = 5;
	Ecumeur.Contact = NC;
	Ecumeur.On = Marche;

	/*
	 * Emplacement 6 => OUT 7
	 * 230V
	 * Contact NC
	 */
	Remonter.N_CarteFille = ListeFille[0];
	Remonter.Emplacement = 6;
	Remonter.Contact = NC;
	Remonter.On = Marche;

	/*
	 * Emplacement 1 => OUT 2
	 * 230V
	 * Contact NC
	 */
	LumiereDec.N_CarteFille = ListeFille[0];
	LumiereDec.Emplacement = 1;
	LumiereDec.Contact = NO;
	LumiereDec.On = Arret;

}

HAL_StatusTypeDef readActitoneur(uint8_t* val) {
	uint8_t ReadVal;
	HAL_StatusTypeDef res;
	// pour une optimisation du nombre de lecture I2C la lecture n'est pas faite en générique si rajout d'une carte fille pensé a refaire cette fonction
	if((res = Read_PCF8574(0, &ReadVal))!=HAL_OK){
		return res;
	}
	val[0] = 0 ;
	val[1] = 0 ;
	if(Nourrisage==Nour_Normal)
		modifBit(&val[0],DECALNOUR,0);
	else
		modifBit(&val[0],DECALNOUR,1);
	//Osmolateur
	modifBit(&val[0],DECALOSMO,MarcheArret(((ReadVal >> Osmolateur.Emplacement) & MASKPAIRE),Osmolateur.Contact));
	//Brassage1
	modifBit(&val[0],DECALBRA1,Brassage1.On);
	//Brassage2
	modifBit(&val[0],DECALBRA2,Brassage2.On);
	//Chauffage
	modifBit(&val[0],DECALCHAU,MarcheArret(((ReadVal >> Chauffage.Emplacement) & MASKPAIRE),Chauffage.Contact));
	//Ecumeur
	modifBit(&val[0],DECALECUM,MarcheArret(((ReadVal >> Ecumeur.Emplacement) & MASKPAIRE),Ecumeur.Contact));
	//Remonter
	modifBit(&val[0],DECALREME,MarcheArret(((ReadVal >> Remonter.Emplacement) & MASKPAIRE),Remonter.Contact));
	//Nourrissage
	modifBit(&val[0],DECALNOUR,Nourrisage);
	//Brassage Général
	modifBit(&val[0],DECALBRAG,BrassageGeneral);

	//TODO Osmolateur manuel
	//OSMOLATEUR Manuel
	//modifBit(&val[1],DECALOSMM,MarcheArret(((ReadVal >> Remonter.Emplacement) & MASKPAIRE),Remonter.Contact));
	//Lumiere
	modifBit(&val[1],DECALLUMI,MarcheArret(((ReadVal >> LumiereDec.Emplacement) & MASKPAIRE),LumiereDec.Contact));
	return res;
}

HAL_StatusTypeDef fc_Nourrisage(enum Etat val) {
	HAL_StatusTypeDef res;
	if (val = Marche){
	BrassageGeneral = Arret;
	res = fc_Brassage();
	if (res != HAL_OK) {
		return res;
	}
	fc_Remonter(Arret);
	if (res != HAL_OK) {
		BrassageGeneral = Marche;
		if (fc_Brassage() != HAL_OK)
			//Todo (Gestion d'erreur) Gros probleme (Arret du brassage mauvaise arret de la remonter et pas de redemarage
			return res;
	}
	fc_Ecumeur(Arret);
	if (res != HAL_OK) {
		BrassageGeneral = Marche;
		if ((fc_Brassage() != HAL_OK) & (fc_Remonter(Marche) != HAL_OK))
			//Todo (Gestion d'erreur) Gros probleme (Arret du brassage et de la remonter mauvaise arret de l'ecumeur et pas de redemarage
			return res;
	}
	Nourrisage = Nour_Nourrisage;
	startTIMNourrisage(); //Lancement du Tim nourrisage
	return res;
	}
	else{

	BrassageGeneral = Marche;
	res = fc_Brassage();
	res += fc_Remonter(Marche);
	res += fc_Ecumeur(Marche);
	if (res != HAL_OK) {
		//Todo (Gestion d'erreur) Gros probleme
		;
	}
	Nourrisage = Nour_Normal;
	stopTIMNourrisage(); //Lancement du Tim nourrisage
	return res;
	}
}

HAL_StatusTypeDef fc_Osmolateur(enum Etat val) {
	if(Osmolateur.On==Marche){
		HAL_StatusTypeDef res = Write_One_Bit_PCF8574(Osmolateur.N_CarteFille, MarcheArret(val, Osmolateur.Contact), Osmolateur.Emplacement);
		if (res == HAL_OK)
			Chauffage.On = val;
		startTIMOsmo();
		return res;
	}
	else
		return HAL_OK;
}

HAL_StatusTypeDef fc_OsmolateurManu(enum Etat val) {
	return Write_One_Bit_PCF8574(Osmolateur.N_CarteFille, MarcheArret(val, Osmolateur.Contact), Osmolateur.Emplacement);
	//TODO (test) si pas de probleme lors d'un relachement rapide du boutton blynk
}

HAL_StatusTypeDef fc_Brassage() {
	HAL_StatusTypeDef res;

	stopTIMBrassage();
	if (BrassageGeneral == Arret) {
		res = Write_One_Bit_PCF8574(Brassage1.N_CarteFille, MarcheArret(Arret, Brassage1.Contact), Brassage1.Emplacement);
		res += Write_One_Bit_PCF8574(Brassage2.N_CarteFille, MarcheArret(Arret, Brassage2.Contact), Brassage2.Emplacement);
		startTIMArretLong();
		return res;
	}
	else if(Brassage1.On != Arret && Brassage2.On != Arret && IntervalBrassage !=0){
		return ChangePompe();
	}
	else{
		if (Brassage1.On == Arret){
			res = Write_One_Bit_PCF8574(Brassage1.N_CarteFille, MarcheArret(Arret, Brassage1.Contact), Brassage1.Emplacement);
		}
		else{
			res = Write_One_Bit_PCF8574(Brassage1.N_CarteFille, MarcheArret(Marche, Brassage1.Contact), Brassage1.Emplacement);
		}

		if (Brassage2.On == Arret){
			res = Write_One_Bit_PCF8574(Brassage2.N_CarteFille, MarcheArret(Arret, Brassage2.Contact), Brassage2.Emplacement);
		}
		else{
			res = Write_One_Bit_PCF8574(Brassage2.N_CarteFille, MarcheArret(Marche, Brassage2.Contact), Brassage2.Emplacement);
		}
	}
}

HAL_StatusTypeDef ChangePompe(){
	HAL_StatusTypeDef res;
	if (numPompe) {
		res = Write_One_Bit_PCF8574(Brassage1.N_CarteFille, MarcheArret(Arret, Brassage1.Contact), Brassage1.Emplacement);
		res += Write_One_Bit_PCF8574(Brassage2.N_CarteFille, MarcheArret(Marche, Brassage2.Contact), Brassage2.Emplacement);
	} else {
		res = Write_One_Bit_PCF8574(Brassage1.N_CarteFille, MarcheArret(Marche, Brassage1.Contact), Brassage1.Emplacement);
		res += Write_One_Bit_PCF8574(Brassage2.N_CarteFille, MarcheArret(Arret, Brassage2.Contact), Brassage2.Emplacement);
	}
	numPompe = !numPompe;
	startTIMBrassage();
	return res;
}

HAL_StatusTypeDef fc_Chauffage(enum Etat val) {
	HAL_StatusTypeDef res = Write_One_Bit_PCF8574(Chauffage.N_CarteFille, MarcheArret(val, Chauffage.Contact), Chauffage.Emplacement);
	if (res == HAL_OK)
		Chauffage.On = val;
	return res;
}

HAL_StatusTypeDef fc_Ecumeur(enum Etat val) {
	HAL_StatusTypeDef res = Write_One_Bit_PCF8574(Ecumeur.N_CarteFille, MarcheArret(val, Ecumeur.Contact), Ecumeur.Emplacement);
	if (res == HAL_OK)
		Ecumeur.On = val;
	return res;
}

HAL_StatusTypeDef fc_Remonter(enum Etat val) {
	HAL_StatusTypeDef res = Write_One_Bit_PCF8574(Remonter.N_CarteFille, MarcheArret(val, Remonter.Contact), Remonter.Emplacement);
	if (res == HAL_OK)
		Remonter.On = val;
	if (val==Arret)
		startTIMArretLong();
	else
		stopTIMArretLong();
	return res;
}

void modifBit(uint8_t* variable, uint8_t emplacement, uint8_t val){

	if (val){
		*variable = *variable | 1 << emplacement;
	}
	else{
		*variable = *variable & ((1 << emplacement)^0xFF);
	}
}

uint8_t MarcheArret(enum Etat val, enum Relais relais) {
	if (relais == NO)
		return val;
	else
		return !val;
}

HAL_StatusTypeDef fc_Lumiere(enum Etat val) {
	HAL_StatusTypeDef res = Write_One_Bit_PCF8574(LumiereDec.N_CarteFille, MarcheArret(val, LumiereDec.Contact), LumiereDec.Emplacement);
	if (res == HAL_OK)
		LumiereDec.On = val;
	return res;
}

HAL_StatusTypeDef fc_Ventilation(){
	HAL_StatusTypeDef res;
	//todo (Gestion d'erreur) faire le retour de la fonction
	if ((gl_Ventil1 == Arret) & (gl_Ventil2 ==Arret)){
		stopVentil();
	}
	else{
		if (gl_Ventil1 != Arret)
			startVentil1(gl_Ventil1);
		else
			HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_1);
		if (gl_Ventil2 != Arret)
			startVentil2(gl_Ventil2);
		else
			HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_2);
	}

	return res;
}
