#!/bin/sh

#### SOME DEFAULTS ONE MIGHT OVERRIDE //start
YMC_SIMPLE_CALC_DIGITS=5
FLIWI_COMMENT_CHAR='#'
#### SOME DEFAULTS ONE MIGHT OVERRIDE //end


ymc_error_msg()
{
  echo "#########" 1>&2
  echo "# ERROR" 1>&2
  echo "#" 1>&2
  /bin/echo -e "# $*" 1>&2
  echo "#########" 1>&2
}

ymc_warning_msg()
{
  echo "#########" 1>&2
  echo "# WARNING" 1>&2
  echo "#" 1>&2
  /bin/echo -e "# $*" 1>&2
  echo "#########" 1>&2
}

ymc_info_msg()
{
  echo "#########" 1>&2
  echo "# INFO" 1>&2
  echo "#" 1>&2
  /bin/echo -e "# $*" 1>&2
  echo "#########" 1>&2
}

ymc_exit_fatal()
{
  echo "#########" 1>&2
  echo "# FATAL" 1>&2
  echo "#" 1>&2
  /bin/echo -e "# $*" 1>&2
  echo "#########" 1>&2
  exit 1
}

ymc_change_to_last_dir()
{
  cd - 1>/dev/null
}

ymc_var_value()
{
  eval echo \$$(ymc_trim $(ymc_var_wash $1))
}

ymc_set_var_content()
{
  eval $(ymc_trim $(ymc_var_wash $1))="'"$2"'"
}

ymc_trim()
{
  echo "$*" | sed -r 's/^[ ]+//' | sed -r 's/[ ]+$//'
}

ymc_wash()
{
  ### Note: 'a-z' and 'A-Z' is not sufficient (as it might contains special-chars like german umlauts, too)
  echo "$*" | sed -r 's/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9=_ .,:@#/!-]//g'
}

ymc_var_wash()
{
  ### Note: 'a-z' and 'A-Z' is not sufficient (as it might contains special-chars like german umlauts, too)
  echo "$*" | sed -r 's/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9_]//g'
}

ymc_contains()
{
  ymc_contains_org_IFS=$IFS
  IFS=' '
  needle=$1
  items=$*
  first_done=0
  for item in $items
  do
    if [ $first_done -eq 0 ]; then
      first_done=1
      continue
    fi
    if [ "$item" = "$needle" ]; then
      echo 1
      IFS=$ymc_contains_org_IFS
      return 0
    fi
  done
  echo 0
  IFS=$ymc_contains_org_IFS
  return 1
}

ymc_get_link_target()
{
  target_path=$1
  if [ ! -L "$target_path" ]; then
    return 1
  fi

  ymc_trim $(LC_ALL=C ls -alh $target_path | sed -r 's/.*-> //')
  return 0
}

ymc_md5()
{
  echo -n "$1" | md5sum | cut -d ' ' -f 1
}

ymc_simple_calc()
{
  experssion=$*
  result=$(echo "scale=$YMC_SIMPLE_CALC_DIGITS; $experssion" | LC_ALL=C bc 2>/dev/null | sed -r 's/^\./0./' | sed -r 's/([0-9]+\..*)[0]+$/\1/' | sed -r 's/[.]+$//')
  if [ "$result" != '' ]; then
    echo $result
    return 0
  else
    return 1
  fi
}

ymc_dec2hex()
{
  decimal=$1
  ymc_simple_calc "obase=16; $decimal"
}

ymc_hex2dec()
{
  hex=$(ymc_str_to_upper $1)
  ymc_simple_calc "ibase=16; $hex"
}

ymc_ceil()
{
  ymc_simple_calc "$(ymc_floor $1) + 1"
}

ymc_floor()
{
  echo $1 | sed -r 's/\..*//'
}

ymc_str_to_lower()
{
  string=$1
  echo $string | tr '[:upper:]' '[:lower:]'
}

ymc_str_to_upper()
{
  string=$1
  echo $string | tr '[:lower:]' '[:upper:]'
}

fliwi_modify_file_add_block_start()
{
  local function_name="fliwi_modify_file_add_block_start"
  local echo_cmd="/bin/echo"

  local file_to_modify="$1"
  local identification_string="$2"
  local is_under_control_of_fliwi="$3"
  local is_under_control_of_fliwi_message="$FLIWI_COMMENT_CHAR### WARNING: This block is under control of Fliwi.\n$FLIWI_COMMENT_CHAR###          Manual changes in it might get overridden anytime."

  if [ -z "$file_to_modify" ]; then
    ymc_error_msg "No file to modify given while calling function '$function_name()'"
    return 1
  fi

  if [ -z "$identification_string" ]; then
    ymc_error_msg "No identification string given while calling function '$function_name()'"
    return 1
  fi

  if [ ! -f "$file_to_modify" ]; then
    ymc_error_msg "The file '$file_to_modify' does not exists while calling function '$function_name()'"
    return 1
  fi

  if [ ! -w "$file_to_modify" ]; then
    ymc_error_msg "The file '$file_to_modify' is not writable while calling function '$function_name()'"
    return 1
  fi

  if [ "$is_under_control_of_fliwi" = "no" ]; then
    is_under_control_of_fliwi_message=""
  elif [ $(echo "$is_under_control_of_fliwi" | wc -w) -gt 1 ]; then
    is_under_control_of_fliwi_message=$is_under_control_of_fliwi
  fi

  $echo_cmd >> $file_to_modify
  $echo_cmd -E "$FLIWI_COMMENT_CHAR### FLIWI ## Automatically added block # $identification_string //start" >> $file_to_modify

  if [ -n "$is_under_control_of_fliwi_message" ]; then
    $echo_cmd -e "$is_under_control_of_fliwi_message" >> $file_to_modify
  fi

  return 0
}

fliwi_modify_file_add_block_end()
{
  local function_name="fliwi_modify_file_add_block_end"
  local echo_cmd="/bin/echo"

  local file_to_modify="$1"
  local identification_string="$2"

  if [ -z "$file_to_modify" ]; then
    ymc_error_msg "No file to modify given while calling function '$function_name()'"
    return 1
  fi

  if [ -z "$identification_string" ]; then
    ymc_error_msg "No identification string given while calling function '$function_name()'"
    return 1
  fi

  if [ ! -f "$file_to_modify" ]; then
    ymc_error_msg "The file '$file_to_modify' does not exists while calling function '$function_name()'"
    return 1
  fi

  if [ ! -w "$file_to_modify" ]; then
    ymc_error_msg "The file '$file_to_modify' is not writable while calling function '$function_name()'"
    return 1
  fi

  $echo_cmd -E "$FLIWI_COMMENT_CHAR### FLIWI ## Automatically added block # $identification_string //end" >> $file_to_modify
}

fliwi_modify_file_remove_added_block()
{
  local function_name="fliwi_modify_file_remove_added_block"

  local file_to_modify="$1"
  local identification_string="$2"
  local do_not_allow_empty_files="$3"
  local awk_search_line="$FLIWI_COMMENT_CHAR### FLIWI ## Automatically added block # $identification_string"

  if [ -z "$file_to_modify" ]; then
    ymc_error_msg "No file to modify given while calling function '$function_name()'"
    return 1
  fi

  if [ -z "$identification_string" ]; then
    ymc_error_msg "No identification string given while calling function '$function_name()'"
    return 1
  fi

  if [ ! -f "$file_to_modify" ]; then
    ymc_error_msg "The file '$file_to_modify' does not exists while calling function '$function_name()'"
    return 1
  fi

  if [ ! -w "$file_to_modify" ]; then
    ymc_error_msg "The file '$file_to_modify' is not writable while calling function '$function_name()'"
    return 1
  fi

  local temporary_file=$(tempfile -p FLIWI -s "_fliwi_modify_file_remove_added_block.tmp")
  if [ $? -ne 0 ] || \
     [ -z "$temporary_file" ] || \
     [ ! -f "$temporary_file" ] || \
     [ ! -w "$temporary_file" ]; then
    ymc_error_msg "Failed to create a temporary file '$temporary_file' while calling function '$function_name()'"
    return 1
  fi

  tac $file_to_modify | awk -v start_string="$awk_search_line //start" \
                            -v end_string="$awk_search_line //end" \
                            'BEGIN {toBuffer="yes"} {if(toBuffer=="maybe" && $0!=""){toBuffer="yes";}; if($0==end_string){toBuffer="no"};if (toBuffer == "yes"){print $0};if(toBuffer=="maybe" && $0!=""){toBuffer="yes";};if($0==start_string){toBuffer="maybe"}}' > $temporary_file
  if [ $? -ne 0 ]; then
    ymc_error_msg "Failed to process file '$file_to_modify' with awk while calling function '$function_name()'"
    rm -f $temporary_file
    return 0
  fi

  if [ $(cat $temporary_file | wc -c) -eq 0 ]; then
    if [ "$do_not_allow_empty_files" = "NO_EMPTY_FILES" ]; then
      ymc_error_msg "Resulting file '$file_to_modify' would be zero bytes large while calling function '$function_name()'"
      rm -f $temporary_file
      return 0
    else
      ymc_warning_msg "Resulting file '$file_to_modify' will be zero bytes large while calling function '$function_name()'"
    fi
  fi

  tac $temporary_file > $file_to_modify

  ### LEGACY-SUPPORT //start
  for legacy_awk_search_line in "### $identification_string" "###$identification_string"
  do
    tac $file_to_modify | awk -v start_string="$legacy_awk_search_line //start" \
                              -v end_string="$legacy_awk_search_line //end" \
                              'BEGIN {toBuffer="yes"} {if(toBuffer=="maybe" && $0!=""){toBuffer="yes";}; if($0==end_string){toBuffer="no"};if (toBuffer == "yes"){print $0};if(toBuffer=="maybe" && $0!=""){toBuffer="yes";};if($0==start_string){toBuffer="maybe"}}' > $temporary_file
    if [ $? -ne 0 ]; then
      ymc_error_msg "Failed to process file '$file_to_modify' with awk while calling function '$function_name()' (legacy-search '$legacy_awk_search_line')"
      rm -f $temporary_file
      return 0
    fi

    if [ $(cat $temporary_file | wc -c) -eq 0 ]; then
      if [ "$do_not_allow_empty_files" = "NO_EMPTY_FILES" ]; then
        ymc_error_msg "Resulting file '$file_to_modify' would be zero bytes large while calling function '$function_name()' (legacy-search '$legacy_awk_search_line')"
        rm -f $temporary_file
        return 0
      else
        ymc_warning_msg "Resulting file '$file_to_modify' will be zero bytes large while calling function '$function_name()' (legacy-search '$legacy_awk_search_line')"
      fi
    fi
  done
  ### LEGACY-SUPPORT //end

  tac $temporary_file > $file_to_modify

  rm -f $temporary_file

  return 0
}
