#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <time.h>
#include <limits.h>

#include "kylinlogger_c.h"

static int log_level = LOG_INFO;
static FILE *log_fp = NULL;
static char *level_str[] = { "DEBUG", "INFO", "WARN", "ERROR", "NOTICE","FATAL" };

static int verify_file(char *path_name)
{
    if(strcmp(path_name, "/") == 0)
        return false;
    return true;
}

int logger_init(const char *name,int verbose)
{
    //char log_path[128] = { 0 };
    char *log_path = NULL;
    const char *homedir;
    int ret;

    log_path = malloc(PATH_MAX);
    if(log_path == NULL){
        return -1;
    }

    if( name != NULL )
    {
        /* get home dir */
        if ((homedir = getenv("HOME")) == NULL) {
            struct passwd *pw = getpwuid(getuid());
            if (pw == NULL) {
                fprintf(stderr, "[x264]logger: cannot get HOME dir\n");
                return -1;
            }

            homedir = pw->pw_dir;
        }

        memset(log_path, 0, PATH_MAX);
        realpath(homedir, log_path);
        if(strnlen(log_path, PATH_MAX) <=0){
            printf("realpath get asb path error\n");
            return -1;
        }else{
            printf("log_path: %s\n", log_path);
        }

        if(!verify_file(log_path)){
            printf("verify file error: invalid argument, the input path(%s) is not in the directory /home/userdir/\n", homedir);
            return -1;
        }

        strncat(log_path, "/.stream-server/" , sizeof(log_path) - strlen(log_path) - 1);

        ret = access(log_path, F_OK);
        if (ret) {
            fprintf(stdout, "[x264]logger: logger dir not exist, create it\n");
            ret = mkdir(log_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
            if (ret) {
                fprintf(stderr, "[x264]logger: create [x264]logger dir failed\n");
                return -1;
            }
        }

        strncat(log_path, name,sizeof(log_path) - strlen(log_path) - 1);

        fprintf(stdout, "[x264]logger: path is %s\n", log_path);

        log_fp = fopen(log_path, "a+"); // appending mode
        if (!log_fp) {
            fprintf(stderr, "[x264]logger: create log file failed\n");
            return -1;
        }
    }
    else
        log_fp = stdout;

    /* set logger log_level from env */
    char *level = getenv("SS_LOG_LEVEL");
    if (level) {
        if (strcmp(level, "DEBUG") == 0)
            log_level = LOG_DEBUG;
        else if (strcmp(level, "INFO") == 0)
            log_level = LOG_INFO;
        else if (strcmp(level, "WARN") == 0)
            log_level = LOG_WARN;
        else if (strcmp(level, "ERROR") == 0)
            log_level = LOG_ERROR;
        else if (strcmp(level, "FATAL") == 0)
            log_level = LOG_FATAL;
        else
            fprintf(stderr, "[x264]logger: env set error "
                            "DEBUG|INFO|WARN|ERROR|FATAL\n");
    }
    log_level = verbose;

    fprintf(stdout, "[x264]logger: current log level is %s\n", level_str[log_level]);
    fflush(stdout);
    return 0;
}

void logger_log(int level, const char *fmt, ...)
{
    char buffer[512] = { 0 }; // for thread safe
    int len;

    if (level < log_level)
        return;

    va_list vl;
    va_start(vl, fmt);
    time_t time_log = time(NULL);
    struct tm *tm_log = localtime(&time_log);

    len = snprintf(buffer , sizeof(buffer) , "\n[x264][%04d-%02d-%02d %02d:%02d:%02d] (%s): \n\t",
                  tm_log->tm_year + 1900, tm_log->tm_mon + 1, tm_log->tm_mday,
                  tm_log->tm_hour, tm_log->tm_min, tm_log->tm_sec,
                  level_str[level]);
    vsnprintf(buffer + len, 512 - len, fmt, vl);
    fwrite(buffer, strlen(buffer), 1, log_fp);
    va_end(vl);

    fflush(log_fp);
}

int logger_get_level()
{
    return log_level;
}

void logger_deinit()
{
    if( log_fp == stdout )
        return;
    //fprintf(log_fp, "\n=========================================\n");
    fflush(log_fp);
    fclose(log_fp);
}
