#!/bin/bash

if [ -f 'config.sh' ]; then
  if [ -f 'config.tmp' ]; then
    . ./config.tmp
  fi
  set -e
  . ./config.sh
  set +e
  echo "# ----- LAST STABLE CONFIGURATION ----- #" > config.tmp
  echo "#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN" >> config.tmp
  echo "BFW_SKIP_UPDATE=\"$BFW_SKIP_UPDATE\"" >> config.tmp
  echo "BFW_UID=\"$BFW_UID\"" >> config.tmp
  echo "BFW_PWD=\"$BFW_PWD\"" >> config.tmp
  echo "BFW_SAVE_PWD=\"$BFW_SAVE_PWD\"" >> config.tmp
  echo "CC_HOST=\"$CC_HOST\"" >> config.tmp
  echo "BFW_HND=\"$BFW_HND\"" >> config.tmp
  echo "BFW_HOST=\"$BFW_HOST\"" >> config.tmp
  echo "BFW_PORT=\"$BFW_PORT\"" >> config.tmp
  echo "BFW_APPID=\"$BFW_APPID\"" >> config.tmp
  echo "BFW_APPPWD=\"$BFW_APPPWD\"" >> config.tmp
else
  echo "You'll need to answer a few questions for first time setup. To change any of these options see config.sh. To reset delete config.sh"
  echo "REMEMBER TO BACK UP YOUR APP PASSWORD BEFORE DELETING 'config.sh'"
  rm -f config.tmp
fi

BFW_UPDATE_ENDPOINT=0
ASK_QUESTIONS=1
USE_NGROK=0
while [ "$ASK_QUESTIONS" -eq 1 ]; do
  ASK_QUESTIONS=0
  echo "#" > config.sh
  echo "# Configuration file for Lucida's BotFramework interface" >> config.sh
  echo "#" >> config.sh

  if [ -z "$BFW_SKIP_UPDATE" ]; then
    echo ""
    echo "By default this script updates messaging endpoint automatically as and when required. You can also set endpoint manually as explained in README"
    echo "This feature is experimental and requires your Microsoft account password"
    echo "Do you want to skip automatic update of endpoint? (y/n)"
    printf "BFW_SKIP_UPDATE [n]: "
    read response
    if [ -z "$respone" ]; then response="n"; fi
    if [[ "$response" != "n" ]] && [[ "$response" != "N" ]]; then
      BFW_SKIP_UPDATE=1
      BFW_UID=
      BFW_PWD=
      BFW_SAVE_PWD=0
      BFW_HOST=
      BFW_HND=
    else
      BFW_SKIP_UPDATE=0
    fi
  fi

  if [ -z "$BFW_UID" ] && [ "$BFW_SKIP_UPDATE" -eq 0 ]; then
    BFW_PWD=
    BFW_SAVE_PWD=
    while [ 1 ]; do
      echo ""
      echo "Enter the email address associated with your Microsoft account. If you don't have an account create one at 'https://signup.live.com/'"
      printf "BFW_UID: "
      read BFW_UID
      echo "$BFW_UID" | grep -Poe "^[A-Za-z0-9_\.]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\.\-_]+$" > /dev/null
      if [ "$?" -ne 0 ]; then
        echo "[ERROR] Please provide a valid email address!!!"
        continue
      fi
      echo ""
      echo "Enter your Microsoft account password. Passwords with exclaimation marks (!), double quotes (\") and backticks (\`) are not supported"
      printf "BFW_PWD: "
      stty -echo
      read BFW_PWD
      stty echo
      echo ""
      echo "$BFW_PWD" | grep -Poe "^[A-Za-z0-9~\!@#\$%\^&*()\-=_+{}\|\[\];:'<>?,\./]{8,16}$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid password!!!"
        continue
      fi
      break
    done
  fi
  echo "" >> config.sh
  echo "# Skip automatic endpoint update (0/1). You may need to update your endpoint at every run if you use ngrok (default). See README" >> config.sh
  echo "BFW_SKIP_UPDATE=\"$BFW_SKIP_UPDATE\"" >> config.sh
  echo "" >> config.sh
  echo "# Microsoft account email address" >> config.sh
  echo "BFW_UID=\"$BFW_UID\"" >> config.sh

  if [ -z "$BFW_PWD" ] && [ ! -z "$BFW_UID" ]; then
    while [ 1 ]; do
      echo ""
      echo "Enter your Microsoft account password. Passwords with exclaimation marks (!), double quotes (\") and backticks (\`) are not supported"
      printf "BFW_PWD: "
      stty -echo
      read BFW_PWD
      stty echo
      echo ""
      echo "$BFW_PWD" | grep -Poe "^[A-Za-z0-9~\!@#\$%\^&*()\-=_+{}\|\[\];:'<>?,\./]{8,16}$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid password!!!"
      else
        break
      fi
    done
  fi

  if [ -z "$BFW_SAVE_PWD" ]; then
    if [ -z "$BFW_PWD" ]; then
      BFW_SAVE_PWD=0
    else
      echo ""
      echo "Do you want me to save password to file? It will be saved in plain text. (y/n)"
      printf "BFW_SAVE_PWD [n]: "
      read BFW_SAVE_PWD
      if [ -z "$BFW_SAVE_PWD" ] || [[ "$BFW_SAVE_PWD" == "n" ]] || [[ "$BFW_SAVE_PWD" == "N" ]]; then
        BFW_SAVE_PWD=0
      else
        BFW_SAVE_PWD=1
      fi
    fi
  fi
  echo "" >> config.sh
  echo "# Microsoft account password" >> config.sh
  if [ "$BFW_SAVE_PWD" -eq 1 ]; then
    echo "BFW_PWD=\"$BFW_PWD\"" >> config.sh
  else
  echo "BFW_PWD=" >> config.sh
  fi
  echo "" >> config.sh
  echo "# Do we save Microsoft account password? (0/1)" >> config.sh
  echo "BFW_SAVE_PWD=\"$BFW_SAVE_PWD\"" >> config.sh

  if [ -z "$CC_HOST" ]; then
    while [ 1 ]; do
      echo ""
      echo "Enter the host:port on which command center is running (e.g. 'http://localhost:3000'). URLs with exclaimation marks ('!') are not allowed."
      echo "If you have no idea what this is you may use default"
      printf "CC_HOST [http://localhost:3000]: "
      read CC_HOST
      if [ -z "$CC_HOST" ]; then CC_HOST="http://localhost:3000"; fi
      echo "$CC_HOST" | grep -Poe "^(https?://)?[A-Za-z0-9\-\._~:/\?#\[\]'@\$&()*+,;=%]+$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid host!!!"
      else
        echo "$CC_HOST" | grep -Poe "^https?://" > /dev/null
        if [ "$?" -eq 1 ]; then
          CC_HOST=`echo http://$CC_HOST`
        fi
        break
      fi
    done
  fi
  echo "" >> config.sh
  echo "# Command center URL" >> config.sh
  echo "CC_HOST=\"$CC_HOST\"" >> config.sh

  if [ -z "$BFW_HND" ] && [ "$BFW_SKIP_UPDATE" -eq 0 ]; then
    while [ 1 ]; do
      echo ""
      echo "Enter the handle of the bot you plan to use with Lucida. If you haven't created a bot do so at 'https://dev.botframework.com/bots/new'"
      printf "BFW_HND: "
      read BFW_HND
      echo "$BFW_HND" | grep -Poe "^[A-Za-z0-9\-_]{3,16}$" > /dev/null
      if [ "$?" -ne 0 ]; then
        echo "[ERROR] Please enter a valid bot handle!!!"
      else
        break
      fi
    done
  fi
  echo "" >> config.sh
  echo "# BotFramework bot handle" >> config.sh
  echo "BFW_HND=\"$BFW_HND\"" >> config.sh

  if [ "$USE_NGROK" -eq 1 ]; then BFW_HOST="https://xxx.ngrok.io"; fi
  if [ -z "$BFW_HOST" ] && [ "$BFW_SKIP_UPDATE" -eq 0 ]; then
    while [ 1 ]; do
      echo ""
      echo "Enter messaging endpoint (https only) on which Lucida's BotFramework interface is running (e.g. 'https://xxx.ngrok.io'). URLs with exclaimation marks ('!') are not allowed."
      echo "If you have no idea what this is just press enter. Doing so will require you to enter your account password everytime you launch BotFramework interface or save it to config.sh"
      printf "BFW_HOST [https://xxx.ngrok.io]: "
      read BFW_HOST
      if [ -z "$BFW_HOST" ]; then BFW_HOST="https://xxx.ngrok.io"; USE_NGROK=1; fi
      echo "$BFW_HOST" | grep -Poe "^https://[A-Za-z0-9\-\._~:/\?#\[\]'@\$&()*+,;=%]+$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid host!!!"
      else
        break
      fi
    done
    BFW_UPDATE_ENDPOINT=1
  fi
  if [ -f "last_pushed_host" ]; then
    BFW_OLD_HOST=`cat last_pushed_host`
    if [[ "$BFW_OLD_HOST" != "$BFW_HOST" ]]; then
      BFW_UPDATE_ENDPOINT=1
    fi
  else
    BFW_UPDATE_ENDPOINT=1
  fi
  echo "" >> config.sh
  echo "# BotFramework bot endpoint" >> config.sh
  echo "BFW_HOST=\"$BFW_HOST\"" >> config.sh

  if [ -z "$BFW_PORT" ]; then
    while [ 1 ]; do
      echo ""
      echo "Enter the port on which Lucida BotFramework interface should run."
      printf "BFW_PORT [3728]: "
      read BFW_PORT
      if [ -z "$BFW_PORT" ]; then BFW_PORT=3728; fi
      echo "$BFW_PORT" | grep -Poe "^\d{2,5}$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid port!!!"
      else
        break
      fi
    done
  fi
  echo "" >> config.sh
  echo "# BotFramework listen port" >> config.sh
  echo "BFW_PORT=\"$BFW_PORT\"" >> config.sh

  if [ -z "$BFW_APPID" ] || [ -z "$BFW_APPPWD" ]; then
    while [ 1 ]; do
      echo ""
      echo "Enter Microsoft application ID and password. (View README)"
      printf "BFW_APPID: "
      read BFW_APPID
      echo "$BFW_APPID" | grep -Poe "^[A-Za-z0-9\-]+$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid application ID!!!"
        continue
      fi
      printf "BFW_APPPWD: "
      read BFW_APPPWD
      echo "$BFW_APPPWD" | grep -Poe "^[A-Za-z0-9]+$" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Please enter a valid application password!!!"
      else
        break
      fi
    done
  fi
  echo "" >> config.sh
  echo "# BotFramework credentials" >> config.sh
  echo "BFW_APPID=\"$BFW_APPID\"" >> config.sh
  echo "BFW_APPPWD=\"$BFW_APPPWD\"" >> config.sh

  if [[ "$BFW_HOST" == "https://xxx.ngrok.io" ]] && [ "$BFW_SKIP_UPDATE" -eq 0 ]; then
    USE_NGROK=1
    BFW_HOST=
    ps -ef | grep ngrok | grep http | grep "$BFW_PORT" > /dev/null
    if [ "$?" -eq 1 ]; then
      ngrok http "$BFW_PORT" > /dev/null & disown
      echo ""
      echo "[INFO] Waiting for ngrok to go online..."
      sleep 10
      ps -ef | grep ngrok | grep http | grep "$BFW_PORT" > /dev/null
      if [ "$?" -eq 1 ]; then
        echo "[ERROR] Could not start ngrok client!!! Please fix the issue"
        exit 1
      fi
    fi
    while read line; do
      ngrok_pid=`echo "$line" | grep -Poe "\d+(?=/ngrok)"`
      ngrok_port=`echo "$line" | grep -Poe "(?<=127.0.0.1:)\d+(?=[^\d])"`
      if [ ! -z "$ngrok_pid" ] && [ ! -z "$ngrok_port" ]; then
        ps -ef | grep "$ngrok_pid" | grep "$BFW_PORT" > /dev/null
        if [ "$?" -eq 0 ]; then
          BFW_HOST=`curl -s "localhost:$ngrok_port/inspect/http" | grep "$BFW_PORT" | grep -Poe "https://.*?ngrok.io"`
        fi
      fi
    done < <(netstat -peanut 2>/dev/null | grep LISTEN)
    if [ -z "$BFW_HOST" ]; then
      echo ""
      echo "[ERROR] Could not connect to ngrok!!! Are you connected to the internet?"
      exit 1
    fi
    BFW_UPDATE_ENDPOINT=1
  fi

  if [ "$BFW_UPDATE_ENDPOINT" -eq 1 ] && [ "$BFW_SKIP_UPDATE" -eq 0 ]; then
    echo ""
    echo "[INFO] Updating endpoint..."
    counter=0
    while [ 1 ]; do
      export BFW_UID
      export BFW_PWD
      export BFW_HOST
      export BFW_HND
      phantomjs set_endpoint.js | tee phantom.out
      grep phantom.out -e "Successfully updated bot endpoint" > /dev/null
      if [ "$?" -eq 0 ]; then
        echo "$BFW_HOST" > "last_pushed_host"
        break
      fi
      grep phantom.out -e "Microsoft needs additional information to sign you in" > /dev/null
      if [ "$?" -eq 0 ]; then
        exit 1
      fi
      grep phantom.out -e "Only https addresses are allowed as endpoints" > /dev/null
      if [ "$?" -eq 0 ]; then
        BFW_HOST=
        ASK_QUESTIONS=1
        break
      fi
      grep phantom.out -e "Your account or password is incorrect" > /dev/null
      if [ "$?" -eq 0 ]; then
        BFW_UID=
        BFW_PWD=
        BFW_SAVE_PWD=
        ASK_QUESTIONS=1
        break
      fi
      grep phantom.out -e "No bot with handle" > /dev/null
      if [ "$?" -eq 0 ]; then
        BFW_HND=
        ASK_QUESTIONS=1
        break
      fi
      grep phantom.out -e "Will try again in a second" > /dev/null
      if [ "$?" -eq 0 ]; then
        counter=$(($counter+1))
        if [ "$counter" -gt 1 ]; then
          echo ""
          echo "Seems like connection to Microsoft is repeatedly failing!!!"
          printf "Do you want to skip automatic update of endpoint? This will require you to update endpoint manually as explained in README (y/n) "
          read response
          if [[ "$response" == "y" ]] || [[ "$response" == "Y" ]]; then
            BFW_SKIP_UPDATE=1
            sed s/BFW_SKIP_UPDATE=.*/BFW_SKIP_UPDATE=1/ -i config.sh
            sed s/BFW_UID=.*/BFW_UID=/ -i config.sh
            sed s/BFW_PWD=.*/BFW_PWD=/ -i config.sh
            sed s/BFW_SAVE_PWD=.*/BFW_SAVE_PWD=0/ -i config.sh
            sed s/BFW_HOST=.*/BFW_HOST=/ -i config.sh
            sed s/BFW_HND=.*/BFW_HND=/ -i config.sh
            break
          fi
          counter=0
        fi
        sleep 1
        continue
      fi
      exit 1
    done
  fi
done

if [ "$BFW_SKIP_UPDATE" -eq 1 ]; then
  rm -f "last_pushed_host"
fi
rm -f config.tmp
rm -f phantom.out

cat << EOF > credentials.js
//     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
exports.credentials = {
  appId: '$BFW_APPID',
  appPassword: '$BFW_APPPWD'
}
EOF

node interface.js "$BFW_PORT" "$CC_HOST"
