#!/bin/bash

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

###########################################################
## utility to call fixeol .. 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-2023 Alexey Kuryakin daqgroup@mail.ru";
};
function print_help(){
 print_version;
 print_copyright;
 echo "about:";
 echo " $scriptname is utility to fix (validate) text file(s) EOL.";
 echo " EOL is End Of Line marker use to separate text lines.";
 echo " Usually it's: CRLF on Windows, LF on Unix, CR on MAC.";
 echo " Zenity based dialog uses to choose files to be fixed.";
 echo " $scriptname converts any text EOL to current system's EOL.";
 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, no file conversion";
 echo " -l,--list f - use file f with list of files to fix";
 echo "parameters:";
 echo " text file(s) to fix EOL";
 echo " if '-' or no parameters";
 echo " then uses stdin/stdout";
 echo "examples:";
 echo " $scriptname -h";
 echo " $scriptname *.txt";
 echo " $scriptname -t -w 60 test.txt";
};

function split(){
 local line="";
 while read -r line || [[ -n "$line" ]]; do
  local w1="$(echo "$line" | cut -d ' ' -f 1)";
  local w2="$(echo "$line" | cut -d ' ' -f 2)";
  if [ "$w1" = "fixeol:" ]; then
   case $w2 in
    passed|fixed)         echo "$line"; ;;
    missed|failed|faulty) echo "$line" 1>&2; ;;
    *)                    ;;
   esac;
  fi;
 done;
};

function zen_choose_action(){
 zenity --title "$scriptname: $(langstr ru "Проверить/Исправить EOL" en "Check or Fix EOL") …" \
        --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 "Проверить макеры конца строки (EOL)" en "Verify (test)  end of line markers (EOL)")" \
        "FALSE" "fix"  "$(langstr ru "Исправить макеры конца строки (EOL)" en "Fix (validate) end of line markers (EOL)")" \
        2>/dev/null;
};

function zenselection(){
 local list="";
 if [ -z "$*" ]; then return; fi;
 for item in $(unix fixeol -t "$@" 2>&1 | grep 'fixeol: faulty' | cut -d ' ' -f 4); do
  list="$list true $item";
 done;
 if [ -z "$list" ]; then return; fi;
 zenity --title "$scriptname: $(langstr ru "выбор файлов для исправления" en "select files to fix") EOL …" \
        --list --modal --timeout 120 --width 800 --height 600 \
        --text "<big><b>$(langstr ru "Выбирайте файлы для исправления" en "Check files to fix") EOL:</b></big>" \
        --checklist --column "$(langstr ru Выбор en Check)" --column "$(langstr ru "Файлы для исправления" en "Files to fix") EOL" \
        --separator " " $list 2>/dev/null;
};

function run_fixeol_work(){
 unix fixeol "$@" 2>&1 | split;
};

function run_fixeol_test(){
 unix fixeol -t "$@" 2>&1 | split;
};

function list_only_text_files(){
 if [ -n "$*" ]; then
  file $* | grep -i -e ' text' | cut -d ':' -f 1 2>/dev/null;
 fi;
};

 # 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(){
 echo "$scriptname received $(echo $items | wc -w) file(s) to check/fix EOL." 1>&2;
 echo "But was NOT found any TEXT file(s) to process." 1>&2;
 echo "All files are binary,directory,link,device etc" 1>&2;
};

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 "$@";
 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;
 if [ "$test" = "0" ]; then
  local act="$(zen_choose_action)";
  case $act in
   test) test=1; ;;
   fix)  test=0; ;;
   *) cancel 0 "$scriptname: $(langstr ru Отмена en Cancel)."; ;;
  esac;
 fi;
 files="$*";
 if [ -n "$list" ] && [ -e "$list" ]; then
  validate_dc_temp_dir $(dirname $list);
  files="$files $(cat $list)";
 fi;
 # trim list of files
 files="$(echo "$files")";
 items="$(echo "$files")";
 if [ -z "$files" ]; then
  echo "$scriptname: no agruments. use $scriptname -h for help." 1>&2;
  if [ "$wait" = "0" ]; then return; fi;
 fi;
 # skip all non-text files
 files="$(list_only_text_files $files)";
 if [ -n "$files" ]; then
  if [ $test = 1 ]; then
   colorize_head echo "$(langstr ru "Проверка маркеров конца строки (EOL):" en "Check text file(s) EOL (end of line) validity:")";
   colorize_head echo "##############################################";
   colorize_bold run_fixeol_test $files;
   local npass="$(run_fixeol_test $files 2>/dev/null | wc -l)";
   local nsumm="$(run_fixeol_test $files 2>&1        | wc -l)";
   local nfail=0; let nfail=$nsumm-$npass;
   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 "Проверка маркеров конца строки (EOL):" en "Check text file(s) EOL (end of line) validity:")";
   colorize_head echo "##############################################";
   colorize_bold run_fixeol_test $files;
   colorize_head echo "$(langstr ru "Правка маркеров конца строки (EOL):" en "Fix (validate) text file(s) EOL (end of line):")";
   colorize_head echo "##############################################";
   files="$(zenselection $files)";
   if [ -z "$files" ]; then
    colorize_bold echo_to_stderr -ne "\n\n$(langstr ru "Нет файлов для обработки." en "No files to process.")\n\n";
    wait_any_key $wait; echo "$scriptname: done.";
    return;
   fi;
   colorize_bold run_fixeol_work $files;
   local npass="$(run_fixeol_test $files 2>/dev/null | wc -l)";
   local nsumm="$(run_fixeol_test $files 2>&1        | wc -l)";
   local nfail=0; let nfail=$nsumm-$npass;
   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
##############
