#include "app_sys.h"
#include "mySystem.h"
#include "myLog.h"



#include <vector>
#include <string>




LOCAL std::vector<stru_app_msg_queue> g_vec_app_msg_queue = 
{
    {"mq_com_to_iec",               MSG_SIZE, MSG_NUM, NULL},
    {"mq_iec_to_com",               MSG_SIZE, MSG_NUM, NULL},
    {"mq_com_to_self_ptl",          MSG_SIZE, MSG_NUM, NULL},
    {"mq_self_ptl_to_com",          MSG_SIZE, MSG_NUM, NULL},
};


LOCAL std::vector<stru_app> g_vec_app = 
{
    {"app_cmd",         0,  app_cmd_init1,          app_cmd_init2,          (app_func_cb)app_cmd,           NULL, 0, NULL},
    {"app_datacenter",  0,  app_datacenter_init1,   app_datacenter_init2,   (app_func_cb)app_datacenter,    NULL, 0, NULL},
    {"app_comm_channel",0,  app_com_channel_init1,  app_com_channel_init2,  (app_func_cb)app_com_channel,   NULL, 0, NULL},
    {"app_com_scan",    0,  app_com_scan_init1,     app_com_scan_init2,     (app_func_cb)app_com_scan,      NULL, 0, NULL},
    {"app_iec",         0,  app_iec_init1,          app_iec_init2,          (app_func_cb)app_iec,           NULL, 0, NULL},
    {"app_self_ptl",    0,  app_self_ptl_init1,     app_self_ptl_init2,     (app_func_cb)app_self_ptl,      NULL, 0, NULL},
    {"app_web_server",  0,  app_web_server_init1,   app_web_server_init2,   (app_func_cb)app_web_server,    NULL, 0, NULL},
    {"app_iec61850m",   0,  app_iec61850m_init1,    app_iec61850m_init2,    (app_func_cb)app_iec61850m,     NULL, 0, NULL},

};


LOCAL uint32_t g_timer_event[TIMER_NUM] = {EV_TIMER1, EV_TIMER2, EV_TIMER3};


LOCAL void app_timer_expire(void *arg)
{
    if(NULL == arg)
    {
        return;
    }

    uint32_t signal = *(uint32_t *)arg;

    uint8_t thid = signal >> 8;
    uint8_t tm_id = signal & 0xff;

    if(thid >= g_vec_app.size() || tm_id >= TIMER_NUM)
    {
        LOG_E("app_timer_expire failed, thid:%d, tm_id:%d", thid, tm_id);
        return;
    }

    task_event_send(g_vec_app[thid].p_event, g_timer_event[tm_id]);
}

LOCAL int app_timer_create(stru_app *p_app )
{
    if(NULL == p_app)
    {
        LOG_E("app_timer_create arg is NULL");
        return -1;
    }

    uint32_t delay_ms = 1;
    for(int i = 0; i < TIMER_NUM; i++)
    {
        std::string tm_name = std::string(p_app->name) + "_tm" + std::to_string(i+1);
        p_app->timer_arg[i] = ((p_app->app_id << 8) | i) & 0xffff;
        delay_ms *= 10;
        p_app->p_timer[i] = task_timer_create(tm_name.c_str(), app_timer_expire, (void *)&p_app->timer_arg[i], delay_ms, TASK_TIMER_FLAG_PERIODIC);
        if(NULL == p_app->p_timer[i])
        {
            LOG_E("timer%d create failed", i+1);
            return -1;
        }
        task_timer_start(p_app->p_timer[i]);
    }

    return 0;
}


LOCAL int app_msg_queue_init()
{
    uint32_t i = 0;
    for(i = 0; i < g_vec_app_msg_queue.size(); i++)
    {
        stru_app_msg_queue *p = &g_vec_app_msg_queue[i];

        p->p_msg_queue = task_msg_queue_create(p->name, p->msg_size, p->msg_num);
        if(!p->p_msg_queue)
        {
            MY_LOG_E("task_msg_queue_create failed, name:%s, msg_size:%d, msg_num:%d", p->name, p->msg_size, p->msg_num);
            return -1;
        }
    }

    return 0;
}

LOCAL int app_init()
{
    uint32_t i = 0;

    for(i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];
        if(NULL == p->app_init1)
        {
            continue;
        }
        
        if(0 != p->app_init1((void *)p))
        {
            MY_LOG_E("app_init1 failed, name:%s", p->name);
            return -1;
        }
    }

    for(i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];
        if(NULL == p->app_init2)
        {
            continue;
        }

        if(0 != p->app_init2((void *)p))
        {
            MY_LOG_E("app_init2 failed, name:%s", p->name);
            return -1;
        }
    }

    for(i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];

        p->app_id = i;

        std::string ev_name = "EV_" + std::string(p->name);
        p->p_event = task_event_create(ev_name.c_str());
        if(!p->p_event)
        {
            MY_LOG_E("task_event_create failed, name:%s", ev_name.c_str());
            return -1;
        }

        p->arg = (void *)p;

        if(0 != app_timer_create(p))
        {
            MY_LOG_E("app_timer_create failed, name:%s", p->name);
            return -1;
        }
        
        if(0 != pthread_create(&p->thread, NULL, p->fun_cb, p->arg))
        {
            MY_LOG_E("pthread_create failed, name:%s", p->name);
            return -1;
        }
        else
        {
            MY_LOG_I("pthread_create success, name:%s", p->name);
        }
        pthread_detach(p->thread);

        task_sleep_ms(10);
    }

    return 0;
}

int app_sys_init(void)
{
    uint32_t size = 0;
    if((size = g_vec_app_msg_queue.size()) != ENUM_MQ_MAX)
    {
        MY_LOG_E("g_vec_app_msg_queue size error, size = %d, ENUM num %d", size, ENUM_MQ_MAX);
        return -1;
    }

    if((size = g_vec_app.size()) != ENUM_APP_MAX)
    {
        MY_LOG_E("g_vec_app size error, size = %d, ENUM num %d", size, ENUM_APP_MAX);
        return -1;
    }

    if(0 != app_msg_queue_init())
    {
        MY_LOG_E("app_msg_queue_init failed");  
        return -1;
    }

    if(0 != app_init())
    {
        MY_LOG_E("app_init failed");  
        return -1;
    }

    return 0;
}


stru_app_msg_queue *app_get_msg_queue_ptr(uint32_t mq_id)
{
    if(mq_id >= ENUM_MQ_MAX)
    {
        LOG_E("mq_id over ENUM_MQ_MAX, mq_id %d, max %d", mq_id, ENUM_MQ_MAX);
        return NULL;
    }

    return &g_vec_app_msg_queue.at(mq_id);
}

stru_app *app_get_ptr(uint32_t app_id)
{
    if(app_id >= ENUM_APP_MAX)
    {
        LOG_E("app_id over ENUM_APP_MAX, app_id %d, max %d", app_id, ENUM_APP_MAX);
        return NULL;
    }

    return &g_vec_app.at(app_id);
}



