#include <iostream>
#include <vector>
#include <string>


#define UPS_MODE_MONITOR

using namespace std;

#define TM_RTC_LEAP_YEAR(year) 			((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
#define TM_RTC_DAYS_IN_YEAR(x)			(bool)TM_RTC_LEAP_YEAR(x) ? 366 : 365
#define TM_RTC_OFFSET_YEAR				1970
#define TM_RTC_SECONDS_PER_DAY			86400
#define TM_RTC_SECONDS_PER_HOUR			3600
#define TM_RTC_SECONDS_PER_MINUTE		60
#define TM_RTC_BCD2BIN(x)				((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
#define TM_RTC_CHAR2NUM(x)				((x) - '0')
#define TM_RTC_CHARISNUM(x)				((x) >= '0' && (x) <= '9')




typedef struct {
	uint8_t seconds;     /*!< Seconds parameter, from 00 to 59 */
	uint16_t subseconds; /*!< Subsecond downcounter. When it reaches zero, it's reload value is the same as
                                 @ref RTC_SYNC_PREDIV, so in our case 0x3FF = 1023, 1024 steps in one second */
	uint8_t minutes;     /*!< Minutes parameter, from 00 to 59 */
	uint8_t hours;       /*!< Hours parameter, 24Hour mode, 00 to 23 */
	uint8_t day;         /*!< Day in a week, from 1 to 7 */
	uint8_t date;        /*!< Date in a month, 1 to 31 */
	uint8_t month;       /*!< Month in a year, 1 to 12 */
	uint8_t year;        /*!< Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */
	uint32_t unixx;       /*!< Seconds from 01.01.1970 00:00:00 */
} TM_RTC_t;


uint8_t TM_RTC_Months[2][12] = {
	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},	/* Not leap year */
	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}	/* Leap year */
};

void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unixx);

//void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format);



int main()
{
#if 0    
	vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"};
	
	for (const string& word : msg)
	{
		cout << word << " ";
	}
	cout << endl;
#endif

    //printf("This year is :%u, %u\r\n", TM_RTC_LEAP_YEAR(2023), TM_RTC_DAYS_IN_YEAR(2023), TM_RTC_Months(2));
    //printf("This year is :%u\r\n", TM_RTC_Months[TM_RTC_LEAP_YEAR(24)][1]);

    TM_RTC_t data;

    TM_RTC_GetDateTimeFromUnix(&data, 1672640327);  // Mon Jan 02 2023 06:18:47 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1676189542);  // Sun Feb 12 2023 08:12:22 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1683619942);  // Tue May 09 2023 08:12:22 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1694333542);  // Sun Sep 10 2023 08:12:22 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1704010342);  // Sun Dec 31 2023 08:12:22 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n");

    TM_RTC_GetDateTimeFromUnix(&data, 1706688742);  // Wed Jan 31 2024 08:12:22 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1709194342);  // Thu Feb 29 2024 08:12:22 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1709281315);  // Fri Mar 01 2024 08:21:55 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1718180601);  // Wed Jun 12 2024 08:23:21 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    TM_RTC_GetDateTimeFromUnix(&data, 1735633401);  // Tue Dec 31 2024 08:23:21 GMT+0000
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);


    
    TM_RTC_GetDateTimeFromUnix(&data, 1709101127);
    printf("Month %u, Date %u, Year %u, %u:%u:%u\r\n", data.month, data.date, data.year, data.hours, data.minutes, data.seconds);

    //TM_RTC_GetDateTimeFromUnix(&data, 1709204345);

}


void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unixx) {
	uint16_t year;
	
	/* Store unix time to unix in struct */
	data->unixx = unixx;
	/* Get seconds from unix */
	data->seconds = unix % 60;
	/* Go to minutes */
	unixx /= 60;
	/* Get minutes */
	data->minutes = unixx % 60;
	/* Go to hours */
	unixx /= 60;
	/* Get hours */
	data->hours = unixx % 24;
	/* Go to days */
	unixx /= 24;
	
	/* Get week day */
	/* Monday is day one */
	data->day = (unix + 3) % 7 + 1;

	/* Get year */
	year = 1970;
	while (1) {
		if (TM_RTC_LEAP_YEAR(year)) {
			if (unixx >= 366) {
				unixx -= 366;
			} else {
				break;
			}
		} else if (unixx >= 365) {
			unixx -= 365;
		} else {
			break;
		}
		year++;
	}
	/* Get year in xx format */
	data->year = (uint8_t) (year - 2000);
	/* Get month */
	for (data->month = 0; data->month < 12; data->month++) {
/*        
        if (unixx == 0) {
            break;
        }
*/        
		if (TM_RTC_LEAP_YEAR(year) && unixx >= (uint32_t)TM_RTC_Months[1][data->month]) {
			unixx -= TM_RTC_Months[1][data->month];
		} else if (!TM_RTC_LEAP_YEAR(year) && unixx >= (uint32_t)TM_RTC_Months[0][data->month]) {
			unixx -= TM_RTC_Months[0][data->month];
		} else {
			break;
		}
	}
	/* Get month */
	/* Month starts with 1 */
	data->month++;
	/* Get date */
	/* Date starts with 1 */
	data->date = unixx + 1;
}


void ups_mode_response(char *data)
{
    char value[50];
    uint8_t len = 0;
    DBG printf("ups_serialresponse: %s\r\n", data);
    if (data[0] != '(') {
        return;
    }
    DBG printf("ups_serial_parser_start\r\n");
    UPS.Present = UPS_CONNECTED;
    UPS.Flag_Present = true;
    UPS.cnt_err_ups = 0;

    data++;

    DBG printf("UPS ups_mode_parser_start: %s\r\n", data);

    if (UPS.Mode != data[0]) {
        UPS.Mode = data[0]; 
#if 1
        memset(value, 0, sizeof(value));
        GetModeStr(value, &len);
        if(UPS.Mode == 'F') {
            memset(ups_pdu.data, 0, UPS_PDU_MAX_LEN);
            send_MegaTec_cmd(ups_fault_status);
            if (ups_megatec_rx_pdu()) {
                if (ups_pdu.data[0] != '(' || strncmp(ups_pdu.data, "(OK", 3) == 0) {
                    return;
                }
                UPS.fault_type = (ups_pdu.data[1] - 0x30) << 4 | (ups_pdu.data[2] - 0x30);
                strncat(value, &ups_pdu.data[1], 6);
                strncat(value, &ups_pdu.data[14], 4);
                strncat(value, &ups_pdu.data[25], 8);
                strncat(value, &ups_pdu.data[35], 4);
                strncat(value, &ups_pdu.data[41], 4);
                strncat(value, &ups_pdu.data[47], 4);
                strncat(value, &ups_pdu.data[53], 4);
                strncat(value, &ups_pdu.data[59], 8);
            }
        }
        SNMP_SendUserTrap(UPS_MODE);
        syslog(SYSLOG_INFORMATIONAL, "Режим ИБП: %s", value);
        log_event_data(LOG_UPS_MODE, value);
#endif
    }
   
}