#!/bin/bash



#starting with define of stream getter functions
#for all funcions: $1 = stream, $2 = time to download
function flvGetter {
  curl -s -m $2 $1 2> /dev/null | MistAnalyserFLV -D 0 -g 0 -V -T $2 2> /dev/null
}

function hlsGetter {
  MistAnalyserHLS -D 0 -g 0 -V -T $2 $1 2>/dev/null
}

function oggGetter {
  curl -s -m $2 $1 | MistAnalyserOGG -D 0 -g 0 -V -T $2
}

function dashGetter {
  MistAnalyserDASH -D 0 -g 0 -V -T $2 $1 2>/dev/null
}

function tsGetter {
  curl -s -m $2 $1 2> /dev/null | MistAnalyserTS -D 0 -g 0 -T $2 -V - 2>/dev/null
}

function rtmpGetter {
  #$rtmpGetter ignores $2, because rtmpdump has no time setting
  #rtmpdump is ended with killall in parent function
  rtmpdump -qRr $1 -o - 2> /dev/null | MistAnalyserFLV -g 0 -D 0 -V -T $2 2> /dev/null
}

function serverTest {
  rm /tmp/res*_*
  #this functions creates a csv file with all statistics during the tests
  #$1 = number of stream batches
  #$2 = amount of streams per batch (amount of streams = $! * $2)
  #$3 = current stream test
  #$4 = duration of test in seconds
  #$5 = getter used for stream testing
  #$6 = Output basename
  echo "Test variables:" > $6.info
  echo "Start time: `date`" >> $6.info
  echo "Client count: `echo "$1 * $2" | bc`" >> $6.info
  echo "Batch Size: $2" >> $6.info
  echo "Stream URL: $3"  >> $6.info
  echo "Duration: $4 seconds" >> $6.info
  val="none"
  if [ -n "$5" ] ; then
    echo "Validator: $5" >> $6.info
    val="$5"
  fi
  
  getter="${val}Getter"
  #starting all tests
  prefix="res"`date +%s`_
  for x in `seq 1 1 $1`; do
    for y in `seq 1 1 $2`; do
      eval "$getter $3 $4" >& /tmp/$prefix`echo "$x * $2 + $y" | bc`.txt &
    done
    sleep 1
  done
  
  start=`date +%s`
  f=$(( `date +%s` - $start ))
  while [ $f -lt $4 ]; do
    sleep 2
    f=$(( `date +%s` - $start ))
  done
  if [ "$val" == "rtmp" ] ; then
    killall rtmpdump
  fi
  #wait 20 seconds after terminating
  start=`date +%s`
  f=$(( `date +%s` - $start ))
  while [ $f -lt 20 ]; do
    sleep 2
    f=$(( `date +%s` - $start ))
  done
  cat /tmp/$prefix* > $6.times
  wait
}


#setting default values
declare -a timegroup
declare -a request
declare -a stream

if [ $# -eq 0 ] ; then
  echo "Usage: $0 -t duration_in_seconds -b 'batchcount clients_per_batch' -m stream_url";
  echo "Duration defaults to 60 seconds if not given";
  echo "Batch defaults to '1 100' if not given (1 batch of 100 clients)";
  echo "Stream URL is the only mandatory field"
  exit 1;
fi

#parsing arguments
red=1
while [ $red -le $# ]; do
  case ${!red} in
    "-t") #defines timelengths for tests
      red=$(( $red + 1 ))
      timegroup+=( ${!red} )
    ;;
    "-b") #defines user batches for tests (must be in format "batchamount batchsize")
      red=$(( $red + 1 ))
      request+=( "${!red}" )
    ;;
    "-m") #defines a media stream and validator
      red=$(( $red + 1 ))
      stream+=( "${!red}" )
    ;;
    *)
  esac
  red=$(( $red + 1 ))
done

#determining validators
for (( i=0; i<${#stream[@]}; i++ )) ; do
  if [ "${stream[$i]:0:4}" == "rtmp" ]; then
    validator[$i]="rtmp"
  elif [ "${stream[$i]:0:2}" == "ws" ]; then
    validator[$i]="rtc"
  else
    tempFile=$(basename "${stream[$i]}")
    tempExt="${tempFile##*.}"
    case $tempExt in
    "flv")
      validator[$i]="flv"
    ;;
    "ogg")
      validator[$i]="ogg"
    ;;
    "m3u8")
      validator[$i]="hls"
    ;;
    "m3u")
      validator[$i]="hls"
    ;;
    "mpd")
      validator[$i]="dash"
    ;;
    "ts")
      validator[$i]="ts"
    ;;
    "mkv")
      validator[$i]="ebml"
    ;;
    *)
      validator[$i]="generic"
    esac
  fi
done

if [ ${#request[@]} == 0 ]; then
  request=( "1 100" )
fi

if [ ${#timegroup[@]} == 0 ]; then
  timegroup=( 60 )
fi

#making directory for test
temp="loadtest`date +%y%m%d%H%M%S`"
mkdir $temp

#starting test
for (( i=0; i<${#stream[@]}; i++ )) ; do
  for (( p=0; p<${#timegroup[@]}; p++ )) ; do
    for (( o=0; o<${#request[@]}; o++ )) ; do
      tnr=` echo "$i * ${#timegroup[@]} * ${#request[@]} + $o * ${#timegroup[@]} + $p" | bc `
      name=$temp"/run"
      if [ $tnr -lt 100 ] ; then
        name="${name}0"
      fi
      if [ $tnr -lt 10 ] ; then
        name="${name}0"
      fi
      amount=`echo ${request[$o]} | sed -e 's/ /*/g' | bc`
      name="${name}${tnr}_${amount}_${validator[$i]}_${timegroup[$p]}"
      echo "$name testing ${request[$o]} batches on ${stream[$i]} for ${timegroup[$p]} seconds using validator ${validator[$i]}"
      serverTest ${request[$o]} ${stream[$i]} ${timegroup[$p]} ${validator[$i]} $name
    done
  done
done

FOLDER=$temp
LABEL=$temp

T="pngcairo size 1000,600 enhanced font \"LiberationSerif,20\""
EXT=png
#T="pdfcairo"
#EXT=pdf

function runplot {
  for R in `seq -w 0 100`; do
    FLDS=( $1 )
    NAMS=( $2 )

    FN=`ls ${FLDS[0]}/run${R}_*.times 2> /dev/null`
    if [ -z $FN ] ; then
      return
    fi
    FILE=`basename $FN`

    FN=`ls ${FLDS[0]}/run${R}_*.times 2> /dev/null`
    TIMES=`basename $FN`
    VIEWERS=`echo $FILE | cut -d '_' -f 2`
    TECH=`echo $FILE | cut -d '_' -f 3`
    SECS=`echo $FILE | cut -d '.' -f 1 | cut -d '_' -f 4`
    TIME=$(( $SECS / 60 ))m

    FILES=()
    TIME_FN=()

    for i in `seq $(( ${#FLDS[@]} - 1 )) -1 0`; do
      FN=`ls ${FLDS[$i]}/run${R}_*.times 2> /dev/null`
      if [ -z $FN ] ; then
        return
      fi
      FILES[$i]="${FLDS[$i]}/`basename $FN`"
      FN=`ls ${FLDS[$i]}/run${R}_*.times 2> /dev/null`
      TIME_FN[$i]="${FLDS[$i]}/`basename $FN`"
    done

    COMMON_DATA="${TIME}, ${VIEWERS} ${TECH}"
    COMMON_FILENAME="${TECH}_${VIEWERS}_${TIME}"

    PLOT5=""
    for i in `seq $(( ${#FLDS[@]} - 1 )) -1 0`; do
      if [ -n "${PLOT5}" ] ; then
        PLOT5="${PLOT5}, "
      fi
      sort --field-separator=',' --key=4g < "${TIME_FN[$i]}" > "${TIME_FN[$i]}_sorted"
      VC=`cut -f 4 -d ',' < "${TIME_FN[$i]}" | awk "(int(\\\$1) >= ${SECS}000-2000) {sum++} END{print sum}"`
      SC=`cut -f 4 -d ',' < "${TIME_FN[$i]}" | awk "(int(\\\$1) >= ${SECS}000-10000) {sum++} END{print sum}"`
      #and buffer times. Smoothing makes no sense here. Don't.
      PLOT5="${PLOT5}'${TIME_FN[$i]}_sorted' using (\$4-${SECS}000)/1000 with linespoints lw 1 title '${VC} good, ${SC} acceptable'"
    done

    gnuplot << EOF
set terminal ${T}
set datafile separator ","
set key on under center

#set style fill solid 0.25 border -1
#set style boxplot outliers pointtype 7
#set style data boxplot
#set boxwidth  0.5
set pointsize 0.2
set arrow from 0,-2 to ${VIEWERS}-1,-2 nohead

set title "Available buffer time, ${COMMON_DATA} clients"
set output '${FOLDER}/${COMMON_FILENAME}_buffers.${EXT}'
set format y "%gs"
set ylabel "Buffer (under black line = success)"
set xlabel "Each point represents a single connection"
unset xtics
set yr [${SECS}:-5]
plot ${PLOT5}


EOF

    for i in `seq $(( ${#FLDS[@]} - 1 )) -1 0`; do
      rm -f "${FLDS[$i]}/${TIMES}_sorted"
    done
  done
}

runplot "$LABEL" "$FOLDER"