#!/usr/bin/perl

# Copyright (c) 2025 Jory A. Pratt, W5GLE
#
# This script is designed to tune the dvswitch.sh application by extracting
# the port number from the /etc/asterisk/rpt.conf file based on the provided
# node number, constructing the ABINFO environment variable, and then
# executing dvswitch.sh with the provided talkgroup.
#
# This script must be run as astrisk if using a dialplan, if not using a dialplan
# you can run this script as root.
#
# The script logs all operations to /var/log/tgtune_dvswitch.log.

use strict;
use warnings;
use File::Basename;
use Time::Piece;

# Configuration with overrides
my $rpt_dir = $ENV{RPT_DIR} || "/etc/asterisk";
my $rpt_file = "$rpt_dir/rpt.conf";
my $dvswitch_path = $ENV{DVSWITCH_PATH} || "/opt/MMDVM_Bridge/dvswitch.sh";
my $abinfo_template = "/tmp/ABInfo_%s.json";
my $log_file = $ENV{LOG_FILE} || "/var/log/tgtune_dvswitch.log";
my $log_level = $ENV{LOG_LEVEL} || "INFO"; # Default to INFO

# Logging levels
my %levels = (DEBUG => 1, INFO => 2, WARNING => 3, ERROR => 4);

# Function to write to the log file (with logging levels)
sub log_message {
    my ($level, $message) = @_;
    return if $levels{$level} < $levels{$log_level}; # Skip if level is too low.

    my $now = localtime->strftime("%Y-%m-%d %H:%M:%S");
    open my $fh, ">>", $log_file or return;
    print $fh "$now [$level]: $message\n";
    close $fh;
}

# Function to extract the port number
sub extract_port {
    my ($nodenumber) = @_;

    if ($nodenumber !~ /^\d+$/) {
        log_message("ERROR", "Error: nodenumber must be numeric.");
        print "Error: nodenumber must be numeric.\n";
        return undef;
    }

    open my $fh, "<", $rpt_file or do {
        log_message("ERROR", "Cannot open $rpt_file: $!");
        print "Cannot open $rpt_file: $!\n";
        return undef;
    };

    my $port;
    my $in_stanza = 0;

    while (my $line = <$fh>) {
        chomp $line;
        if ($line =~ /^\[$nodenumber\]/) {
            $in_stanza = 1;
        }
        if ($in_stanza && $line =~ /^rxchannel\s*=\s*USRP\/127\.0\.0\.1:(\d+):/) {
            $port = $1;
            last;
        }
    }
    close $fh;

    if (not defined $port) {
        log_message("ERROR", "Error: port not found in rpt.conf for nodenumber: $nodenumber.");
        print "Error: port not found in rpt.conf for nodenumber: $nodenumber.\n";
        return undef;
    }

    return $port;
}

# Function to execute dvswitch.sh
sub execute_dvswitch {
    my ($talkgroup) = @_;

    if ($talkgroup !~ /^\d+$/) {
        log_message("ERROR", "Error: talkgroup must be numeric.");
        print "Error: talkgroup must be numeric.\n";
        return 0;
    }

    my $command = "$dvswitch_path tune $talkgroup";
    log_message("INFO", "Executing command: $command");
    my $result = system($command);

    if ($result != 0) {
        log_message("ERROR", "Error executing dvswitch.sh");
        print "Error executing dvswitch.sh\n";
        return 0;
    }
    return 1;
}

# Main script
if (@ARGV != 2) {
    log_message("ERROR", "Usage: " . basename($0) . " <nodenumber> <talkgroup>");
    print "Usage: " . basename($0) . " <nodenumber> <talkgroup>\n";
    exit 1;
}

my ($nodenumber, $talkgroup) = @ARGV;

my $port = extract_port($nodenumber);
if (not defined $port) {
    exit 1;
}

my $abinfo = sprintf($abinfo_template, $port);
$ENV{ABINFO} = $abinfo;

if (not execute_dvswitch($talkgroup)) {
    delete $ENV{ABINFO};
    exit 1;
}

delete $ENV{ABINFO};

log_message("INFO", "Script executed successfully.");
exit 0;
