#include "Main_Thread.h"
#include "Main_Private.h"
#include "CmsisRtosThreadUtils.h"
#define LOGGER &env->slog.logger
#define LOG_SIGN "Main"

/**
 * Процедура инициализации и запуска подсистем
 * Логирование, хранилище, командный интерфейс
 * @param env
 */
#undef LOG_SIGN
#define LOG_SIGN "Main_ISS"
static void MainThread_InitSubSystems(tMain *env){
    /// Инициализация Логирования
    LoggerToSerialPort_Init(
            &env->slog,
            0,
            &SERIAL_PORTS.comint_IO, //Пока нет платы с 485
            //&SERIAL_PORTS.comint_HD_IO, //485
            NULL,
            SERIAL_LOGGER_SHOW_AUTHOR | SERIAL_LOGGER_SHOW_LOG_LEVEL
    );
    LoggerInfoStatic(LOGGER, LOG_SIGN, "Start Logging")
    /// Инициализация Индикации
    Indication_Init(&env->indication,&env->gpios.ledPins);
    LoggerInfoStatic(LOGGER, LOG_SIGN, "Indication Init Completed")
    /// Передача интерфейса логирования в хранилище
    env->storage.logger = &env->slog.logger;

    /// Инициализация хранилища
    StorageOnFlash_Init();
    if(DeviceStorage_Init(&env->storage, &env->flash->interface) == false){
        LoggerErrorStatic(LOGGER, LOG_SIGN, "Storage Init Error")
    } else {
        LoggerInfoStatic(LOGGER, LOG_SIGN, "Storage Init Completed")
    }

    /// Запуск потока дампера
    VarsTabDumpObserver_StartThread(&env->storage.dumpObserver);

    /// Запуск потока индикации
    Indication_StartThread(&env->indication);
}

/**
 * Процедура Потока MAIN
 * @param env
 */
#undef LOG_SIGN
#define LOG_SIGN "Main_Thread"
_Noreturn void Main_Thread(tMain *env) {

    MainThread_InitSubSystems(env);

    LoggerInfoStatic(LOGGER, LOG_SIGN, "Start main loop")

    while (1){
        ///Вызов процедуры обработчика
        Main_Processing(env);
        SystemDelayMs(MAIN_THREAD_DELAY_MS);
    }
}

/**
 * Процедура вызова запуска потока MAIN
 * @param env
 */
void Main_StartThread(tMain *env){
    if (!env->thread.id) {
        env->thread.id = osThreadNew((osThreadFunc_t) (Main_Thread), (void *) (env), &env->thread.attr);
    } else {
        osThreadResume(env->thread.id);
    }
}

/**
 * Процедура инициализации потока MAIN
 * @param env
 */
void Main_InitThread(tMain *env){
    InitThreadAtrStatic(&env->thread.attr, "MAIN", env->thread.controlBlock, env->thread.stack, osPriorityNormal);
    env->thread.id = 0;
}