#!/bin/bash

# Script moves tagged mails to their respective folders if they are still lying around in INBOX
# It also moves mails tagged with "del" to the Trash folder, "archive" to Archive, and "spam" to Spam folder

CURDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

DEBUG=false    # use 'true' to echo verbose debug messages

CSV="$CURDIR"/tag-list.csv    # Table of tags/folders
MAILDIR="$HOME/Mails/FSFE"    # Maildir
TRASHTAG="del"    # Tag of trashed mails
TRASHFOL="Trash"  # Trash bin folder
SPAMTAG="spam"         # Tag of spam mails
SPAMFOL="INBOX.Junk"   # Spam folder
ARCHTAG="archive"   # Archive tag
ARCHFOL="ARCHIVE"   # Archive folder
LOG="$CURDIR"/move-tag.log  # Location of logfile
USETAGS=".+"  # List of tags which shall be moved
THREADTAGS=".+"  # List of tags for which single, but connected messages in INBOX shall be tagged

BL_USETAGS=""   # Tags which are *not* considered to be moved
BL_THREADTAGS="$TRASHTAG|$SPAMTAG|$ARCHTAG|draft"   # Tags for which their whole thread will not be tagged if they are still in INBOX

touch "$LOG"  # Create logfile or update time stamp

var_conn=$1   # supposed to be "on" or "off"

function pdate {
  DATE=$(date +%y-%m-%d_%H:%M:%S)
  echo "[$DATE]"
}

function logrun {
  # Write command itself to log, and pipe errors to log
  echo "$(pdate) $@" >> "$LOG"
  eval "$@" 2>> "$LOG"
}

function debugmsg {
  if ${DEBUG}; then
    echo "$(pdate) $@"
  fi
}

# Set date until when files are searched for, depending on current connection status
if [ "${var_conn}" == "off" ]; then
  DATELIMIT="1d"
  logrun echo "Datelimit for search set to $DATELIMIT"
else
  DATELIMIT="14d"
  logrun echo "Datelimit for search set to $DATELIMIT"
fi

while read line; do
  TAG=$(echo $line | cut -d";" -f1)
  FOL=$(echo $line | cut -d";" -f2)

  if ! $(echo $BL_USETAGS | grep -qE "${TAG}($|\|)") && $(echo $TAG | grep -qE "$USETAGS"); then
    BL_USETAGS="$TAG,$BL_USETAGS"   # Add current tag to list of tags which do not have to be searched for another time

    # TRASH tag "del"
    if [ "$TAG" = "$TRASHTAG" ]; then
      debugmsg "search trash tagged mails"
      HITFILES=$(notmuch search --output=files --exclude=false tag:$TRASHTAG and not path:$TRASHFOL/**) # Files which are tagged with "del" but not in Trash bin
      FOL="$TRASHFOL"   # Set destination folder to Trash

    # SPAM tag "spam"
    elif [ "$TAG" = "$SPAMTAG" ]; then
      debugmsg "search spam tagged mails"
      HITFILES=$(notmuch search --output=files --exclude=false tag:$SPAMTAG and not path:$SPAMFOL/**) # Files which are tagged with "spam" but not in Spam folder
      FOL="$SPAMFOL"   # Set destination folder to INBOX.Junk

    # ARCHIVE tag "archive"
    elif [ "$TAG" = "$ARCHTAG" ]; then
      debugmsg "search archive tagged mails"
      HITFILES=$(notmuch search --output=files --exclude=false tag:$ARCHTAG and not path:$ARCHFOL/**) # Files which are tagged with "archive" but not in ARCHIVE folder
      # Folder will be derived from the current position later

    # DEFAULT
    else
      # For some tags, also tag its threads
      if ! $(echo $BL_THREADTAGS | grep -qE "${TAG}($|\|)") && $(echo $TAG | grep -qE "$THREADTAGS"); then
        # If one file is tagged (except del, spam, archive), also tag the other mails of its thread respectively, IF they are located in INBOX [TODO: is this the best approach?]. Only then they can be moved by this script

        # 1. Get thread ids of all entries with the searched tag
        debugmsg "search for all threads tagged with $TAG"
        THREADS=$(notmuch search --exclude=false tag:$TAG and date:${DATELIMIT}.. | cut -d" " -f1 | cut -d":" -f2)

        # 2. Get message ids of all messages in these threads
        debugmsg "search for all IDs of these threads"
        MID=
        for t in $THREADS; do
          MID="$MID "$(notmuch search --output=messages --exclude=false thread:$t)
          # MID consists of many something like "id:5XXX0CD1.305516@fsfe.org"
        done

        # 3. Tag all message ids of messages which are still in INBOX
        debugmsg "tag all these IDs if they are in INBOX:" $(echo "$MID" | wc -w) "files"
        for m in $MID; do
          if $(notmuch search --exclude=false --output=files "$m" | grep -q "$MAILDIR/INBOX/"); then
            debugmsg "tag $m with $TAG"
            logrun notmuch tag +"$TAG" -- "$m"
          fi
        done
        
        # Search for these lone messages in INBOX
        debugmsg "search for these messages which are still in INBOX"
        HITFILES=$(notmuch search --output=files --exclude=false path:INBOX/** and tag:$TAG | grep "$MAILDIR/INBOX/")
      fi
      
    fi

    # Move files to their destination folders
    debugmsg "move the files of tag $TAG"
    for m in $HITFILES; do

      # Destination folder is derived from the current location
      if [ "$TAG" = "$ARCHTAG" ]; then
        SUBFOL=$(echo $m | sed -E "s|($MAILDIR)/(.+?)/cur/.*|\2|g")
        FOL="$ARCHFOL/$SUBFOL"
      fi
      DESTFOL="$MAILDIR/$FOL/cur"
      if [ ! -e "$DESTFOL" ]; then
        logrun mkdir -p "$DESTFOL"
      fi
      logrun mv "$m" "$DESTFOL"
    done
  fi
  
  debugmsg "Tag $TAG finished"
  debugmsg ""

done < "$CSV"
