#!/usr/bin/perl
# http://userside.ua/wiki/index.php/usm_stat - Module Information
$moduleRevision = "20";
$moduleVersion  = "usm_stat v.3.8." . $moduleRevision; #Version

#========================================================================
# Custom configuration
#========================================================================

$isDebugMode    = 0; #Debug Mode [0/1]

#========================================================================

use Time::Local;
use FindBin;
use URI;
use URI::Escape;
use LWP::UserAgent;
use JSON;
use Data::Dumper;

$modulePath = $FindBin::RealBin . "/";

#Загрузка параметров из файла конфигурации
open ($file, $modulePath . "usm_stat.conf") || die "ERROR: Open Config File " . $modulePath . "usm_stat.conf\n";
close $file;
require($modulePath . "usm_stat.conf");

#Присвоение пустым параметрам значений по-умолчанию
$logsFullPath = $logsPath . '/usm_stat_';
if ($interval < 1) {
    $interval = 45;
}

#Стартовые действия
initializeModule(1);

#Загружаем параметры из системы
my $data = {
  'key'             => $usApiKey,
  'cat'             => 'usm_stat',
  'action'          => 'module_start',
  'module_version'  => $moduleVersion,
  'module_path'     => uri_escape($modulePath),
  'logs_path'       => uri_escape($logsPath)
};
$response = apiRequest('post', $data, 'module_start');

$isModuleEnable = $response->{'data'}->{'is_module_enable'};
$moduleMinAllowVersion = $response->{'data'}->{'module_min_allow_version'};
$lastActivityFix = $response->{'data'}->{'lastActivityFix'};
$lastActivityFixUnix = $response->{'data'}->{'lastActivityFixUnix'};

#Проверяем версию и включен ли модуль
verifyModulePermit();

#Фиксируем в логе параметры этого модуля
writeToLogModule("interval              = " . $interval);
writeToLogModule("lastActivityFix       = " . $lastActivityFix);

#Начинаем работу
$isWork = 0;
if ($lastActivityFixUnix < 100000) {
    $isWork = 1;
} else {
    $dateInterval = ($lastActivityFixUnix + 60 * $interval) - time;
    if ($dateInterval < 0) {
        $isWork = 1;
    }
}
$lastActivityFixUnix = time - 60 * $interval;
$timeStat = getFormatDateTime("YYYY-MM-DD hh:mm:ss", $lastActivityFixUnix);
writeToLogModule("timeStat              = " . $timeStat);
if ($isWork ne 1) {
    writeToLogModule("update stat disabled. DateInterval: " . $dateInterval);
} else {
    my $data = {
      'key'             => $usApiKey,
      'cat'             => 'usm_stat',
      'action'          => 'doing',
      'time_stat'       => $timeStat
    };
    $responce = apiRequest('post', $data, 'doing');
    $countActivity = $response->{'count_activity'};    
    $customerList = $response->{'customer_list'};    
    writeToLogModule("CustomerList: " . $customerList);
}

#Отмечаем, что мы закончили работу
my $data = {
  'key'             => $usApiKey,
  'cat'             => 'usm_stat',
  'action'          => 'module_finish'
};
$response = apiRequest('post', $data, 'module_finish');

moduleFinish();

exit(0);

### ================================================================================================================
#Standart Module Light Function v.2.7 - 20.12.2015
#================================================================================================================

sub moduleFinish
{
    my($additionalText) = @_;    
    open ($file, ">>" . $logLaunches) || die "ERROR: Open file " . $logLaunches . ". Verify path and rights\n";
        if ($additionalText ne '') {
            print $file $moduleVersion . " " . $additionalText . "\n";
            if ($isSilence ne 1) {
                print $additionalText . "\n";
            }
            #writeToLogModule($additionalText);
        }
        if ($additionalText eq '') {
            writeToLogModule($moduleVersion . " - finish module");
            print $fileLogModule "===============================================================================\n";
            close $fileLogModule;
            print $file $moduleVersion . " Module FINISH at " . getFormatDateTime() . "\n";
            print $file "==========================================================\n";
        }
    close $file;
    if ($isSilence ne 1 && $additionalText eq '') {
        print 'Finish module at ' . getFormatDateTime() . "\n";
        print "====================================\n";
    }
}

sub verifyModulePermit 
{
    if ($isModuleEnable ne 1) {
        moduleFinish("Module disabled in system - exit");
        exit(1);
    }
    if ($moduleRevision < $moduleMinAllowVersion || $moduleMinAllowVersion < 1) {
        moduleFinish('Version failure. Need version: ' . $moduleMinAllowVersion . " - exit");
        exit(1);
    }
}

sub initializeModule {
    my $isAllowPid     = $_[0];
    $logLaunches = $logsFullPath . 'launches.log';
    $logModule = $logsFullPath . 'module.log';

    if ($ARGV[0] eq 'debug' || $ARGV[1] eq 'debug' || $ARGV[2] eq 'debug') {
        $isDebugMode = 1;
    }

    #Удаляем громоздкий файл
    $size  = -s $logLaunches;
    if ($size > 100000) {
        unlink($logLaunches);
    }
    
    open ($file, ">>" . $logLaunches) || die "ERROR: Open file " . $logLaunches . ". Verify path and rights\n";
        print $file $moduleVersion . ' Module START  at ' . getFormatDateTime() . "\n";
    close $file;

    if ($isAllowPid ne 1) {
        $pidFile = $logsFullPath . 'pid.pid';
        if (-e $pidFile) {
            unless (open(PIDFILE, $pidFile)) {
                moduleFinish("Find previous PID - exit");
                close PIDFILE;
                exit(1);
            }
            $oldpid = <PIDFILE>;
            close PIDFILE;
            if ($oldpid > 1 && kill(0, $oldpid)) {
                moduleFinish("Find previous PID " . $oldpid . " - exit");
                exit(1);
            }
        }
        open(PID, ">" . $pidFile) || die "ERROR: Open file pid.pid. Verify path and rights\n";
            print PID $$;
        close(PID);
    }

    #Выведем заголовок модуля
    if ($isSilence ne 1) {
        print $moduleVersion . "\n";
        print "====================================\n";
        print ' Start module at ' . getFormatDateTime() . "\n";
    }
    
    open ($fileLogModule, ">" . $logModule) || die "ERROR: Open file " . $logModule . ". Verify path and rights\n";
    print $fileLogModule "===============================================================================\n";
    
    #Фиксируем версию модуля и путь к модулю
    writeToLogModule($moduleVersion . " - start module");
    writeToLogModule($modulePath);
    
    #Фиксируем основные параметры
    writeToLogModule("isSilence = " . $isSilence);
}

sub writeToLogModule
{
    my($string) = @_;
    print $fileLogModule getFormatDateTime() . " - " . $string . "\n";
}

sub trim 
{
    my($string) = @_;
    for ($string) {
        s/^\s+//;
        s/\s+$//;
    }
    return $string;
}

sub ip2long
{
    return unpack("N", inet_aton(shift));
}

sub long2ip 
{
    return inet_ntoa(pack("N",shift));
}

sub apiRequest
{
    my $requestType     = $_[0];
    my $data     = $_[1];
    my $comment     = $_[2];
    writeToLogModule("API Request: " . $comment);
    if ($requestType eq 'get') {
        $response = curlGet($data);
    }
    if ($requestType eq 'post') {
        $response = curlPost($data);
    }
    $result = $response->{'result'};
    if ($result eq '') {
        $result = $response->{'Result'};
    }
    writeToLogModule("Result: " . $result);
    if ($result eq 'ERROR') {
        $errorText = $response->{'error_text'};
        if ($errorText eq '') {
            $errorText = $response->{'ErrorText'};
        }
        writeToLogModule("Error: " . $errorText);
        moduleFinish("API Error - " . $errorText . " - exit");
        exit(1);
    }
    return $response;
}

sub curlPost
{
    my $data     = $_[0];
    my $ua       = LWP::UserAgent->new(ssl_opts=>{verify_hostname => 0});
    my $response = $ua->post($usUrl . "/api.php", $data);
    if ($isDebugMode eq 1) {
        print  Dumper($response);
    }
    $content = $response->decoded_content;
    if (substr(trim($content), 0, 1) ne '{') {
        writeToLogModule("Content: " . $content);
        $content = '{}';
    }
    return decode_json($content);
}

sub curlGet
{
    my $data     = $_[0];
    my $ua       = LWP::UserAgent->new(ssl_opts=>{verify_hostname => 0});
    my $url = URI->new($usUrl . "/api.php");
    $url->query_form($data);
    my $req = HTTP::Request->new(GET => $url);
    $req->header('content-type' => 'application/json', 'accept' => 'application/json');
    my $response = $ua->request($req);
    if ($isDebugMode eq 1) {
        print  Dumper($response);
    }
    return decode_json($response->decoded_content);
}

sub getFormatDateTime 
{
    my $format = shift @_ || "YYYY-MM-DD hh:mm:ss";
    my $datetime = shift @_ || time;
    my %strings = (
        '500'=>"AM", '501'=>"PM",
        '400'=>"January", '401'=>"February", '402'=>"March", '403'=>"April", '404'=>"May", '405'=>"June", '406'=>"July", '407'=>"August", '408'=>"September", '409'=>"October", '410'=>"November", '411'=>"December",
        '300'=>"Jan", '301'=>"Feb", '302'=>"Mar", '303'=>"Apr", '304'=>"May", '305'=>"Jun", '306'=>"Jul", '307'=>"Aug", '308'=>"Sep", '309'=>"Oct", '310'=>"Nov", '311'=>"Dec",
        '200'=>"Sunday", '201'=>"Monday", '202'=>"Tuesday", '203'=>"Wednesday", '204'=>"Thursday", '205'=>"Friday", '206'=>"Saturday",
        '100'=>"Sun", '101'=>"Mon", '102'=>"Tue", '103'=>"Wed", '104'=>"Thu", '105'=>"Fri", '106'=>"Sat"
    );
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($datetime);
    $year += 1900;
    if ($format=~m/AM/) {
        my $ampmhour=($hour % 12) || 12;
        $format=~s/hh/sprintf("%02u",$ampmhour)/eg;
        $format=~s/h/$ampmhour/eg;
        $format=~s/AM/($hour>11?"^501":"^500")/eg;
    } else {
        $format=~s/hh/sprintf("%02u",$hour)/eg;
        $format=~s/h/$hour/eg;
    };
    $format=~s/mm/sprintf("%02u",$min)/eg;
    $format=~s/m/$min/eg;
    $format=~s/ss/sprintf("%02u",$sec)/eg;
    $format=~s/s/$sec/eg;

    $format=~s/YYYY/$year/eg;
    $format=~s/YY/sprintf("%02u",$year % 100)/eg;
    $format=~s/MMMM/sprintf("^4%02u",$mon)/eg;
    $format=~s/MMM/sprintf("^3%02u",$mon)/eg;
    $format=~s/MM/sprintf("%02u",$mon+1)/eg;
    $format=~s/M/($mon+1)/eg;
    $format=~s/DDDD/sprintf("^2%02u",$wday)/eg;
    $format=~s/DDD/sprintf("^1%02u",$wday)/eg;
    $format=~s/DD/sprintf("%02u",$mday)/eg;
    $format=~s/D/$mday/eg;
    $format=~s/\^(\d\d\d)/$strings{$1}/g;
    return $format;
}
