#!/bin/sh

# start mongodb replicas on port 27017, 27018 and 27019
start() {
  echo "Check for active mongod process ..."
  if pgrep mongod > /dev/null
  then
      echo "MongoDB already running"
  else
      echo "Starting MongoDB"
      mongod --config ./data/mongodb/mongod-1.conf --fork
      mongod --config ./data/mongodb/mongod-2.conf --fork
      mongod --config ./data/mongodb/mongod-3.conf --fork
      
      if [[ "$OSTYPE" = "darwin"* ]]; then
        echo  "\nMacOS detected \n"
        echo "... done"
      else
        echo  "\nnot MacOS\n"
        echo "wait 10 sec ..."
        sleep 10
        echo "... done"
      fi
  fi
}

# stop mongodb replicas
stop() {
  echo "Check for active mongod process ..."
  if pgrep mongod > /dev/null
  then
    echo "Stopping MongoDB"
      
    if [[ "$OSTYPE" = "darwin"* ]]; then
      echo "\nmacos detected\n"
      pkill mongo
      sleep 1
    else
      echo  "\nnot MacOS\n"
      mongod --dbpath ./data/mongodb/data-1 --shutdown
      mongod --dbpath ./data/mongodb/data-2 --shutdown
      mongod --dbpath ./data/mongodb/data-3 --shutdown
      sleep 1
    fi
  else
      echo "MongoDB Process not running"
  fi
}

# start mongodb, create folders and replica sets, restart mongodb
setup() {
  echo "stop running mongo db"
  stop
  
  echo "Creating data and log folders ..."
  mkdir data/mongodb
  mkdir data/mongodb/data-1
  mkdir data/mongodb/data-2
  mkdir data/mongodb/data-3
  mkdir data/mongodb/log
  
  echo "\nPlease enter the following Mongo DB connection properties for the setup of a 3 members replica set. Set default (default value) by pressing enter."
  read -p "Enter host name for mongodb access (localhost): " hostname
  if [ -z "$hostname" ]
  then
    hostname="localhost"
  fi
  
  read -p "Enter port of primary replica 0 (27017): " portA
  if [ -n "$portA" ]; then  
    read -p "Enter port of replica 1: " portB
    read -p "Enter port of replica 2: " portC
  else
    portA=27017
    portB=27018
    portC=27019
  fi
  
  echo "Starting mongo db on port $portA"
  mongod --port $portA --dbpath ./data/mongodb/data-1 --logpath ./data/mongodb/log/repl-1.log --fork
  
  read -p "Enter a new root username to enable authentification (leave empty if you don't want to use authentification): " username
  if [ -n "$username" ]; then
    authorization="enabled"
    
    read -p "Enter new password for user $username: " password
    read -p "Repeat password: " passwordRpt
    
    if [ "$password" != "$passwordRpt" ]; then
      echo "passwords do not match. Restart setup to try again."
      exit 1
    fi
    
    read -p "Allow access from remote IPs? y or n (don't allow remote access): " remote_access
    
    echo "Create root user $username"
    
    mongo --port $portA --eval "db.getSiblingDB('admin').createUser({user:'$username',pwd:'$password',roles:['root']})"
    
    # create mongodb keyfile
    echo "create mongo db keyfile ./data/mongodb/mongodb.key"
    openssl rand -base64 741 > ./data/mongodb/mongodb.key
    chmod 600 ./data/mongodb/mongodb.key
    
    echo "Authentification enabled"
  else
    authorization="disabled"
  fi
  
  # create or overwrite mongod config files based on mongod.conf for all replica sets
  if [ "$remote_access" = "y" ] || [ "$remote_access" = "yes" ]; then
    makeConfig "1" $portA "0.0.0.0" $authorization
  else
    makeConfig "1" $portA "127.0.0.1" $authorization
  fi
  
  makeConfig "2" $portB "127.0.0.1" $authorization
  makeConfig "3" $portC "127.0.0.1" $authorization
  
  #stop single mongodb and start replica set with new config files
  mongod --dbpath ./data/mongodb/data-1 --shutdown
  start
  
  # initiate replica sets
  cfg="{
     '_id' : 'adaptor-repl',
     'members' : [
      {
       '_id' : 0,
       'host' : '$hostname:$portA'
      },
      {
       '_id' : 1,
       'host' : '$hostname:$portB'
      },
      {
       '_id' : 2,
       'host' : '$hostname:$portC'
      }
     ]
  }"
  # echo $cfg
  
  if [ -n "$username" ]
  then
    echo "Try creating mongo replica sets on $hostname:$portA, $hostname:$portB and $hostname:$portC with user $username ..."
    mongo --port $portA --username $username --password $password --authenticationDatabase admin --eval "JSON.stringify(db.adminCommand({'replSetInitiate' : $cfg}))"
  else
    echo "Try creating mongo replica sets on $hostname:$portA, $hostname:$portB and $hostname:$portC with authorization disabled ..."
    mongo --port $portA --eval "JSON.stringify(db.adminCommand({'replSetInitiate' : $cfg}))"
  fi
  
  #echo "restart mongo process ..."

  stop
  start
  
  echo "Setup finished"
  echo "Next time you start adaptor append mongodb options to connect to mongodb:"
  if [ "$authorization" = "enabled" ]; then
    echo "node index.js --database mongodb --mongourl 'mongodb://$username:$password@$hostname:$portA/admin?replicaSet=adaptor-repl'"
  else
    echo "node index.js --database mongodb --mongourl 'mongodb://$hostname:$portA/?replicaSet=adaptor-repl'"
  fi
}

# replica set id, port, ip, authorization (enbled/disabled)
makeConfig() {
  echo "write config file ./data/mongodb/mongod-$1.conf setting port to $2, ip to $3 and authorization $4"
  sed "s/port: .*/port: $2/
  s/dbPath: .*/dbPath: .\/data\/mongodb\/data-$1/
  s/bindIp: .*/bindIp: $3/
  s/authorization: .*/authorization: $4/
  s/path: .*/path: .\/data\/mongodb\/log\/repl-$1.log/" <./mongod.conf >./data/mongodb/mongod-$1.conf
  
  sleep 0.2
  
  # add or remove keyFile path
  if [ "$4" = "enabled" ]; then
    sed -e "s/#\? \?keyFile: .*/keyFile: .\/data\/mongodb\/mongodb.key/" -i ./data/mongodb/mongod-$1.conf
  else
    sed -e "s/#\? \?keyFile: .*/# keyFile: .\/data\/mongodb\/mongodb.key/" -i ./data/mongodb/mongod-$1.conf
  fi
}

manual() {
  echo "Please use in one of the following ways: "
  echo "sh mongo.sh setup   <- run once to setup mongo replicas and authorization"
  echo "sh mongo.sh start   <- run whenever you want to start mongodb"
  echo "sh mongo.sh stop    <- run whenever you want to stop mongodb"
}

# decide on function based on provided option
# allow more options: if [ "$#" -ge 1 ]
cmd=""
if [ "$#" -ge 1 ]
then
    cmd=$1
    case $cmd in
        setup)
          setup
          ;;
        start)
          start
          ;;
        stop)
          stop
          ;;
        *)
          echo $cmd "is not a valid option"
          manual
          ;;
    esac
else
    manual
    exit 1
fi
