/*
 * connector.c
 *
 * All initialization before 12v_aux
 */

#include "connector.h"
#include "board.h"
#include "edcan.h"
#include "debug.h"
#include <string.h>
#include <charger_gbt.h>


CONN_State_t connectorState;
// CONN[0] - GB/T, CONN[1] - CCS (reserved for future use)
CONN_t CONN[2];

uint8_t CC_STATE_FILTERED;

static void CONN_UpdateEdcanOutput(void);

void CONN_Init(){
	memset(&CONN, 0, sizeof(CONN));
	CONN[0].connControl = CMD_NONE;
	CONN[1].connControl = CMD_NONE;
	/* Default requested limits are initialized once here for all connectors.
	 * They can be changed later only by external commands.
	 */
	CONN[0].RequestedCurrent = 1000;
	CONN[0].RequestedVoltage = 400;
	CONN[1].RequestedCurrent = 1000;
	CONN[1].RequestedVoltage = 400;
	/* Keep non-zero runtime defaults until external commands/measurements arrive. */
	CONN[0].SOC = 50;
	CONN[1].SOC = 50;
	CONN[0].MeasuredVoltage = 400;
	CONN[1].MeasuredVoltage = 400;
	CONN_SetState(Unknown);
}

void CONN_Task(){
	switch (connectorState){
	case Unknown:
		CONN_SetState(Unplugged);
		break;

	case Disabled:
		if(CONN[0].chargingError == 0) {
			CONN_SetState(Unplugged);
		}
		break;
	case Unplugged: // Ожидание подключения и начала сессии
	{
		// Обновляем признак физического подключения разъёма по уровню CC
		if(CONN_CC_GetState() == GBT_CC_4V){
			CONN[0].EvseConnected = 1;
			log_printf(LOG_INFO, "Charger plugged, waiting for 12V AUX\n");
			CONN_SetState(AuthRequired);
		}else{
			CONN[0].EvseConnected = 0;
		}
		break;
	}

	case AuthRequired:
	{
		// Если уровень CC вернулся к 6/12В – считаем, что коннектор выдернули
		if(CONN_CC_GetState() != GBT_CC_4V){
			log_printf(LOG_INFO, "Charger unplugged\n");
			CONN_SetState(Unplugged);
			GBT_Reset();
			break;
		}

		// Как только появляется 12V AUX от станции – переходим в Preparing (инициализация протокола)
		if(IN_ReadInput(IN_0) == 1){
			log_printf(LOG_INFO, "12V AUX detected, starting session\n");
			CONN_SetState(Preparing);
			GBT_SwitchState(GBT_EV_CONNECTING);
		}
		break;
	}

	case Preparing:
		// Ожидаем переход стейт-машины GB/T в режим зарядки.
		// Как только GBT_State уходит в режим CHARGING – считаем, что начался заряд.
		if(GBT_State == GBT_EV_CHARGING){
			log_printf(LOG_INFO, "Charging started\n");
			CONN_SetState(Charging);
		}
//		if(IN_ReadInput(IN_0) == 0){
//			CONN_SetState(Unplugged);
//			GBT_Reset();
//		}
		if(GBT_State == GBT_DISABLED){
			CONN_SetState(Finished);
		}
		break;

	case Charging: // Активная зарядка
		// Завершение по окончанию GB/T-сессии или при падении тока/отключении AUX можно
		// добавить позже. Пока ориентируемся только на завершение GB/T.
		if(GBT_State == GBT_COMPLETE){
			CONN_SetState(Finished);
		}
		if(IN_ReadInput(IN_0) == 0){
			log_printf(LOG_INFO, "12V AUX removed, finishing session\n");
			CONN_SetState(Finished);
		}
		break;

	case Finished: // Сессия завершена, ждём окончания и возможного переподключения
		// Когда GB/T стейт-машина полностью вернулась в исходное состояние,
		// можно считать сессию закрытой и вернуться в Unplugged.
		cc_enable = 0;
		if(CONN_CC_GetState() != GBT_CC_4V){
			CONN_SetState(Unplugged);
			GBT_Reset();
		}
		break;

	case FinishedEV:
	case FinishedEVSE:
		CONN_SetState(Finished);
		break;
	default:
		CONN_SetState(Unknown);

	}

}


void CONN_SetState(CONN_State_t state){
	connectorState = state;
	CONN[0].connState = state;

	if(connectorState == Unknown) 				log_printf(LOG_DEBUG,"ConnState: Unknown\n");
	if(connectorState == Unplugged) 			log_printf(LOG_DEBUG,"ConnState: Unplugged\n");
	if(connectorState == Disabled) 				log_printf(LOG_DEBUG,"ConnState: Disabled\n");
	if(connectorState == Preparing) 			log_printf(LOG_DEBUG,"ConnState: Preparing\n");
	if(connectorState == AuthRequired) 			log_printf(LOG_DEBUG,"ConnState: AuthRequired\n");
	if(connectorState == WaitingForEnergy) 		log_printf(LOG_DEBUG,"ConnState: WaitingForEnergy\n");
	if(connectorState == ChargingPausedEV) 		log_printf(LOG_DEBUG,"ConnState: ChargingPausedEV\n");
	if(connectorState == ChargingPausedEVSE) 	log_printf(LOG_DEBUG,"ConnState: ChargingPausedEVSE\n");
	if(connectorState == Charging)				log_printf(LOG_DEBUG,"ConnState: Charging\n");
	if(connectorState == AuthTimeout) 			log_printf(LOG_DEBUG,"ConnState: AuthTimeout\n");
	if(connectorState == Finished)				log_printf(LOG_DEBUG,"ConnState: Finished\n");
	if(connectorState == FinishedEVSE)			log_printf(LOG_DEBUG,"ConnState: FinishedEVSE\n");
	if(connectorState == FinishedEV)			log_printf(LOG_DEBUG,"ConnState: FinishedEV\n");
	if(connectorState == Replugging)			log_printf(LOG_DEBUG,"ConnState: Replugging\n");

}


void CONN_CC_ReadStateFiltered() {
    static uint32_t last_change_time;
    static uint32_t last_check_time;
    static uint8_t prev_state;

    if((HAL_GetTick()-last_check_time)<100) return;

    last_check_time = HAL_GetTick();

    uint8_t new_state = CONN_CC_GetStateRaw();

    if (new_state != prev_state) {
        last_change_time = HAL_GetTick();
        prev_state = new_state;
    } else if ((HAL_GetTick() - last_change_time) >= 300) {
        CC_STATE_FILTERED = prev_state;
    }
}

uint8_t CONN_CC_GetState(){
	return CC_STATE_FILTERED;
}
uint8_t CONN_CC_GetStateRaw(){
	//Vref=3.3v = 4095
	//k=1/11
	//Vin = 12v
	//Vin*k= 1.09v
	//12vin = 1353 ADC
//TODO: Filter 100ms
	uint32_t adc;
	float volt;
	ADC_Select_Channel(ADC_CHANNEL_3);
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1, 100);
	adc = HAL_ADC_GetValue(&hadc1);
	HAL_ADC_Stop(&hadc1);

	volt = (float)adc/113.4f;
//	if((volt<12.6f) && (volt>11.4f)) return GBT_CC_12V;
//	if((volt<6.8f) && (volt>5.2f)) return GBT_CC_6V;
//	if((volt<4.8f) && (volt>3.2f)) return GBT_CC_4V;
//	if((volt<2.8f) && (volt>1.2f)) return GBT_CC_2V;
	if((volt<13.0f) && (volt>11.0f)) return GBT_CC_12V;
	if((volt<7.2f) && (volt>4.8f)) return GBT_CC_6V;
	if((volt<4.8f) && (volt>3.0f)) return GBT_CC_4V;
	if((volt<3.0f) && (volt>1.0f)) return GBT_CC_2V;
	return GBT_CC_UNKNOWN;
}

float CONN_CC_GetAdc(){
	//TODO: Filters
	//Vref=3.3v = 4095
	//k=1/11
	//Vin = 12v
	//Vin*k= 1.09v
	//12vin = 1353 ADC

	uint32_t adc;
	float volt;
	ADC_Select_Channel(ADC_CHANNEL_3);
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1, 100);
	adc = HAL_ADC_GetValue(&hadc1);
	HAL_ADC_Stop(&hadc1);

	volt = (float)adc/113.4f;

	return volt;
}
