#!/bin/bash

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

###########################################################
## utility to call filecase with confirmation using zenity
## options:
##  -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.1 built 20240121";
};
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 fix char case of filenames.";
 echo " Zenity based dialog uses to choose files to be fixed.";
 echo " $scriptname change filenames to lowercase or uppercase.";
 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 " -l,--list f - use file f with list of files to fix";
 echo "parameters:";
 echo " file(s) to fix filename char case";
 echo " if '-' or no parameters then uses stdin/stdout";
 echo "examples:";
 echo " $scriptname -h";
 echo " $scriptname *.txt";
 echo " $scriptname -w 60 test.txt";
};

declare tmpfile="";
declare optlist="-s -d -l";

function free_tmpfile(){
 if [ -n "$tmpfile" ]; then
  rm -f "$tmpfile";
  tmpfile="";
 fi;
};

function cleanup() {
 rv=$?;
 free_tmpfile;
 exit $rv;
}

function tmplog(){
 if [ -n "$tmpfile" ] && [ -n "$1" ]; then
  echo "$1" >> "$tmpfile";
 fi;
};

function init_tmpfile(){
 if [ -z "$tmpfile" ]; then
  tmpfile="$(mktemp)";
  trap "cleanup" EXIT;
 fi;
};

function nsumm(){
 cat "$tmpfile" | wc -l;
};

function npass(){
 cat "$tmpfile" | grep -e ' passed ' -e ' rename ' | wc -l;
};

function nfail(){
 cat "$tmpfile" | grep -e ' missed ' -e ' failed ' | wc -l;
};

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" = "filecase:" ]; then
   case $w2 in
    passed|rename) echo "$line";      tmplog "$line"; ;;
    missed|failed) echo "$line" 1>&2; tmplog "$line"; ;;
    *)             ;;
   esac;
  fi;
 done;
};

function check_filecase(){
 if [ -z "$(unix which filecase)" ]; then
  1>&2 echo "$scriptname: filecase not found";
  exit 1;
 fi;
};

function zenselection(){
 local list="";
 if [ -z "$*" ]; then return; fi;
 for item in $*; do
  local check="true";
  list="$list $check $item";
 done;
 if [ -z "$list" ]; then return; fi;
 zenity --title "$scriptname: $(langstr en "select files to fix filecase" ru "выбрать файлы для исправления регистра имен") …" \
        --list --modal --timeout 180 --width 800 --height 600 \
        --text "<big><b>$(langstr en "Check files to fix filecase" ru "Отметьте файлы для обработки"):</b></big>" \
        --checklist --column "$(langstr en Check ru Выбор)" \
        --column "$(langstr en "Files to fix filename (upper|lower) case" ru "Файлы для изменения регистра имен")" \
        --separator " " --print-column 2 $list 2>/dev/null;
};

function zenoptions(){
 local list="";
 list="$list true  [-s] $(langstr en Process_SubDirectories. ru Обрабатывать_ПодКаталоги.)";
 list="$list true  [-d] $(langstr en Rename_Directories_too. ru Переименовать_Каталоги_тоже.)";
 list="$list false [-h] $(langstr en Process_Hidden_Files.   ru Обрабатывать_Скрытые_Файлы_тоже.)";
 list="$list true  [-l] $(langstr en Convert_to_LowerCase.   ru Преобразовывать_в_нижний_регистр.)";
 list="$list false [-u] $(langstr en Convert_to_UpperCase.   ru Преобразовывать_в_ВЕРХНИЙ_РЕГИСТР.)";
 zenity --title "$scriptname: $(langstr en "select options to fix filecase" ru "выбор опций переименования") …" \
        --list --modal --timeout 180 --width 470 --height 240 \
        --text "<big><b>$(langstr en "Check options to fix filecase" ru "Выбор опций обработки регистра"):</b></big>" \
        --checklist --column "$(langstr en Check ru Выбор)" \
        --column "$(langstr en Option ru Опция)" \
        --column "$(langstr en "Option description" ru "Описание опции")" \
        --separator " " --print-column 2 $list 2>/dev/null | tr '\[' ' ' | tr '\]' ' ';
};

function run_filecase_work(){
 unix filecase $optlist "$@" 2>&1 | split;
 #notify-send -t 30000 "unix filecase --charset $fixutf8_charset $*";
};

 # 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 "unix sudoit chmod 777 $dir";
   unix sudoit 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_filespec_message(){
 echo "$scriptname: no file(s) specified to process." 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 filecasezen(){
 welcome_doublecmd "$@";
 check_filecase;
 local wait=0;
 local list="";
 local files="";
 while is_option $1; do
  case $1 in
   -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;
 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")";
 if [ -z "$files" ]; then
  echo "$scriptname: no agruments. use $scriptname -h for help." 1>&2;
  if [ "$wait" = "0" ]; then return; fi;
 fi;
 if [ -n "$files" ]; then
  colorize_head echo "$(langstr ru "Исправить (верхний|нижний) регистр файлов" en "Fix the filename(s) char (upper|lower)case"):";
  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;
  optlist="$(zenoptions)";
  if [ -z "$optlist" ]; then return; fi;
  colorize_bold run_filecase_work $files;
  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 "##############################################";
  colorize_bold no_filespec_message;
  colorize_head echo "##############################################";
 fi;
 # wait press enter or timeout
 if [ "$wait" = "0" ]; then return; fi;
 wait_any_key $wait; echo "$scriptname: done.";
};

function main(){
 init_tmpfile;
 filecasezen "$@";
 free_tmpfile;
};

main "$@";

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