#!/bin/bash
###############################################
#                                             #
#       ToriOS OS Places Menu (JWM)           #
# copyright Israel<israeldahl@gmail.com> 2016 #
#               GPL3 License                  #
#                                             #
#               Prov 26:13-16                 #
#        13 The slothful man saith,           #
#        There is a lion in the way;          #
#        a lion is in the streets.            #
#    14 As the door turneth upon his hinges,  #
#      so doth the slothful upon his bed.     #
#    15 The slothful hideth his hand in his   #
#    bosom; it grieveth him to bring it again #
#    to his mouth. 16 The sluggard is wiser   #
#    in his own conceit than seven men that   #
#          can render a reason.               #
#                                             #
#      Prose from KJV Bible public Domain     #
#                                             #
###############################################
[[ -z "$(which jwm)" ]] && exit
## set up safer shellscript
set -o pipefail
# e if a command fails, exit
# u error on unset variables
# C disallow existing regular files to be overwritten by redirection of output
FULLHUGEMENU=""
LIMIT=4
[[ -n "$1" ]] && FULLHUGEMENU="true"
DIR="$HOME/.cache"
[[ -d "$DIR" ]] || mkdir -p "$DIR"
progname="${0/*\/}"
MENUfileCACHE="$DIR/$progname.cache"
LOGDIR="$HOME/.jwm/jsm-logs"
[[ -d "$LOGDIR" ]] || mkdir -p "$LOGDIR"
LOGFILE="$LOGDIR/$progname.log"
[[ -f "$LOGFILE" ]] && rm "$LOGFILE"
date > "$LOGFILE"
## this function will print the info to the screen and save it to a cache file
writeOut(){
  ## $* means ALL arguments sent in
  if [[ -n "$FULLHUGEMENU" ]]
  then
    printf "%s\n" "$*" >> "$MENUfileCACHE"
  else
    printf "%s\n" "$*" 2>>"$LOGFILE"
  fi
}

## I have removed the modification time part of the code because these menus get file permissions, plus they build quickly
getModtime(){
  ## read that file sent in
  thisFile="$1"
  if [[ ! -f "$thisFile" ]]
  then
    printf "%s" "$thisFile is not a file">>"$LOGFILE" 2>>"$LOGFILE"
    touch "$thisFile"
    return
  fi
  while read LINE || [[ -n "${LINE}" ]]
  do
  ## check the line for content using a case statement
    case $LINE in
      # does it contain Modify? this has the last modified time
      Modify*)printf "%s" "${LINE/Modify: }"2>>"$LOGFILE";;
      *);;
    esac
  done < "$thisFile"
}
modtime(){
  MODfile="$DIR/.placemod"
  [[ -f "$MODfile" ]] && rm "$MODfile" 2>>"$LOGFILE"
  [[ "$(whoami)" == "root" ]] && chmod a+rw "$MODfile" 2>>"$LOGFILE"
  [[ ! -f "$HOME/.config/gtk-3.0/bookmarks" ]] && echo "$HOME/.config/gtk-3.0/bookmarks is not a file" >> "$LOGFILE" 2>>"$LOGFILE" && return
  stat "$HOME/.config/gtk-3.0/bookmarks" > "$MODfile" 2>>"$LOGFILE"
  currentMODtime=$(getModtime "$MODfile")
  if [[ -f "$MODfile.old" ]] && [[ -f "$MENUfileCACHE" ]]
  then
    [[ "$(whoami)" == "root" ]] && chmod a+rw "$MODfile.old" 2>>"$LOGFILE"
    getOLDmodTime=$(getModtime "$MODfile.old")
    if [[ "$getOLDmodTime" == "$currentMODtime" ]]
    then
     cat "$MENUfileCACHE" 2>>"$LOGFILE"
      exit
    fi
  else
    NOFILE="True"
    printf "%s" "<JWM>
<Program label=\"Reload the menu, it has generated fully\">jwm -restart</Program>
<!--"
  fi
  mv "$MODfile" "$MODfile.old" 2>>"$LOGFILE"
}
[[ -n "$FULLHUGEMENU" ]] && modtime
HEADER="<JWM>
<!-- generated by $progname -->"
if [[ -n "$FULLHUGEMENU" ]]
then
  [[ "$(whoami)" == "root" ]] && chmod a+rw "$MENUfileCACHE" 2>>"$LOGFILE"
  printf "%s" > "$MENUfileCACHE"
fi

writeOut "$HEADER"
## GTK ICONS ##
outXML(){
	MSG="$*"
	writeOut "<!--$MSG-->"
}
## Icon names
HOME_ICON="folder-home"
DOC_ICON="folder-documents"
DL_ICON="folder-downloads"
MUSIC_ICON="folder-music"
PIC_ICON="folder-pictures"
VID_ICON="folder-video"
RUBBISH="user-trash"
MEDIA_ICON="file-manager"
FOLDER_ICON="folder"
quoteXML(){
  input="$*"
  input="${input//&/&#09;}"
  input="${input//\\t/&#09;}"
  input="${input//\\n/&#10;}"
  input="${input//!/&#33;}"
  input="${input//\"/&#34;}"
  input="${input//\$/&#36;}"
  input="${input//\%/&#37;}"
  input="${input//\'/&#39;}"
  input="${input//(/&#40;}"
  input="${input//)/&#41;}"
  input="${input//\*/&#42;}"
  input="${input//+/&#43;}"
  input="${input//,/&#44;}"
  input="${input//-/&#45;}"
  input="${input//./&#46;}"
  input="${input//\//&#47;}"
  input="${input//:/&#58;}"
  input="${input//</&#60;}"
  input="${input//=/&#61;}"
  input="${input//>/&#62;}"
  input="${input//\?/&#63;}"
  input="${input//@/&#64;}"
  input="${input//[/&#91;}"
  input="${input//\\/&#92;}"
  input="${input//]/&#93;}"
  input="${input//^/&#94;}"
  input="${input//_/&#95;}"
  input="${input//\`/&#96;}"
  input="${input//\{/&#123;}"
  input="${input//|/&#124;}"
  input="${input//\}/&#125;}"
  input="${input//~/&#126;}"
  printf "%s" "$input"
}
homeName(){
  myLANG="${LANGUAGE%% *}"
  [[ -n "$myLANG" ]] || myLANG="${LANG%_*}"
  local IFS=':'
  HOME_DIR=""
  for dir in ${XDG_DATA_DIRS:-/usr/share/}
  do
  FILE="${dir%/}/desktop-directories/jwm-home.directory"
  if [[ -f "${FILE}" ]]
  then
    while read LINE || [[ -n "$LINE" ]]
    do
      case $LINE in
        "Name[$myLANG]="*)HOME_DIR="${LINE/*=}";;
         *);;
      esac
    done < "${FILE}" 2>>"$LOGFILE"
  fi
  done 2>>"$LOGFILE"
  [[ -z "$HOME_DIR" ]] && HOME_DIR="Home"

  printf "%s" "$HOME_DIR" 2>>"$LOGFILE"
}

# update dirs
xdg-user-dirs-update 2>>"$LOGFILE"
## these are all the XDG variables we want
XDG_COMM=$(which xdg-user-dir 2>>"$LOGFILE")
TRASH=""
if [[ -n "$XDG_COMM" ]]
then
  #DESKTOP=$( "${XDG_COMM}" DESKTOP)
  DOCUMENTS=$( "${XDG_COMM}" DOCUMENTS 2>>"$LOGFILE")
  DOWNLOADS=$( "${XDG_COMM}" DOWNLOAD 2>>"$LOGFILE")
  MUSIC=$( "${XDG_COMM}" MUSIC 2>>"$LOGFILE")
  PICTURES=$( "${XDG_COMM}" PICTURES 2>>"$LOGFILE")
  #PUBLICSHARE=$( "${XDG_COMM}" PUBLICSHARE 2>>"$LOGFILE")
  #TEMPLATES=$( "${XDG_COMM}" TEMPLATES 2>>"$LOGFILE")
  VIDEOS=$( "${XDG_COMM}" VIDEOS 2>>"$LOGFILE")
  #DESKTOP_DIR=${DESKTOP##$HOME/}
  DOCUMENTS_DIR=${DOCUMENTS##$HOME/}
  DOWNLOADS_DIR=${DOWNLOADS##$HOME/}
  MUSIC_DIR=${MUSIC##$HOME/}
  PICTURES_DIR=${PICTURES##$HOME/}
  #PUBLICSHARE_DIR=${PUBLICSHARE##$HOME/}
  #TEMPLATES_DIR=${TEMPLATES##$HOME/}
  VIDEOS_DIR=${VIDEOS##$HOME/}
  HOME_DIR=$(homeName)
else
  DOCUMENTS_DIR="Documents"
  DOWNLOADS_DIR="Downloads"
  MUSIC_DIR="Music"
  PICTURES_DIR="Pictures"
#PUBLICSHARE_DIR="Public"
#TEMPLATES_DIR="Templates"
 #DESKTOP_DIR="Desktop"
  VIDEOS="Videos"
  VIDEOS="$HOME/$VIDEOS_DIR"
  DOCUMENTS="$HOME/$DOCUMENTS_DIR"
  DOWNLOADS="$HOME/$DOWNLOADS_DIR"
  MUSIC="$HOME/$MUSIC_DIR"
  PICTURES="$HOME/$PICTURES_DIR"
  for item in "$VIDEOS" "$DOCUMENTS" "$DOWNLOADS" "$MUSIC" "$PICTURES"
  do
    [[ -d "$item" ]] || mkdir -p "$item" 2>>"$LOGFILE"
  done
  HOME_DIR="${HOME/*\/}"
fi
TRASH_PLACE="$HOME/.local/share/Trash/files"
[[ -d "$TRASH_PLACE" ]] || mkdir -p "$TRASH_PLACE" 2>>"$LOGFILE"


XDGMIME="$(which xdg-mime 2>>$LOGFILE)"
[[ -n "$XDGMIME" ]] && TRASH="$($XDGMIME query default inode/directory 2>>$LOGFILE)"

if [[ -z "$TRASH" ]]
then
  TRASH_PLACE="xdg-open $TRASH_PLACE"
else
  TRASH_PLACE="${TRASH/.desktop} trash:///"
fi
TRASH_PLACE="$(quoteXML ${TRASH_PLACE})"
counter=0
submenu(){
  baseDIR="${*}"
  if [[ ! -d "$baseDIR" ]] || [[ ! -O "$baseDIR" ]]
  then
    return
  fi
  for subDir in "${baseDIR}"/**
  do

    if [[ -d "$subDir" ]]
    then
      if [[ -n "$FULLHUGEMENU" ]]
      then
        BIGmenu "${subDir}" "$FOLDER_ICON" "${subDir/*\/}"
        (( counter >= LIMIT )) && outXML "COUNTER FULL" && counter=0 && return
      else
        subDir="$(quoteXML ${subDir})"
      fi
      writeOut "        <Program icon=\"$(quoteXML $FOLDER_ICON)\" label=\"$(quoteXML ${subDir/$baseDIR})\">xdg-open $(quoteXML ${subDir})</Program>"
    fi
  done
}
BIGmenu(){
   MENU_DIR="$1"
   (( counter >= LIMIT )) && counter=0 && return
   counter=$(( counter + 1 ))
   if [[ -n "$FULLHUGEMENU" ]]
   then
     printf "%s" "$MENU_DIR $counter"
   fi
   XML_MENU_DIR="$(quoteXML $1)"
   if [[ ! -d "$MENU_DIR" ]] || [[ ! -O "$MENU_DIR" ]]
   then
    return
   fi
   ICON="$(quoteXML $2)"
   LABEL="$(quoteXML $3)"
   if [[ "$MENU_DIR" == "$HOME" ]]
   then
    writeOut "    <Program icon=\"$ICON\" label=\"${LABEL}\">xdg-open ${XML_MENU_DIR}</Program>"
    return
   else
     writeOut "   <Menu label=\"${LABEL}\" icon=\"$ICON\" height=\"0\">
       <Program icon=\"$ICON\" label=\"${LABEL}\">xdg-open ${XML_MENU_DIR}</Program>"
submenu "${MENU_DIR}"
     writeOut "    </Menu>"
    fi
}
BIGmenu "$HOME" "$HOME_ICON" "$HOME_DIR"
BIGmenu "$DOCUMENTS" "$DOC_ICON" "$DOCUMENTS_DIR"
BIGmenu "$DOWNLOADS" "$DL_ICON" "$DOWNLOADS_DIR"
BIGmenu "$MUSIC" "$MUSIC_ICON" "$MUSIC_DIR"
BIGmenu "$PICTURES" "$PIC_ICON" "$PICTURES_DIR"
BIGmenu "$VIDEOS" "$VID_ICON" "$VIDEOS_DIR"
[[ -d "/media" ]] && BIGmenu "/media" "$MEDIA_ICON" $"Connected Devices"

## GTK BOOKMARKS
if [[ -f "$HOME/.config/gtk-3.0/bookmarks" ]]
then
  while read LINE || [[ -n "${LINE}" ]]
  do
    LINE="${LINE/file:\/\/}"
    if [[ "${LINE/\//}" != "${LINE}" ]]
    then
      case ${LINE} in
      "${HOME}") ;;
      "${DOCUMENTS}") ;;
      "${DOWNLOADS}") ;;
      "${MUSIC}");;
      "${PICTURES}");;
      "${VIDEOS}");;
      *)
      BIGmenu "${LINE}" "$FOLDER_ICON" "${LINE/*\/}"
      ;;
      esac
    fi
  done < "$HOME/.config/gtk-3.0/bookmarks" 2>>"$LOGFILE"
fi

## END MENU tag
writeOut "        <Program icon=\"$(quoteXML $RUBBISH)\" label=\"Trash\">$TRASH_PLACE</Program>
</JWM>"
[[ "$(whoami)" == "root" ]] && chmod a+rw "$LOGFILE" 2>>"$LOGFILE"
[[ "$NOFILE" == "True" ]] && printf "%s" "--!></JWM>"
