#!/bin/bash

###########################################################
## Copyright (c) 2002-2024 Alexey Kuryakin daqgroup@mail.ru
###########################################################

###########################################################
## utility to call checksum  with confirmation using zenity
## options:
##  -t --test    test mode
##  -l --list f  take list of files from file f
###########################################################

###########################################################
source $(crwkit which crwlib_base.sh); # Use base library #
###########################################################

function print_version(){
 echo "$scriptname version 1.0";
};
function print_copyright(){
 echo "Copyright (c) 2002-2024 Alexey Kuryakin daqgroup@mail.ru";
};
function print_help(){
 print_version;
 print_copyright;
 echo "about:";
 echo " $scriptname is utility to calculate/verify checksum.";
 echo " Zenity based dialog uses to choose action to execute.";
 echo "usage:";
 echo " $scriptname [options] [parameters]";
 echo "options:";
 echo " --version   - print version";
 echo " -h,--help   - print help screen";
 echo " -w,--wait n - if nonzero, wait n seconds on exit";
 echo " -t,--test   - run in test mode - verify checksum";
 echo " -l,--list f - use file f with list of files";
 echo "parameters:";
 echo " file of MD5 checksum (checksum.md5)";
 echo "examples:";
 echo " $scriptname";
 echo " $scriptname -h";
 echo " $scriptname -w 180 checksum.md5";
};

declare -i npass=0;
declare -i nfail=0;
declare -i nsumm=0;

function split(){
 local line=""; local err=0;
 while read -r line || [[ -n "$line" ]]; do
  local w1="$(echo $line | cut -d ' ' -f 1)";
  local w5="$(echo $line | cut -d ' ' -f 5)";
  case $w1 in
   Error:|BAD|NOT) let err=1; ;;
   *) ;;
  esac;
  case $w5 in
   FAILURE)        let err=1; ;;
   *) ;;
  esac;
  if [ $err -eq 0 ]; then
   echo "$line";
  else
   1>&2 echo "$line";
  fi;
  let err=0;
 done;
};

function check_checksum(){
 if [ -z "$(unix which checksum)" ]; then
  fatal 1 "$scriptname: checksum not found";
 fi;
};

function zen_choose_action(){
 zenity --title "$scriptname: $(langstr ru "Проверить/Вычислить К.С. MD5" en "Check or Calculate MD5 checksum") …" \
        --list --modal --timeout 180 --width 600 --height 170 \
        --text "<big><b>$(langstr ru "Пожалуйста выбирете Действие для выполнения:" en "Please select Action you want to execute:")</b></big>" \
        --radiolist --column "$(langstr ru Выбор en Choice)" --column "$(langstr ru Действие en Action)"  --column "$(langstr ru Комментарий en Comment)" \
        --separator " " --print-column 2 \
        "TRUE"  "test" "$(langstr ru "Проверить целостность файлов по сумме checksum.md5" en "Verify (test) file(s) integrity by checksum.md5")" \
        "FALSE" "make" "$(langstr ru "Вычислить файл MD5 - сумм в каталоге: checksum.md5" en "Calculate (make) MD5 in directory: checksum.md5")" \
        2>/dev/null | cut -d ' ' -f 1 | tr '[:upper:]' '[:lower:]';
};

function exec_checksum_make(){
 if unix checksum -r -mchecksum "*"; then let npass++; else let nfail++; fi;
 let nsumm++;
};

function run_checksum_make(){
 exec_checksum_make "$@" 2>&1 | split;
};

function exec_checksum_test(){
 for item in $*; do
  case $item in
   *.md5) if unix checksum -c$(basename $item); then let npass++; else let nfail++; fi; ;;
   *) 1>&2 echo "Error: file is not MD5 $item"; let nfail++; ;;
  esac;
  let nsumm++;
 done;
};

function run_checksum_test(){
 exec_checksum_test "$@" 2>&1 | split;
};

function list_only_md5_files(){
 for item in $*; do
  case $item in
   *.md5) echo $item; ;;
   *) ;;
  esac;
 done;
};

 # DoubleCommander (DC) creates temporary file list in /tmp/_dc~~~/,
 # so we need to enable file write access for any users to avoid
 # access deny problems when running several DC instances.
readonly tmp_dc_dir="/tmp/_dc~~~";
function validate_dc_temp_dir(){
 local dir="$1";
 if [ -z "$COMMANDER_PATH" ]; then return; fi;
 if [ "$dir" = "$tmp_dc_dir" ] && [ -d "$dir" ]; then
  local mode="$(oct_file_mode $dir)";
  if [ "$mode" != "777" ]; then
   echo "sudo -n chmod 777 $dir";
   sudo -n chmod 777 $dir;
  fi;
 fi;
};
function fix_tmp_dc(){
 if [ -z "$COMMANDER_PATH" ]; then return; fi;
 if is_iam_root || is_iam_sudo; then
  validate_dc_temp_dir $tmp_dc_dir;
 fi;
 if is_iam_root; then
  validate_dc_temp_dir $tmp_dc_dir;
 fi;
};

function no_text_files_found_message(){
 1>&2 echo "$scriptname has received $(echo $items | wc -w) file(s) to process.";
 1>&2 echo "But was NOT found any MD5 file(s) to process.";
};

function welcome_doublecmd(){
 if [ -z "$COMMANDER_PATH" ]; then return; fi;
 echo "Caller information:";
 echo "scriptfile=$scriptfile";
 echo "scriptFILE=$scriptFILE";
 echo "CmdLine=$0 $*"; echo "PWD=$PWD";
 echo "COMMANDER_PATH=$COMMANDER_PATH";
 fix_tmp_dc; echo "";
};

function main(){
 welcome_doublecmd "$@";
 check_checksum;
 local test=0;
 local wait=0;
 local list="";
 local files="";
 local items="";
 while is_option $1; do 
  case $1 in
   -t|--test) test=1; ;;
   -l|--list) list=$2; shift; fix_tmp_dc; ;;
   -w|--wait) wait=$2; shift; ;;
   -h|--help) print_help; return 0; ;;
   --version) print_version; return 0; ;;
   -*)        fatal 1 "$scriptname: invalid option $1"; ;;
   *)         ;;
  esac;
  shift;
 done;
 local zen="$(zen_choose_action)";
 case $zen in
  test) test=1; ;;
  make) test=0; ;;
  *) echo ""; echo "$scriptname: cancel."; echo ""; exit 0; ;;
 esac;
 files="$*";
 if [ -n "$list" ] && [ -e "$list" ]; then
  validate_dc_temp_dir $(dirname $list);
  files="$files $(cat $list)";
 fi;
 # skip all non-MD5 files
 if [ $test = 1 ]; then
  files="$(list_only_md5_files $files)";
 fi;
 # use default checksum.md5 if empty
 if [ $test = 1 ] && [ -z "$files" ]; then
  files="checksum.md5";
 fi;
 # trim list of files
 files="$(echo "$files")";
 items="$(echo "$files")";
 if [ -n "$files" ]; then
  if [ $test = 1 ]; then
   colorize_head echo "$(langstr ru "Проверка целостности файлов (MD5 сумм):" en "Check the file(s) integrity by MD5 checksum"):";
   colorize_head echo "##############################################";
   colorize_bold run_checksum_test $files;
   exec_checksum_test $files >/dev/null 2>&1;
   colorize_head echo "##############################################";
   echo "$nsumm $(langstr ru "файл(ов) обработал" en "file(s) processed"), $npass $(langstr ru успешно en succeed), $nfail $(langstr ru ошибочно en failed).";
  else
   colorize_head echo "$(langstr ru "Расчет MD5 контрольных сумм файлов" en "Make MD5 checksum for specified file(s)"):";
   colorize_head echo "##############################################";
   colorize_bold run_checksum_make $files;
   exec_checksum_make $files >/dev/null 2>&1;
   colorize_head echo "##############################################";
   echo "$nsumm $(langstr ru "файл(ов) обработал" en "file(s) processed"), $npass $(langstr ru успешно en succeed), $nfail $(langstr ru ошибочно en failed).";
  fi;
 else
  colorize_head echo "##############################################";
  colorize_bold no_text_files_found_message;
  colorize_head echo "##############################################";
 fi;
 # wait press enter or timeout
 if [ "$wait" = "0" ]; then return; fi;
 wait_any_key $wait; echo "$scriptname: done.";
};

main "$@";

##############
## END OF FILE
##############
