
#include "mw_shutdownmgr.h"
#include "htime.h"
#include "hthread.h"
#include "hbase.h"
#include "hlog.h"
#include "hmutex.h"



typedef struct{
  hthread_t     th;
  hmutex_t		mutex;
  hsem_t 		sem;
  uint8_t 		exit;
  struct list_head wakeuplist;
}shutdownmgr_s;


typedef struct {
    struct list_head link;
    WAKEUP_SOURCE src;
    uint64_t start_ms;
    uint64_t expire_ms;
}wakeup_src_s;

static shutdownmgr_s *s_mgr;

static void start_ms_shutdown();
static void *thread_entry(void *param){
    shutdownmgr_s *mgr = (shutdownmgr_s*)param;
    hlogd("%s start_ms:%p", __func__, param);
    for(;;)
    {
        {
            hmutex_lock(&mgr->mutex);
            struct list_head *pos = NULL, *n = NULL;
            list_for_each_safe(pos, n, &mgr->wakeuplist) {
                wakeup_src_s* src = list_entry(pos, wakeup_src_s, link);
                uint64_t now = gettimeofday_ms();
                if( now > src->expire_ms) {
                    hlogd("now:%llu src %d expire_msd start_ms: %llu expire_ms:%llu interval: %llu ms", now, src->src, src->start_ms, src->expire_ms, src->expire_ms - src->start_ms);
                    list_del(&src->link);
                    hv_free(src);
                }//else Whlogd(myLog, "src %d param %d now %ld, expire_ms: %ld", src->src, src->param, clock(), src->expire_ms);
            }
            hmutex_unlock(&mgr->mutex);
            if(list_empty(&mgr->wakeuplist)) {
                break;
            }
        }
        hv_msleep(100);
    }

    hlogw("%s go to shutdown", __func__);

    //standby();
    return NULL;
}

void shutdownmgr_set(WAKEUP_SOURCE source, uint32_t expire_ms_ms){
    shutdownmgr_s *mgr;
    if (!s_mgr ){
        s_mgr = hv_malloc(sizeof(shutdownmgr_s));
        INIT_LIST_HEAD(&s_mgr->wakeuplist);
        hmutex_init(&s_mgr->mutex);
        s_mgr->th = hthread_create(thread_entry, s_mgr);
    }
    mgr = s_mgr;
    
    hmutex_lock(&mgr->mutex);
    struct list_head *pos, *n;
    list_for_each_safe(pos, n, &mgr->wakeuplist)
    {
        wakeup_src_s* src = list_entry(pos, wakeup_src_s, link);
        if(src->src == source) {
            src->expire_ms = gettimeofday_ms() + expire_ms_ms;
            hmutex_unlock(&mgr->mutex);
            return;
        }
    }
    wakeup_src_s *src = hv_malloc(sizeof(wakeup_src_s));
    src->src    = source;
    src->start_ms  = gettimeofday_ms();
    src->expire_ms = src->start_ms + expire_ms_ms;
    list_add_tail(&src->link, &mgr->wakeuplist); 
    hmutex_unlock(&mgr->mutex);

    hloge("addWakeupSource %d now:%llu, after: %llums, expire_ms: %llu", source, gettimeofday_ms(), expire_ms_ms, src->expire_ms);
    start_ms_shutdown();
}

void start_ms_shutdown()
{
    hlogd("start_ms_shutdown:%s",  __func__);
}



void shutdownmgr_test()
{
    shutdownmgr_set(WAKEUP_DEFAULT, 2*1000);
    shutdownmgr_set(WAKEUP_USER,    5*1000);
    shutdownmgr_set(WAKEUP_QRCODE,  8*1000);
}
