#!/usr/bin/perl
use Time::localtime;

use strict;
use warnings;
use Data::Dumper;
use File::Basename qw(dirname);
use Log::Log4perl "get_logger";

# Load configuration (env may be emtpy on the start)
my $dirname = dirname(__FILE__);
open (ECF,"$dirname/../../base/etc/env.conf")     || die("Cannot read env.conf\n");
map {$ENV{$1}=$2 if /^(\w+)=(\S+)/} grep {/^\w+=\S+/} <ECF>;
close ECF;



my $UPDATE="$ENV{APL}/av/bin/update_av_position event=yes"; # create event
# VARS -------------------------
my $CONF_DIR="$ENV{APL_CONF}/av/";

# LOGS -------------------------
Log::Log4perl::init_and_watch("$ENV{APL}/common/etc/logger_sms.conf",60);
my $log= get_logger('SMS');

#--------------------------------------------------------------
sub update_status {
   my ($phone,$stat)=@_;
   $log->info($phone);
   $log->info(join(",",%$stat));
   opendir(DIR,$CONF_DIR) || $log->fatal("Can't opendir $CONF_DIR: $!");
   my @dirs= grep { /^\d+$/ } readdir(DIR);
   close DIR;
   foreach my $dir (@dirs) {
     if (open(CONF,"$CONF_DIR/$dir/conf")) {
       my %conf=map{/(^\w+)=(.+)/} grep {/^\w+=.+/} <CONF>;
       close CONF;
       if(exists $conf{TELEPHONE_NUMBER} and $conf{TELEPHONE_NUMBER} eq $phone) {
           my %old_stat;
           if (open(STAT,"$CONF_DIR/$dir/stat")) {   # read old stat
             %old_stat=map{/(^\w+)=(.+)/} grep {/^STAT_\w+=.+/} <STAT>;
             close STAT;
           }
           my %new_stat=(%old_stat,%$stat); #cobine old and new stat
           if(open(STAT,">$CONF_DIR/$dir/stat")) {
              print STAT "$_=$new_stat{$_}\n" foreach (sort keys %new_stat );
              close STAT;
              $log->info("$CONF_DIR/$dir/stat is updated");
              if(defined $stat->{STAT_POSITION}) {
                $log->info("position:$stat->{STAT_POSITION};");
                my $ret=`$UPDATE av=$conf{OBJID}`;
                $log->info("position:$stat->{STAT_POSITION}; ret:$ret");
              }
              return;
           }else {
              $log->warn("Cannot write $CONF_DIR/$dir/stat");
           }
       }
     }
   }
   $log->warn("cannot find phone $phone in DB");
}

#--------------------------------------------------------------
sub GLU_position {  # publish position
  my ($phone,$str)=@_;
  if($str=~/T=GLU,Lat=(-?\d+\.\d+),Long=(-?\d+\.\d+)/) { # ========= POSITION
    my %stat=(STAT_POSITION=>"$1,$2,0");
    %stat=() if $stat{STAT_POSITION} eq '0.0,0.0,0';     #ignore empty position
    update_status($phone,\%stat);
  }
}

#--------------------------------------------------------------
sub GSU_status {
    # T=GSU,S=3,OUT:(PR2=0,PDVR=1,PMW=0,FCUT=0,PRAD=1,PR1=0),IN:(Vb=12.91,Ts=39.25,MWS=0,TMP=0,TRP=0,DS=0,LCK=0,S1=1,HS=0,IGN=0,Cb=55,Sb=N)

    my ($phone,$str)=@_;
    my %stat=(
        STAT_RECORDING => '?',
        STAT_ENGINE => '?',
        STAT_RADIO => '?',
        STAT_TAMPER => '?',
        STAT_ACTIVITY => '?',
        STAT_TIME => time,
        STAT_BATTERY => '-1',
        STAT_BATTERY_STATE => 'Unknown',
        STAT_BATTERY_CAPACITY => '-1',
        STAT_CHANNEL_STATUS => '?',
        STAT_MESSAGE => 'status over sms',
        STAT_MESSAGE_TIME => time
    );
    if (my ($scenario,$out_str,$in_str) = $str =~ /S=(\d+),OUT:\((.+)\),IN:\((.+)\)/) {
        my %out=map{/(\w+)=(.*)/} grep {/\w+=.*/} split(',',$out_str);
        my %in =map{/(\w+)=(.*)/} grep {/\w+=.*/} split(',',$in_str);

        $log->debug("outputs: ". Dumper(\%out));
        $log->debug("inputs: " . Dumper(\%in ));

        if($out{FCUT}==1) {               # ---------- ENGINE
            $stat{STAT_ENGINE}='CUTOFF';
        }elsif($in{IGN}==1) {
            $stat{STAT_ENGINE}='RUN';
        }else {
            $stat{STAT_ENGINE}='STOP';
        }
        $stat{STAT_RECORDING} = ($out{PDVR}==1) ? 'ON' :'OFF';
        $stat{STAT_RECORDING} = 'OFF' if $scenario == 1; # OFFLOAD_DATA
        $stat{STAT_RADIO}     = ($out{PRAD} == 1) ? 'ON' :'OFF';
        $stat{STAT_TAMPER}    = ($in{TMP} == 1) ? 'ALERT' : 'NONE';
        $stat{STAT_ACTIVITY}  = 'YES' if $in{IGN} == 1; # overwrite if IGNITION

        $stat{STAT_BATTERY}   = "$in{Vb}v" if $stat{STAT_BATTERY} == -1;
        if ($in{Sb})
        {
            my %state = (
                U => 'Unknown',
                N => 'Normal',
                L => 'Low',
                Q => 'Questionable'
            );
            $stat{STAT_BATTERY_STATE} = $state{$in{Sb}};
        }
        if ($in{Cb})
        {
            $stat{STAT_BATTERY_CAPACITY} = $in{Cb};
        }
    }else{
        $log->error("Cannot parse:$str from $phone");
    }
    update_status($phone,\%stat);
}

#--------------------------------------------------------------
sub TGW_respond {
#T=TGW,M=test1
    my ($phone,$str)=@_;
    my $msg;
    $msg=$1 if $str=~/T=TGW,M=(\w+)/;
    $log->info("test is detected $phone:$str");
    my $file=time;
    if(open(SMS,">$ENV{APL_VAR}/sms/out/$file.101")) {
      print SMS "OBJ=101\nRESPOND=$msg\nTELEPHONE_NUMBER=$phone\n";
      close SMS;
      $log->info("respond is sent to $phone");
    }
}

# decode sms message
#  <<<17039735795,ASCII,124,543d4753552c533d322c4f55543a285052323d302c504456523d302c504d573d302c464355543d302c505241443d302c5052313d30292c494e3a2856623d31322e32342c54733d33372e37322c4d57533d302c544d503d302c5452503d302c44533d302c4c434b3d302c53313d312c48533d302c49474e3d30290d0a>>>

sub sms_decode {
  my $msg=shift;
  my ($phone,$str);
  if($msg=~/<<<(\d+),ASCII,\d+,(\w+)>>>/) {
     ($phone,$str)=($1,$2);
     $str=~s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg;
     $log->info("$phone>$str");
  }
  ($phone,$str);
}

#MAIN ===========================================================

my ($input, $buffer);

if (sysread(STDIN, $input, 512) > 0) {
    my ($phone,$str)=sms_decode($input);
    if($str=~/T=GLU/) { GLU_position($phone,$str) }# === POSITION
    if($str=~/T=GSU/) { GSU_status($phone,$str);  }# === STATUS
    if($str=~/T=TGW/) { TGW_respond($phone,$str); }# === RESPOND TO THE GATAWAY TEST
}
