#include <stdint.h>
#include "sys_api.h"
#include "sys_hal.h"
#include "settings_api.h"
#include "common_config.h"
#include "common.h"
#include "rtc.h"
#include <string.h>
#include <stdio.h>



//
bool sys_set_default(sys_settings_t *settings) 
{
    settings->sn = 0;
    
	settings->prod_date = 0;
    
	settings->test_state = 0;
        
	settings->control_word = SETTINGS_CONTROL_WORD;

    settings->crc = SYS_GetCRC(settings);
    
	return true;
}

//
uint32_t SYS_GetCRC(sys_settings_t *settings)
{
    crc_data_reset();
    return crc_block_calculate((uint32_t *)settings, sizeof(*settings)/4 - 1);
}

//
bool sys_settings_load(sys_settings_t *settings)
{
    uint32_t loadCRC;  // CRC из flash
    uint32_t newCRC;   // CRC загруженной структуры настроек
    bool need_default = false;

    if (!settings)
  		return false;

    SYS_ReadFromFlash((uint8_t*)settings, sizeof(*settings), SYS_SECTOR);

    // Считываем CRC из флеш памяти
    loadCRC = (*(uint32_t*)SYS_CRC_ADDRESS);

    // Рассчитываем CRC для структуры настроек
    newCRC = SYS_GetCRC(settings);

    // Если CRC не совпадают нужно прошивать дефолтные настройки
    if (loadCRC != newCRC)
    {
        DBG printf("Bad system sector CRC. Factory defaults restored.\r\n");
        need_default = true;
    }
    // CRC совпала, проверяем контрольное слово если слово не совпадает
	// то это значит, что поплыла структура нстроек, прошиваем дефолт */
    else if (settings->control_word != SETTINGS_CONTROL_WORD)
    {
        DBG printf("Bad system sector control word. Factory defaults restored.\r\n");
        need_default = true;
    }

    // Прошиваем дефолтные настройки если нужно
    if (need_default) 
    {
        sys_set_default(settings);
        sys_save(settings);
    }

    DBG sys_print(settings);

    return true;
}

// Запись структуры настроек во flash
bool sys_save(sys_settings_t *settings)
{
	uint32_t crc_user = 0;

	if (!settings)
		return false;

	crc_user = SYS_GetCRC(settings);

	SYS_WriteToFlash((uint8_t*)settings, sizeof(*settings), crc_user);

	return true;
}

//
void sys_print(sys_settings_t *settings)
{
    TM_RTC_t data;
    
    printf("\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n");
    printf("   Системные настройки:\r\n");
    
    printf("\tСерийный номер: %u\r\n", settings->sn);
    
    TM_RTC_GetDateTimeFromUnix(&data, settings->prod_date);
    printf("\tДата производства: ");       
	printf("%02d.%02d.%02d %02d:%02d:%02d\r\n", data.date, data.month, data.year,
			data.hours, data.minutes, data.seconds);
    
    printf("\tСтатус тестирования: ");
    switch (settings->test_state) {
        case 0 : printf("NO Test\r\n"); break;
        case 1 : printf("Test OK\r\n"); break;
        case 2 : printf("Test FAIL\r\n"); break;
        default : break;
    }
    
    printf("\tКонтрольное слово: ");
    printf("%u\r\n", settings->control_word);
    
    printf("\tCRC: ");
    printf("0x%X\r\n", settings->crc);
    
    printf("\r\n\n");
}

// Очистить сектор системных настроек
void sys_clear(void)
{
    flash_unlock();
    SYS_EraseFlashSector();
    flash_lock();
}

