/**
 * Copyright 2016 the WHATAP project authors. All rights reserved.
 * Use of this source code is governed by a license that
 * can be found in the LICENSE file.
 */
 var WHATAP_CONF  = process.env.WHATAP_CONF || 'whatap';

 var conf     = require('./conf/configure'),
     DateUtil = require('./util/dateutil'),
     path     = require('path'),
     fs       = require('fs');
 
 var PID=process.pid;
 
 var initializer = {
     last : DateUtil.currentTime(),
     lastDateUnit : DateUtil.getDateUnit(),
     lastFileRotation : true,
     reset : function () {
         if(Logger.printWriter)
             Logger.printWriter.close();
         Logger.logfile = null;
         Logger.openFile();
     },
     process : function () {
         conf  = require('./conf/configure');
         var now = DateUtil.currentTime();
         if(now > this.last + DateUtil.MILLIS_PER_HOUR) {
             this.last = now;
             // Logger.clearOldLog();
         }
         if(this.lastFileRotation !== conf.log_rotation_enabled
             || this.lastDateUnit !== DateUtil.getDateUnit()
             || (Logger.logfile !== null && fs.existsSync(Logger.logfile) == false)) {
             try {
                 if(Logger.printWriter){
                     Logger.printWriter.close();
                 }
                 Logger.logfile = null;
                 this.lastFileRotation = conf.log_rotation_enabled;
                 this.lastDateUnit = DateUtil.getDateUnit();
             } catch(e) {
                 console.log(e);
             }
         }
         try {
             Logger.openFile();
         } catch(e) {
             console.log(e);
         }
     }
 };
 
 var Logger = {
     ONAME : null,
     logfile : null,
     lastLog : {},
     printWriter : null,
     printAll : function (id, message, sysout) {
         try{
             var b_msg = this.build(id, message);
             if(this.printWriter != null) {
                 this.printWriter.write(b_msg);
                 this.printWriter.write('\n');
             } else {
                 this.openFile();
             }
             sysout = (sysout || process.env.WHATAP_PRINT);
             if(sysout) {
                 console.log(b_msg);
             }
         } catch (e){
             if(sysout) {
                 console.log(e);
             }
         }
     },
     print : function (id, message, sysout) {
         if(this.checkOk(id, 10) == false) {
             return;
         }
         try{
             var b_msg = this.build(id, message);
             if(this.printWriter != null) {
                 this.printWriter.write(b_msg);
                 this.printWriter.write('\n');
             } else {
                 this.openFile();
             }
             sysout = (sysout || process.env.WHATAP_PRINT);
             if(sysout) {
                 console.log(b_msg);
             }
         } catch (e){
             if(sysout) {
                 console.log(e);
             }
         }
     },
     initPrint : function (message) {
        try{
            var b_msg = this.build("WHATAP-INIT", message + " starting!");
            if(this.printWriter != null) {
                this.printWriter.write(b_msg);
                this.printWriter.write('\n');
            } else {
                this.openFile();
            }
        } catch (e){
           
        }
    },
    printError : function (id, message, err, sysout) {
         if(this.checkOk(id, 10) == false) {
             return;
         }
         this.print(id, message, false);
         sysout = (sysout || process.env.WHATAP_PRINT);
         if(sysout) {
             console.error(this.build(id, message));
         }
         if(err) {
             if(this.printWriter != null) {
                 this.printWriter.write(err.stack);
                 this.printWriter.write('\n');
             }
         }
     },
     checkOk : function (id, sec) {
         if(conf.log_print_enabled === false) { return false; }
         if(conf.isIgnoreLog && conf.isIgnoreLog(id)) { return false; }
 
         if(Object.keys(Logger.lastLog).length >= 1000) {
             Logger.lastLog = {};
         }
 
         if(sec > 0) {
             var last = Logger.lastLog[id];
             if(last == null) {
                 last = 0;
             }
             var now = Date.now();
             if(now < last + sec * 1000) {
                 return false;
             }
             Logger.lastLog[id] = now;
         }
         return true;
     },
     build : function (id, message) {
         var str = DateUtil.datetime(Date.now());
         // str += ' ';
         // if(conf.getProperty('log_oname_enabled') && this.ONAME) {
         //     str += '['  + this.ONAME + ']'
         // }
         str += '[';
         str += id;
         str += '] <' + PID + '> ';
         str += message;
         return str;
     },
     openFile : function () {
         if(conf.log_file_enabled === false ) { return; }
         var log_prefix = WHATAP_CONF+"-hook-";
 
         var root = conf.getProperty('log_root', null) || process.env.WHATAP_HOME || conf['app.root'];
         if(root==null || root ==undefined){
             console.log('[WHATAP]Logger Error - WHATAP ROOT DIR IS NULL');
             return;
         }
         if(fs.existsSync(root) == false) {
             fs.mkdirSync(root, {recursive: true});
         }
         var dir = path.join(root, 'logs');
         if(fs.existsSync(dir) == false) {
             fs.mkdirSync(dir);
         }
 
         if(conf.log_rotation_enabled) {
             var file = path.join(dir, log_prefix + DateUtil.yyyymmdd() + '.log');
             this.logfile = file;
             this.printWriter = fs.createWriteStream(file, {flags : 'a'});
         } else {
             var file = path.join(dir, 'whatap.log');
             this.logfile = file;
             this.printWriter = fs.createWriteStream(file, {flags : 'a'});
         }
 
     },
     clearOldLog: function () {
         if (conf.log_rotation_enabled === false || conf.log_enabled === false) {
             return;
         }
         if (conf.log_keep_days <= 0) {
             return;
         }

         var root = conf.getProperty('log_root', null) || process.env.WHATAP_HOME || conf['app.root'];
         if(root==null || root ==undefined){ return; }
         if(fs.existsSync(root) == false) {
             fs.mkdirSync(root, {recursive: true});
         }
         var nowUnit = DateUtil.getDateUnit(),
             dir = path.join(root, 'logs'),
             log_prefix = WHATAP_CONF + "-";

         fs.readdir(dir, function (err, files) {
             for (var i = 0; i < files.length; i++) {
                 var stat = fs.statSync(path.join(dir, files[i]));
                 if (stat.isDirectory()) {
                     return true;
                 }
                 var name = files[i];
                 if (name.indexOf(log_prefix) < 0) {
                     return true;
                 }
                 var x = name.lastIndexOf('.');
                 if (x < 0) {
                     return true;
                 }
                 var date = name.substr(log_prefix.length, (x - log_prefix.length));
                 if (date.length != 8) {
                     return true;
                 }
                 var d = DateUtil.yyyymmdd(date);
                 var fileUnit = DateUtil.getDateUnit(d);
                 try {
                     if (nowUnit - fileUnit > conf.log_keep_days) {
                         let filePath = `${dir}/${files[i]}`;
                         fs.rmSync(filePath);
                     }
                 } catch (e) {
                 }
             }
         });
     },
     read : function( file,  endpos,  length , callback) {
 
         if ( file == null || length === 0)
             return null;
         if (file.startsWith(WHATAP_CONF) == false)
             return null;
 
 
 
             var root = conf.getProperty('log_root', null) || process.env.WHATAP_HOME || conf['app.root'];
             if(root==null ){
                 return null;
             }
             var dir = path.join(root, 'logs');
             var fileFullPath = path.join(dir, file);
 
             if(fs.existsSync(fileFullPath) == false) {
                 return null;
             }
             const stats = fs.statSync(fileFullPath);
 
         if (endpos < 0) {
             endpos = stats.size;
         }
         
         var start = Math.max(0, endpos - length);
 
         if ( stats.size < start)
             return null;
             
         var available = stats.size - start;
         var readable = Math.min(available, length);
         var next=-1;
         var buffer = Buffer.alloc(readable);
         fs.open(fileFullPath, 'r', function (err, fd) {
             fs.read(fd, buffer, 0, buffer.length, start,function(e,l,b){
                 next = endpos + l;
                 if (next > stats.size) {
                     next = -1;
                 }
                 callback(start, next,b.toString("utf8",0,l)) ;
             });
             fs.close(fd);
         });
        
     },
     getLogFiles : function () {
         var MapValue = require('./value/map-value');
         var log_prefix = WHATAP_CONF+"-";
 
         var o = new MapValue();
         if(conf.log_file_enabled === false ) { return o; }
         var root = conf.getProperty('log_root', null) || process.env.WHATAP_HOME || conf['app.root'];
         if(root==null){
             return o;
         }
         var dir = path.join(root, 'logs');
         if(fs.existsSync(dir) === false) {
             return o;
         }
         var agoOneMonthTime=DateUtil.getMonth(Date.now(), -1);
 
         if(conf.log_rotation_enabled) {
             var files = fs.readdirSync(dir);
             files.forEach(function (file) {
                 if (file.startsWith(log_prefix) == false) {
                     return;
                 }
                 var x = file.lastIndexOf('.');
                 if (x < 0) {
                     return;
                 }
                 var date = file.substring(log_prefix.length , x);
                 if (date.length != 8) {
                     return;
                 }
                 if (DateUtil.yyyymmdd(date) < agoOneMonthTime) {
                     return;
                 }
                 const stats = fs.statSync(dir + '/'+file);
                 if(stats){
                     o.putLong(file, stats.size);
                 }
             });
         } else {
             if (fs.existsSync(dir + "/whatap.log")) {
                 const stats = fs.statSync(dir + "/whatap.log");
                 o.putLong(file, stats.size);
             }
         }
         return o;
     },
     initializer : initializer,
     CODE: {
         
     }
 };
 
 module.exports = Logger;