/* DESC: A Script that can be used for a longtime logging of a NetModule Wireless Router. 
 * The upper part of the script is the logger template. The lower part is the real programm, where you describe the settings and workflow.
 * Copyright (C) 2014 NetModule AG, Switzerland
 */
    
template logger

{
    
    workfile="current.log";
    currentFilename="";
    currentLogStart=0; // the current logfile was startet at this time
    intervall=5; //new logentry every # seconds
    logfileIntervall=3600; //new logfile every # seconds
    //due to the fact that we cannot see the amount of free space in the  sdk
    // we need to improvise and add up the current filesizes   
    currentLogSize=0; //in Bytes
    maxLogSize=15000000;  //in Bytes
    freespace=1000000; //in Bytes
    # give the constructor the absolute path to store the Loggs into
    void logger(string path) {

        dh=opendir(path);    
        if(dh == -1) {
            if ( mkdir(path,0666) == -1 ); {
                nb_syslog("Could not create dir: %s. Exiting",path);
                exit(1);
            }
        } else {
        nb_syslog("directory already existent: %s", path);
        closedir(dh);
        }
        this.path = path;
        this.fields = mkarray();
        this.currentFilename=strftime("%Y%m%d_%H%M%S_start.log",localtime(time()));


    }

    int jiffy()
    {
        sys = sysinfo();
        u = struct_get(sys, "uptime");

        if (is_void(u) || u < 1) {
            return 0;
        } else {
            return u;
        }
    } 

    int addField(string fieldname) {
        if (strlen(fieldname) > 0 ) {
            this.fields = array_merge(this.fields, fieldname);
            return 0;

        } else {
            nb_syslog("Fieldname to short, not adding");
            return -1;
        }
    }

    int addFields(array localFields) {
       for (i=0; i < length(localFields); i++) {
            if (this.addField(localFields[i]) == -1 ) return -1;
        }   
    return 0;

    }
    
    int newLogfile() {
        
        // check if file if we have a work file an rename it to currentFile
        fd=fopen(sprintf("%s%s", this.path,this.workfile),"r" );
        if(fd) {
        // we have a current workfile lets rename it
        fclose(fd);
            if(!rename(sprintf("%s%s",this.path,this.workfile), sprintf("%s%s",this.path,this.currentFilename))){
                nb_syslog("Could not rename %s to %s, %s will be deleted",this.workfile, this.currentFilename,this.workfile);
                remove(sprintf("%s%s",this.path,this.workfile));  
            }
          
        } 
        //set new current Filename as we stored the old one away
        this.currentFilename=strftime("%Y%m%d_%H%M%S.log",localtime(time()));
        this.currentLogStart=this.jiffy();
        //creating Header   
        header="";
        for (i=0; i < length(this.fields); i++) {
            header=sprintf('%s%s;',header,this.fields[i]);   
        }   

        if(this.addLineToFile(header) == -1 ) {
            nb_syslog("writing of header to file: %s%s:", this.path,this.workfile);
            return -1;
        } else {
            return 0;
        }

    }

    int addLineToFile(string line) {
        fd=fopen(sprintf("%s%s", this.path,this.workfile),"a" );
        if (fd < 0 ) {
            nb_syslog("could not open file %s%s", this.path, this.workfile);
        }
      
        if(!fwrite(fd,sprintf("%s\n",line))) {
            nb_syslog("writing of line to file: %s%s:", this.path,this.workfile);
            fclose(fd);
            return -1;
        } else {
            fclose(fd);
            return 0;
        }

    } 

    int filesize(string file) {
        fd=fopen(file,"r");
        if (fd) {
        fseek(fd,-1);
        size=ftell(fd);
        fclose(fd);
        return size;
        } else {
            return -1;
        }
        
    }


    int logNow()  {
        
        //get current status output
        sections=mkarray("system","wan","wwan","wlan","gnss","lan","openvpn","ipsec","dio","license");
        status=mkstruct();
        for (i=0;i<length(sections);i++) {
            status=struct_merge(status,nb_status(sections[i]));
        }
        
        line="";
        for (i=0; i < length(this.fields); i++) {
            value=struct_get(status,this.fields[i]);
            if (strlen(value) == 0) {   
                value=sprintf("%s unknown",this.fields[i]);
            }
            line=sprintf('%s%s;',line,value);   
        }

        if(this.addLineToFile(line) == -1 ) {
            nb_syslog("writing of line to file failed: %s%s:", this.path,this.workfile);
            return -1;
        } else {
            return 0;
        }
        

    }

    int logRotate() {
        //get all files in path
        nb_syslog("Starting Logrotate");
        files=mkarray();
        handle = opendir(this.path);
        if (handle != -1) {
            while ((entry = readdir(handle))) {
                if (entry == ".") continue;
                if (entry == "..") continue;
                if (entry == this.workfile) continue;
                files=array_merge(files,entry);
            }
            closedir(handle);
        } else {
            nb_syslog("cannot open directory %s", this.path);
        }
        //sort old to new
        qsort(files);
        // files=array_reverse(files);
        //get current filesizes
        this.currenLogSize=0;
        sizes=mkarray();
        for(i=0;i<length(files);i++){
            size[i]=this.filesize(sprintf("%s%s",this.path,files[i]));
            this.currentLogSize=this.currentLogSize+size[i]; 
        }
        nb_syslog("Current Logsize: %i byte",this.currentLogSize);
        //if we don't have enough space delete enough old ones to have enough space
        for(i=0;i<length(files);i++) {
        if (this.currentLogSize < (this.maxLogSize-this.freespace)) break;
            if(remove(sprintf("%s%s",this.path,files[i]))) {
                this.currentLogSize=this.currentLogSize-size[i];
                nb_syslog("Removed %s%s",this.path,files[i]);
       
            } else {
                nb_syslog("could not remove %s%s",this.path,files[i]);
            }
        }
       nb_syslog("new logsize: %i", this.currentLogSize);
    return 0;
    }


} // of template logger

#template position {
#        
#    oldLat=0.0;
#3    oldLon=0.0;
#    currentLat=0.0;
#    currentLon=0.0;
#    isMoving=false;
#    movingDistance=100; // in metern
#    int getPosition() { 
#
#        this.oldLat=this.currentLat;
#        this.oldLon=this.currentLon;
#        gps_status=nb_status("gnss");
#        this.currenLon= struct_get(gps_status,"GNSS1_LONGITUDE");
#        this.currentLat=struct_get(gps_status,"GNSS1_LATITUDE");
#
#    }
#
#
#} // of template position

#################################################
#################################################
#################################################
#################################################
#################################################
#################################################

logging = nb_config_get("hotspot.logging");
if (logging=="0") {
    nb_syslog("Logging deactivated, exiting SDK Script");
    exit(0);
}

l = new logger("/logger/");

l.addFields(mkarray("SYSTEM_TIME","GNSS1_LONGITUDE","GNSS1_LATITUDE","GNSS1_SATELLITES_INVIEW","MOBILE1_SIGNAL","MOBILE1_SERVICE_TYPE","MOBILE1_NETWORK","WAN_HOTLINK","WANLINK1_STATE","WANLINK2_STATE","WANLINK1_DOWNLOAD_RATE","WANLINK1_UPLOAD_RATE","WANLINK2_DOWNLOAD_RATE","WANLINK2_UPLOAD_RATE","WANLINK1_DATA_DOWNLOADED","WANLINK1_DATA_UPLOADED","WANLINK2_DATA_DOWNLOADED","WANLINK2_DATA_UPLOADED")); 
l.addField("IN1");

l.newLogfile();
l.intervall=5; //log every 5sec

l.logfileIntervall=1800; //create a new file every 5 min


while (true) {

    l.logNow();
    sleep(l.intervall);
    // lets see if we need a new logfile
    if (l.currentLogStart+l.logfileIntervall<l.jiffy()) {
       l.newLogfile();
       l.logRotate();
    }
}

exit(0);
