#!/bin/sh

#-PARAMETERS--------------------------------------
MMSERVER_ADDR=brasspounder.com	# Default server
MMSERVER_PORT=8873		# Default port
NEW_MSG_CHECK_DELAY=60		#seconds
CWCHANNEL=1000
#-------------------------------------------------



# Function to get an XML file from the MorseServe server, unixise it, put it all
# on one line, strip the HTML XML header and split all the tags and words
function get_mm_xml
{
  MMXML=`curl --stderr /dev/null $MMSERVER/$1 | awk '{gsub(/\r/,"");	\
  	sub(/<\?xml .* \?>/,"");gsub(/<[^>]*>/," & ");printf($0" ")}'`
}



# Find out all the MorseServe channels
function map_mm_channels
{
  echo "Getting the list of available channels on $MMSERVER ..."
  get_mm_xml channels
  MMCHANNELS=(`(for I in $MMXML;do echo $I;done) | awk '/<\/channel>/	\
	{c=0} c==1 {print $0} /<channel>/ {c=1}'`)
  echo "Done."
}



# Function that fetches a message on channel $1, with timestamp $2 and sends
# it in CWirc format
function fetch_and_play_msg
{
  echo "[REJECT INCOMING MESSAGES]"
  echo "Fetching message ..."
  let TSTAMP_MINUS_ONE_MS=$2-1
  get_mm_xml ${MMCHANNELS[$1]}/?ms1970=$TSTAMP_MINUS_ONE_MS
  MSG_DE=`(for I in $MMXML;do echo $I;done) | awk '/<\/DE>/ {c=0} c==1	\
		{print $0} /<DE>/ {c=1}'`
  MSG_EVTS=`(for I in $MMXML;do echo $I;done) | awk '/<\/MorseMail>/	\
		{c=0} c==1 {print $0} /<MorseMail>/ {c=1}'`
  MSG_EVTS=`echo $MSG_EVTS | awk '{sub(/^....\...\.../,"");		\
		gsub(/-/," -");gsub(/+/," +");print $0}'`

  echo "Sending message. Send anything to stop ..."
  echo "$MSG_EVTS"						\
  	| ./send_cw events $CWCHANNEL "" "" "$MSG_DE" "" &
  SENDING_PROCESS_PID=$!

  echo "[ACCEPT INCOMING MESSAGES]"
  while [ "`ps --no-headers -p $SENDING_PROCESS_PID`" ];do
    if read -t 2;then
      kill $SENDING_PROCESS_PID
    fi
  done
  wait $SENDING_PROCESS_PID 2> /dev/null

  echo "Done sending message."
}



# Main program
echo "[REJECT INCOMING MESSAGES]"
if [ "$2" ] && [ "$3" ];then
  MMSERVER_ADDR=$2
  MMSERVER_PORT=$3
fi
MMSERVER="$MMSERVER_ADDR:$MMSERVER_PORT"

echo "---------MORSEMAIL-REPEATER----------"
echo "73 $1!"
echo "I will send CW on channel $CWCHANNEL."
echo "-------------------------------------"
echo " "
echo "This repeater allows you to send and receive"
echo "CW messages to and from the MorseServe server"
echo "at $MMSERVER from the CWirc network."
echo " "
echo "Go to http://www.seanet.com/~harrypy/MorseMail/"
echo "for more information about MorseMail, written"
echo "by Harry Pyle AB7TB."
echo " "

map_mm_channels

QUIT=0
C=0
while [ $QUIT = 0 ];do
  echo "[ACCEPT INCOMING MESSAGES]"
  echo " "
  echo "Menu:"
  echo " "
  echo "1 - Listen to MorseServe channel \"${MMCHANNELS[$C]}\" live"
  echo "2 - Browse older messages on MorseServe channel \"${MMCHANNELS[$C]}\""
  echo "3 - Send message to MorseServe channel \"${MMCHANNELS[$C]}\""
  echo " "
  echo "C - Change current channel (currently \"${MMCHANNELS[$C]}\")"
  echo " "
  echo "Q - Quit"
  echo " "
  echo "Your choice ?"
  read

  case "$REPLY" in
  1)
    FIRSTCALL=1
    LQUIT=0
    while [ $LQUIT = 0 ];do
      echo "[REJECT INCOMING MESSAGES]"

      # Get the timestamp of the latest message on this channel
      echo "Checking for new messages ..."
      get_mm_xml ${MMCHANNELS[$C]}/time
      TSTAMP=`(for I in $MMXML;do echo $I;done) | awk '/<\/ms1970>/	\
		{c=0} c==1 {print $0} /<ms1970>/ {c=1}'`

      if [ $FIRSTCALL = 1 ];then
        TSTAMP_PREV=$TSTAMP
        FIRSTCALL=0
      fi

      # New message ?
      if [ "$TSTAMP" != "$TSTAMP_PREV" ];then
        fetch_and_play_msg ${MMCHANNELS[$C]} $TSTAMP
      else
        echo "No new message."
      fi
      TSTAMP_PREV=$TSTAMP
      
      echo "[ACCEPT INCOMING MESSAGES]"
      echo "Send anything to return to the main menu,"
      echo "or wait for the next new message check ..."
      if read -t $NEW_MSG_CHECK_DELAY;then
        LQUIT=1
      fi
    done
    ;;

  2)
    echo "[REJECT INCOMING MESSAGES]"
    get_mm_xml ${MMCHANNELS[$C]}/msgs
    TSTAMP_L=(`(for I in $MMXML;do echo $I;done) | awk '/<\/ms1970>/	\
		{c=0} c==1 {print $0} /<ms1970>/ {c=1}'`)
    DE_L=(`(for I in $MMXML;do echo $I;done) | awk '/<\/DE>/ {c=0} c==1	\
		{print $0} /<DE>/ {c=1}'`)
    TO_L=(`(for I in $MMXML;do echo $I;done) | awk '/<\/TO>/ {c=0} c==1	\
		{print $0} /<TO>/ {c=1}'`)
    LEN_L=(`(for I in $MMXML;do echo $I;done) | awk '/<\/msLength>/	\
		{c=0} c==1 {printf("%.1f\n",$0/1000)} /<msLength>/ {c=1}'`)
    echo "[ACCEPT INCOMING MESSAGES]"
    echo " "
    J=0
    K=1
    S="  "
    for I in ${TSTAMP_L[*]};do
      D=`date -d"1970-01-01 UTC ${I:0:10} sec" +"%D %T"`
      echo "${S:${#K}}$K - $D, ${TO_L[$J]} de ${DE_L[$J]} (${LEN_L[$J]} sec)"
      let J=J+1
      let K=K+1
      let M=(K-1)%20
      if [ $M = 0 ] && [ $K -gt 0 ];then
        echo "More [Y/N]?"
        read
        if [ "$REPLY" != y ] && [ "$REPLY" != Y ];then
          break
        fi
      fi
    done

    echo " "
    echo "Choose a message to replay, or Q to return to the main menu:"
    read
    if [ "$REPLY" != q ] && [ "$REPLY" != Q ];then
      if [ "$REPLY" ] &&
	[ "`echo $REPLY|awk '{sub(/[^[:digit:]]/,"");print $0}'`" = "$REPLY" ]
      then
        let INTVAL=$REPLY-1
      else
        let INTVAL=-1
      fi
      if [ $INTVAL -lt 0 ] || [ "${TSTAMP_L[$INTVAL]}" = "" ];then
        echo "Invalid message!"
      else
        fetch_and_play_msg $C TSTAMP_L[$INTVAL]
      fi
    fi
    ;;

  3)
    echo "Key your CW message, then type \"send [destination]\""
    echo "when you're done, or type \"cancel\" to abort sending."
    echo "If you leave [destination] blank, it will be sent to \"ALL\"."
    echo " "
    echo "Recording your CW message now ..."

    SQUIT=0
    MSG_EVTS=""
    CALLSIGN=""
    while [ $SQUIT = 0 ];do
      read -r
      case "$REPLY" in
      send|send\ *)
        if [ "$MSG_EVTS" ];then
          # Find out the source
          if [ "${CALLSIGN}" ];then
            DE=$CALLSIGN
          else
            DE=$1	# No callsign in CW transmission : fallback on IRC nick
          fi

          # Find out the destination
          TO=${REPLY:5}
          if [ "${TO}" = "" ];then
            TO="ALL"
          fi

          # Create the XML message to send to the MorseServe server
          MSG_EVTS=`echo $MSG_EVTS | awk '{gsub(/ /,"");print $0}'`
          MMXML="<MorseMail>$MSG_EVTS</MorseMail><DE>$DE</DE><TO>$TO</TO>"

          # Send the message to the MorseServe server
          echo "Sending message to $MMSERVER/${MMCHANNELS[$C]}/ ..."

          echo "[REJECT INCOMING MESSAGES]"
          SEND_RESULT=`echo -n "$MMXML" | ./post_to_morseserve		\
		$MMSERVER_ADDR $MMSERVER_PORT ${MMCHANNELS[$C]} |	\
		awk '/HTTP.*OK/ {print "OK"}'`
          if [ "${SEND_RESULT}" = "OK" ];then
            echo "Message sent."
          else
            echo "Error sending message!"
          fi

          SQUIT=1
        else
          echo "Nothing to send!"
        fi
        ;;

      cancel|quit|exit)
        echo "Transmission cancelled!"
        SQUIT=1
        ;;

      *)
        # Did the user send a CW frame ?
        if CWFRAME_PARAMS=`echo "$REPLY" | ./decode_cw_frame`;then
          # Extract the callsign, if any
          CALLSIGN=`echo $CWFRAME_PARAMS | awk '{c=$1;			\
			sub(/callsign=/,"",c);print c}'`

          # Add the new events to the already-recorded ones
          NEW_EVTS=`echo $CWFRAME_PARAMS |				\
			awk '{sub(/^.*cwchannel=[[:digit:]]* /,"");print $0}'`
          MSG_EVTS="$MSG_EVTS $NEW_EVTS"

          # Combine eventual consecutive space or mark events
          MSG_EVTS=`(for I in $MSG_EVTS;do echo $I;done) |		\
		awk '(/+/ && p==0) || (/-/ && p==1) {lv=$0}		\
		(/+/ && p==1) || (/-/ && p==0)				\
		{sub(/[+-][[:digit:]]* *$/,"",l);lv=lv+$0}		\
		{l=sprintf("%s %s%d",l,(lv>=0?"+":""),lv)}		\
		/+/ {p=1} /-/ {p=0} END {print l}'`
        else
          echo "Malformed CW frame or invalid response."
          echo "Transmission cancelled!"
          SQUIT=1
        fi
        ;;
      esac
    done
    ;;

  c|C)
    echo "Channels available on $MMSERVER:"
    echo " "
    let J=1
    for I in ${MMCHANNELS[*]};do
      echo "$J - $I"
      let J=J+1
    done
    echo " "
    echo "Your choice ?"
    read
    if [ "$REPLY" ] &&
	[ "`echo $REPLY|awk '{sub(/[^[:digit:]]/,"");print $0}'`" = "$REPLY" ]
    then
      let INTVAL=$REPLY
    else
      let INTVAL=-1
    fi
    if [ $INTVAL -lt 1 ] || [ $INTVAL -ge $J ];then
      echo "Invalid channel!"
    else
      let C=$INTVAL-1
    fi
    ;;

  q|Q)
    QUIT=1
    ;;
  esac
done

echo "[ACCEPT INCOMING MESSAGES]"
