#!/bin/bash

daqgroup_toolbox() {
  about(){
    local self="$1";
    echo " ";
    echo " DaqGroup toolbox - set of usefull utilities for AstraLinux";
    echo " Copyright (c) 2017-2023 Alexey Kuryakin kouriakine@mail.ru";
    echo " Revision: 20230216";
    echo " ";
    echo "$self usage:";
    echo " ";
    echo "- vnc (remote desktop server) tools:";
    echo "  $self vnc stop                        - VNC server stop";
    echo "  $self vnc start                       - VNC server start";
    echo "  $self vnc status                      - VNC server status view";
    echo "  $self vnc restart                     - VNC server stop & start";
    echo "  $self vnc install                     - VNC server installation";
    echo "  $self vnc preferences                 - VNC server preferences GUI";
    echo " ";
    echo "- ser2net (serial to network proxy server) tools:";
    echo "  $self ser2net stop                    - ser2net server stop";
    echo "  $self ser2net start                   - ser2net server start";
    echo "  $self ser2net status                  - ser2net server status view";
    echo "  $self ser2net restart                 - ser2net server stop & start";
    echo "  $self ser2net install                 - ser2net server installation";
    echo "  $self ser2net register                - ser2net server register as system service";
    echo "  $self ser2net showconf                - ser2net server show config file";
    echo "  $self ser2net editconf                - ser2net server edit config file";
    echo "  $self ser2net reloadconf              - ser2net server reload config file";
    echo " ";
    echo "- vbox (VirtualBox virtual machine) tools:";
    echo "  $self vbox list vms                   - VirtualBox list virtual machines";
    echo "  $self vbox list runningvms            - VirtualBox list running virtual machines";
    echo "  $self vbox startvm vm arg             - VirtualBox start virtual machine «vm» with options «arg»";
    echo "  $self vbox startvm vm --fullscreen    - VirtualBox start virtual machine «vm» in fullscreen mode (example)";
    echo "  $self vbox sleep-n-startvm n vm arg   - VirtualBox sleep «n» sec & start virtual machine «vm» with options «arg»";
    echo "  $self vbox vboxnet0 create            - create VirtualBox hostonlyif vboxnet0 network adapter";
    echo "  $self vbox vboxnet0 remove            - remove VirtualBox hostonlyif vboxnet0 network adapter";
    echo "  $self vbox vboxnet0 status            - status of VirtualBox hostonlyif vboxnet0 network adapter";
    echo "  $self vbox vboxnet0 server status     - vboxnet0 command server on port 26101 - status";
    echo "  $self vbox vboxnet0 server start      - vboxnet0 command server on port 26101 - start";
    echo "  $self vbox vboxnet0 server stop       - vboxnet0 command server on port 26101 - stop";
    echo "  $self vbox vboxnet0 server status p   - vboxnet0 command server on port «p» - status";
    echo "  $self vbox vboxnet0 server start p    - vboxnet0 command server on port «p» - start";
    echo "  $self vbox vboxnet0 server stop p     - vboxnet0 command server on port «p» - stop";
    echo "  $self vbox wait-vms                   - VirtualBox wait while virtual machines running";
    echo "  $self vbox wait-vms 10 system halt    - VirtualBox wait while vms running, sleep 10 sec then system halt";
    echo "  $self vbox wait-vms 20 system logout  - VirtualBox wait while vms running, sleep 20 sec then system logout";
    echo "  $self vbox wait-vms 30 system reboot  - VirtualBox wait while vms running, sleep 30 sec then system reboot";
    echo " ";
    echo "- simulator (terminal to check vboxnet0) tools:";
    echo "  $self simulator start                 - terminal simulator start";
    echo "  $self simulator stop                  - terminal simulator stop";
    echo " ";
    echo "- watch (statistics view in real time) tools:";
    echo "  $self watch netstat tcp               - watch opened tcp ports";
    echo "  $self watch netstat udp               - watch opened udp ports";
    echo "  $self watch netstat all               - watch all opened ports";
    echo "  $self watch netstat                   - watch all opened ports";
    echo " ";
    echo "- miscellaneous system tools:";
    echo "  $self system info                     - short information on operation system";
    echo "  $self system info cpu                 - short information on CPU properties";
    echo "  $self system info usb                 - short information on USB devices";
    echo "  $self system info pci                 - short information on PCI devices";
    echo "  $self system info blk                 - short information on BLK devices (disks)";
    echo "  $self system forcefsck                - force check HDD disks on next system boot";
    echo "  $self system tcp_low_latency          - TCP low latency parameter check";
    echo "  $self system tcp_low_latency 0        - TCP low latency parameter assign 0";
    echo "  $self system tcp_low_latency 1        - TCP low latency parameter assign 1";
    echo "  $self system autologin-user           - check which user is autologin to system";
    echo "  $self system autologin-user \$USER     - autologin to system as current user";
    echo "  $self system autologin-user daq       - autologin to system as user «daq»";
    echo "  $self system logout                   - correct system logout user session with logout dialog"; 
    echo "  $self system logout 10                - correct system logout user session with logout dialog after 10 sec delay"; 
    echo "  $self system logout logout            - correct system logout user session without logout dialog"; 
    echo "  $self system logout logout 10         - correct system logout user session without logout dialog after 10 sec delay"; 
    echo "  $self system logout halt              - correct system logout & halt";
    echo "  $self system logout halt 20           - correct system logout & halt after 20 sec delay";
    echo "  $self system logout reboot            - correct system logout & reboot";
    echo "  $self system logout reboot 30         - correct system logout & reboot after 30 sec delay";
    echo " ";
    echo "- miscellaneous service tools:";
    echo "  $self nicewaiting d w t THIS          - nice delay prompt «Wait: THIS after d sec...»; d:delay, w:width, t:ticks";
    echo "  $self setup                           - copy $self to home folder «\$HOME/scripts/» for short access";
    echo "  $self setup target                    - copy $self to some folder «target» for future use";
    echo " ";
  };
  local defcolor="\e[0m";
  local redcolor="\e[1;37;41m";
  local selffile="${BASH_SOURCE[0]}";
  local selfname="$(basename $selffile)";
  local wavinfo="/usr/share/sounds/freedesktop/stereo/dialog-information.oga";
  local waverror="/usr/share/sounds/freedesktop/stereo/dialog-error.oga";
  local wavlogin="/usr/share/sounds/freedesktop/stereo/service-login.oga";
  local wavlogout="/usr/share/sounds/freedesktop/stereo/service-logout.oga";
  skip() {
    true;
  }; 
  execnohup() {
    [ -z "$(which $1)" ] && { echo "Not found: $1"; return 1; };
    "$@" </dev/null &>/dev/null & disown;
  };
  execute() {
    echo "$*";
    "$@";
  };
  soundplay() {
    [ -z "$1" ] && return 1;
    [ -e "$1" ] && { play -q $1 </dev/null &>/dev/null; };
  };
  isnumber() {
    [ -z "$1" ] && return 1;
    local test; let "test=$1+0";
    [ "$test" == "$1" ] && return 0;
    return 1;
  };
  clearline() {
    isnumber "$1" || return 1; local width="$1";
    printf "\r"; for j in $(seq $width); do printf " "; done; printf "\r";
  };
  nicewaiting() {
    isnumber "$1" || return 1;
    isnumber "$2" || return 1;
    isnumber "$3" || return 1;
    local trapint="$(trap -p SIGINT)";
    local trapterm="$(trap -p SIGTERM)";
    trap -- 'echo -e \\nSIGINT signal received: Interrupted.; exit 130;' SIGINT;
    trap -- 'echo -e \\nSIGTERM signal received: Terminated.; exit 143;' SIGTERM;
    local delay="$1"; local width="$2"; local ticks="$3"; local this="$4"; local tick;
    for i in $(seq $delay); do
      clearline $width;
      let "delay-=1"; printf "Wait: $redcolor $this $defcolor after $redcolor %3d $defcolor sec" "$delay"; sleep 1;
      [ "$ticks" == "0" ] || { let "tick=delay % ticks"; [ "$tick" == "0" ] && soundplay $wavinfo; };
    done;
    clearline $width;
    trap -- SIGTERM; [ -n "$trapterm" ] && $trapterm;
    trap -- SIGINT; [ -n "$trapint" ] && $trapint;
    return 0;
  };
  start_system_shutdown() {
    [ -z "$1" ] && return 1;
    clear; printf "\n\n\n"; printf "Wait: $redcolor System shutdown ($1) in progress... $defcolor "; sleep 1;
    [ "$1" == "logout" ] && { fly-wmfunc FLYWM_LOGOUT   && sleep 0xffffffff; };
    [ "$1" == "reboot" ] && { fly-wmfunc FLYWM_REBOOT   && sleep 0xffffffff; };
    [ "$1" == "halt"   ] && { fly-wmfunc FLYWM_SHUTDOWN && sleep 0xffffffff; };
  };
  [ "$1" == "vnc" ] && {
    local vnc_server="/usr/lib/vino/vino-server";
    [ -e "$vnc_server" ] || {
     echo "VNC server is not installed yet.";
     echo "Use command: $(basename ${BASH_SOURCE[0]}) vnc install";
     return 1;
    };
    [ "$2" == "stop" ] && {
      pkill -ef $vnc_server;
      return;
    };
    [ "$2" == "start" ] && {
      execnohup $vnc_server;
      pgrep -lf $vnc_server;
      return;
    };
    [ "$2" == "status"   ] && {
      netstat -laptn 2>/dev/null | grep $(basename $vnc_server);
      ps --no-header -o pid,user,command -C $(basename $vnc_server);
      skip pgrep -lf $vnc_server;
      return;
    };
    [ "$2" == "restart" ] && {
      pkill -ef $vnc_server; sleep 1;
      execnohup $vnc_server;
      pgrep -lf $vnc_server;
      return;
    };
    [ "$2" == "preferences" ] && {
      execnohup vino-preferences;
      echo "VNC server preferences:";
      gsettings list-recursively org.gnome.Vino;
      return;
    };
    [ "$2" == "install"  ] && {
      sudo apt-get install vino;
      return;
    };
  };
  [ "$1" == "ser2net" ] && {
    [ "$2" == "stop" ] && {
      sudo /etc/init.d/ser2net stop;
      return;
    };
    [ "$2" == "start" ] && {
      sudo /etc/init.d/ser2net start;
      return;
    };
    [ "$2" == "status"   ] && {
      echo "service ser2net status     : $(service ser2net status)";
      echo "/etc/init.d/ser2net status : $(/etc/init.d/ser2net status)";
      ps --no-header -o pid,user,command -C ser2net;
      return;
    };
    [ "$2" == "restart" ] && {
      sudo /etc/init.d/ser2net restart;
      return;
    };
    [ "$2" == "full-restart" ] && {
      sudo service ser2net --full-restart;
      return;
    };
    [ "$2" == "install"  ] && {
      sudo apt-get install ser2net;
      return;
    };
    [ "$2" == "register" ] && {
      sudo systemctl enable ser2net;
      return;
    };
    [ "$2" == "showconf" ] && {
      cat /etc/ser2net.conf;
      return;
    };
    [ "$2" == "editconf" ] && {
      sudo medit /etc/ser2net.conf;
      return;
    };
    [ "$2" == "reloadconf" ] && {
      sudo pkill --signal SIGHUP ser2net;
      return;
    };
  };
  [ "$1" == "vbox" ] && {
    [ "$2" == "vboxnet0" ] && {
      [ "$3" == "create" ] && {
        if [ -z "$(VBoxManage list hostonlyifs | grep vboxnet0)" ]; then VBoxManage hostonlyif create; fi;
        if [ -n "$(VBoxManage list hostonlyifs | grep vboxnet0)" ]; then 
          VBoxManage hostonlyif ipconfig         vboxnet0 --ip 192.168.56.1   --netmask 255.255.255.0;
          if [ -z "$(VBoxManage list dhcpservers | grep vboxnet0)" ]; then
            VBoxManage dhcpserver add    --ifname vboxnet0 --ip 192.168.56.100 --netmask 255.255.255.0 --lowerip 192.168.56.101 --upperip 192.168.56.254 --enable;
          fi;
          if [ -n "$(VBoxManage list dhcpservers | grep vboxnet0)" ]; then
            VBoxManage dhcpserver modify --ifname vboxnet0 --ip 192.168.56.100 --netmask 255.255.255.0 --lowerip 192.168.56.101 --upperip 192.168.56.254 --enable;
          fi;
        fi;
        VBoxManage list hostonlyifs;
        VBoxManage list dhcpservers;
        return;
      };
      [ "$3" == "remove" ] && {
        if [ -n "$(VBoxManage list dhcpservers | grep vboxnet0)" ]; then VBoxManage dhcpserver remove --ifname vboxnet0; fi;
        if [ -n "$(VBoxManage list hostonlyifs | grep vboxnet0)" ]; then VBoxManage hostonlyif remove vboxnet0; fi;
        return;
      };
      [ "$3" == "status" ] && {
        VBoxManage list hostonlyifs;
        VBoxManage list dhcpservers;
        sudo ifconfig vboxnet0;
        return;
      };
      [ "$3" == "server" ] && {
        local port="26101";
        [ "$4" == "start" ] && {
          isnumber "$5" && port="$5";
          /bin/bash -c "while netcat -kl $port -e /bin/bash; do sleep 0; done;";
          return;
        };
        [ "$4" == "stop" ] && {
          isnumber "$5" && port="$5";
          pkill --signal SIGINT  -xfe "/bin/bash -c while netcat -kl $port -e /bin/bash; do sleep 0; done;";
          pkill --signal SIGINT  -xfe "netcat -kl $port -e /bin/bash";
          sleep 1;
          pkill --signal SIGTERM -xfe "/bin/bash -c while netcat -kl $port -e /bin/bash; do sleep 0; done;";
          pkill --signal SIGTERM -xfe "netcat -kl $port -e /bin/bash";
          sleep 1;
          pkill --signal SIGKILL -xfe "/bin/bash -c while netcat -kl $port -e /bin/bash; do sleep 0; done;";
          pkill --signal SIGKILL -xfe "netcat -kl $port -e /bin/bash";
          return;
        };
        [ "$4" == "status" ] && {
          isnumber "$5" && port="$5";
          local pids="$(pgrep -xf "netcat -kl $port -e /bin/bash"; pgrep -xf "/bin/bash -c while netcat -kl $port -e /bin/bash; do sleep 0; done;";)";
          [ -n "$pids" ] && ps --no-header -o pid,user,command -p $pids;
          return;
        };
      };
    };
    [ "$2" == "list" ] && {
      VBoxManage list $3;
      return;
    };
    [ "$2" == "startvm" ] && {
      local vm="$3"; shift 3;
      execnohup $(which VirtualBoxVM) --startvm $vm $*;
      return;
    };
    [ "$2" == "sleep-n-startvm" ] && {
      isnumber "$3" && {
        local delay="$3";
        local vm="$4"; shift 4;
        let "step=100/$delay";
        { for i in $(seq 0 $step 100); do echo $i; sleep 1; done; } | zenity --title "STARTING VIRTUAL MACHINE «$vm»…" --progress --time-remaining --text "<big><big>Going to Start Virtual Machine «$vm»</big></big>…\n\nPress Cancel to terminate or wait to Continue.\n" --auto-close && VirtualBoxVM --startvm $vm $* & disown;
        return;
      };
    };
    [ "$2" == "wait-vms" ] && {
      while [ -n "$(VBoxManage list runningvms)" ]; do clear; printf "$(date) - $redcolor Waiting for running vms: $defcolor \n"; VBoxManage list runningvms; sleep 1; done;
      printf "VirtualBox machines now stopped.\n\n";
      isnumber "$3" && {
        [ "$4" == "system" ] && {
          [ "$5" == "halt" ] && {
            nicewaiting $3 60 1 "SYSTEM HALT"; soundplay $wavlogout;
            start_system_shutdown halt;
            return;
          };
          [ "$5" == "logout" ] && {
            nicewaiting $3 60 1 "SYSTEM LOGOUT"; soundplay $wavlogout;
            start_system_shutdown logout;
            return;
          };
          [ "$5" == "reboot" ] && {
            nicewaiting $3 60 1 "SYSTEM REBOOT"; soundplay $wavlogout;
            start_system_shutdown reboot;
            return;
          };
        };
      };
      return;
    };
  };
  [ "$1" == "watch" ] && {
    [ "$2" == "netstat" ] && {
      [ "$3" == "tcp" ] && {
        sudo watch netstat -apt;
        return;
      };
      [ "$3" == "udp" ] && {
        sudo watch netstat -apu;
        return;
      };
      [ "$3" == "all" ] && {
        sudo watch netstat -aptu;
        return;
      };
      sudo watch netstat -ap;
      return;
    };
  };
  [ "$1" == "simulator" ] && {
    [ "$2" == "start" ] && {
      for i in $(seq 26001 26012; seq 26101 26101); do xterm -geometry 80x20+0+0 -e "$(which netcat) -kl $i" & disown; done;
      return;
    };
    [ "$2" == "stop" ] && {
      for i in $(seq 26001 26012; seq 26101 26101); do pkill -xfe "$(which netcat) -kl $i"; done;
      return;
    };
    [ "$2" == "status" ] && {
      [ -n "$(pgrep netcat)" ] && ps --no-header -o pid,command $(pgrep netcat);
      return;
    };
  };
  [ "$1" == "system" ] && {
    [ "$2" == "info" ] && {
      [ "$3" == "cpu" ] && {
        lscpu $4 $5 $6 $7 $8 $9;
        return;
      };
      [ "$3" == "usb" ] && {
        sudo lsusb $4 $5 $6 $7 $8 $9;
        return;
      };
      [ "$3" == "pci" ] && {
        sudo lspci $4 $5 $6 $7 $8 $9;
        return;
      };
      [ "$3" == "blk" ] && {
        lsblk $4 $5 $6 $7 $8 $9;
        return;
      };
      echo "$(lsb_release -ds) system on $(uname -m) platform, $(uname -r) kernel.";
      return;
    };
    [ "$2" == "forcefsck" ] && {
      sudo touch /forcefsck;
      return;
    };
    [ "$2" == "tcp_low_latency" ] && {
      local tcp_low_latency="/proc/sys/net/ipv4/tcp_low_latency";
      [ "$3" == "0" ] && {
        echo "$3" | sudo tee $tcp_low_latency;
        return;
      };
      [ "$3" == "1" ] && {
        echo "$3" | sudo tee $tcp_low_latency;
        return;
      };
      echo "$tcp_low_latency = $(cat $tcp_low_latency)";
      return;
    };
    [ "$2" == "autologin-user" ] && {
      sudo fly-admin-dm;
    };
    [ "$2" == "logout" ] && {
      [ "$3" == "halt" ] && {
        isnumber "$4" && { nicewaiting $4 60 1 "SYSTEM HALT"; soundplay $wavlogout; };
        start_system_shutdown halt;
        return;
      };
      [ "$3" == "reboot" ] && {
        isnumber "$4" && { nicewaiting $4 60 1 "SYSTEM REBOOT"; soundplay $wavlogout; };
        start_system_shutdown reboot;
        return;
      };
      [ "$3" == "logout" ] && {
        isnumber "$4" && { nicewaiting $4 60 1 "SYSTEM LOGOUT"; soundplay $wavlogout; };
        start_system_shutdown logout;
        return;
      };
      isnumber "$3" && { nicewaiting $3 60 1 "SYSTEM LOGOUT"; soundplay $wavlogout; };
      start_system_shutdown logout;
      return;
    };
  };
  [ "$1" == "nicewaiting" ] && {
    isnumber "$2" && isnumber "$3" && isnumber "$4" [ -n "$5" ] && {
      local delay="$2"; local width="$3"; local ticks="$4"; shift 4;
      nicewaiting $delay $width $ticks "$*";
      return;
    };
  };
  [ "$1" == "setup" ] && {
    local homescriptsdir="$HOME/scripts";
    local rootscriptsdir="/mnt/data/root/scripts";
    local script="$(readlink -e "${BASH_SOURCE[0]}")";
    [ -n "$2" ] && homescriptsdir="$2";
    [ -d "$homescriptsdir" ] || mkdir -pv $homescriptsdir;
    cp -fv "$script" "$homescriptsdir/$(basename $script)";
    chmod -fv 755 "$homescriptsdir/$(basename $script)";
    [ -d "$rootscriptsdir" ] && {
      sudo cp -fv "$script" "$rootscriptsdir/$(basename $script)";
      sudo chmod -fv 755 "$rootscriptsdir/$(basename $script)";
      ln -fvs "$rootscriptsdir/$(basename $script)" "$homescriptsdir/$(basename $script)";
    };
    return;
  };
  about $selfname;
};
daqgroup_toolbox $*;
