#!/bin/bash
#
# Welcom to use Bigemap Server
# Copyright(c) 2020 BIGEMAP
#

set -e
help_setup() {
  echo -e "
Once the download command has completed, you will run the setup command.

Usage:

  ./bm-server-installer setup <source> <target> [options]

  <source>        : (required) The directory that contains all the files downloaded 
                    with the download command.
  <target>        : (required)The directory where Bigemap Server will be installed
                    on the host.

Options:

  --config <file>       : (optional) Pass in a JSON configuration file to configure the 
                          Bigemap Server password, port, and hostname.
  --self-signed, -l     : (optional) This will tell the installer to create self-signed 
                          SSL certificates and configure server to run over HTTPS.
                          Cannot be used with --ssl or --http.
  --ssl, -s <path>      : (optional) The path to a directory that contains SSL certificate files
                          1. cert.pem (a certificate file)
                          2. key.pem  (a private key for the certificate)
                          Cannot be used with --http or --self-signed.
  --ssl-key             : (optional) The private key file for the certificate
                          Must be used with --ssl-cert.
  --ssl-cert            : (optional) The certificate file
                          Must be used with --ssl-key.
  --ssl-ca              : (optional) The certificate file.
                          Cannot be used with --http, --ssl or --self-signed.

Example:

  ./bm-server-installer setup bm-server-files/ bm-server/ --config /usr/local/etc/bm-server.json

  ./bm-server-installer setup bm-server-files/ bm-server/ --ssl path/to/certs

Configuration:

  {
    \"Hostname\": \"localhost\",
    \"Port\": 3000,
    \"ServicePort\": 3001,
    \"Password\": \"password\",
    \"TilesetPath\": \"./tilesets\"
  }
"
}

help_settings() {
  echo -e "
If you want to change the config file or the server protocol (HTTP/HTTPS) after you set up Bigemap Server, use the settings command.

Usage:

  ./bm-server-installer settings <target> --config <path to JSON file>

  <target>        : (required)The directory where Bigemap Server will be installed
                    on the host.

Options:

  --config <file>       : (optional) Pass in a JSON configuration file to configure the 
                          Bigemap Server password, port, and hostname.
  --http                : (optional) Configure server to use HTTP. 
                          Cannot be used with --ssl or --self-signed
  --self-signed, -l     : (optional) This will tell the installer to create self-signed 
                          SSL certificates and configure server to run over HTTPS.
                          Cannot be used with --ssl or --http.
  --ssl, -s <path>      : (optional) The path to a directory that contains SSL certificate files
                          1. cert.pem (a certificate file)
                          2. key.pem  (a private key for the certificate)
                          Cannot be used with --http or --self-signed.
  --ssl-key             : (optional) The private key file for the certificate
                          Must be used with --ssl-cert.
  --ssl-cert            : (optional) The certificate file
                          Must be used with --ssl-key.
  --ssl-ca              : (optional) The certificate file.
                          Cannot be used with --http, --ssl or --self-signed.

Example:
  # Stop Bigemap Server
  (cd bm-server && ./bm-server.sh stop)

  # Update the server config
  ./bm-server-installer settings bm-server/ --config path/to/config.json

  # Switch to HTTP
  ./bm-server-installer settings bm-server/ --http

  # Switch to HTTPS (custom certificate)
  ./bm-server-installer settings bm-server/ --ssl path/to/certs
  
  # Switch to HTTPS (self-signed certificate)
  ./bm-server-installer settings bm-server/ --self-signed

  # Start Atlas
  (cd bm-server && ./bm-server.sh start)

Configuration (JSON file):

  {
    \"Hostname\": \"localhost\",
    \"Port\": 3000,
    \"ServicePort\": 3001,
    \"Password\": \"password\",
    \"TilesetPath\": \"./tilesets\"
  }
"
}

setup() {
  if [ ! -n "$1" ]; then
    echo -e "${RED}You must specify the directory that contains all the files downloaded. ${NC}\n"
    help_setup
    exit 1
  fi

  SOURCE=$1

  if [ ! -n "$2" ]; then
    echo -e "${RED}You must specify the directory where Bigemap Server will be installed. ${NC}\n"
    case $SOURCE in
    'settings') help_settings ;;
    *) help_setup ;;
    esac
    exit 1
  fi

  TARGET=$2
  shift 2

  case $SOURCE in
  'settings')
    if [ $# = 0 ]; then
      echo -e "${RED}You does not specify [OPTIONS]. ${NC}\n"
      help_settings
      exit 1
    fi
    USE_HTTP=$(echo $(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'BS_USEHTTP=*[^"]+' || echo '1') | cut -d'=' -f2)
    ;;
  *) USE_HTTP=1 ;;
  esac

  while [ $# != 0 ]; do
    case $1 in
    "--config" | "-c")
      CONF_FILE="$2"
      if [ ! -f $CONF_FILE ]; then
        echo -e "${RED}Error arg for $1: '$CONF_FILE' is incorrect.${NC}"
        exit 1
      fi
      shift 2
      ;;
    "--ssl" | "-s")
      USE_HTTP=0
      CERTS_PATH="$2"
      if [ ! -d $CERTS_PATH ]; then
        echo -e "${RED}Error arg for $1: '$CERTS_PATH' is incorrect.${NC}"
        exit 1
      fi
      shift 2
      ;;
    "--ssl-key")
      USE_HTTP=0
      CERTS_KEY="$2"
      if [ ! -f $CERTS_KEY ]; then
        echo -e "${RED}Error arg for $1: '$CERTS_KEY' is incorrect.${NC}"
        exit 1
      fi
      shift 2
      ;;
    "--ssl-cert")
      USE_HTTP=0
      CERTS_CERT="$2"
      if [ ! -f $CERTS_CERT ]; then
        echo -e "${RED}Error arg for $1: '$CERTS_CERT' is incorrect.${NC}"
        exit 1
      fi
      shift 2
      ;;
    "--ssl-ca")
      USE_HTTP=0
      CERTS_CA="$2"
      if [ ! -f $CERTS_CA ]; then
        echo -e "${RED}Error arg for $1: '$CERTS_CA' is incorrect.${NC}"
        exit 1
      fi
      shift 2
      ;;
    "--self-signed" | "-l")
      USE_HTTP=0
      SELF_SIGNED=1
      shift
      ;;
    "--http")
      USE_HTTP=1
      shift
      ;;
    "--init-auth")
      INIT_BM_AUTH=1
      shift
      ;;
    *)
      echo "Error option $1"
      case $SOURCE in
      'settings') help_settings ;;
      *) help_setup ;;
      esac
      exit 1
      ;;
    esac
  done

  if [[ -n "$CERTS_KEY" && ! -n "$CERTS_CERT" ]] || [[ ! -n "$CERTS_KEY" && -n "$CERTS_CERT" ]]; then
    echo -e "${RED}Both of options --ssl-key, --ssl-cert must be used.${NC}"
    exit 1
  fi

  if [ "$SOURCE" != "settings" ]; then
    if [ ! -n "$(find $SOURCE/docker -name "bm-server-*.tar.gz" | grep -Eo "v([0-9]+\.)+[0-9]+-slim[0-9]?" | sort -V | tail -n 1)" ]; then
      echo -e "${RED}You must run download command first.\nor the source directory is incorrect.${NC}"
      exit 1
    fi
  fi

  HOST="localhost"
  PORT="3000"
  SPORT="3001"
  AUTH_APP_PORT="4388"
  PWD="password"
  TILESET_PATH_DEFAULT="./tilesets"
  TILESET_PATH=$TILESET_PATH_DEFAULT
  if [ -f "$CONF_FILE" ]; then
    HOST=$(cat $CONF_FILE | grep -i 'Hostname' | grep -Eo ':[" ]?*[^"]+' | grep -Eo '[^: "]+' || echo $HOST)
    PORT=$(cat $CONF_FILE | grep -i '"Port"' | grep -Eo ':[" ]?*[^"]+' | grep -Eo '[^: ",]+' || echo $PORT)
    SPORT=$(cat $CONF_FILE | grep -i 'ServicePort' | grep -Eo ':[" ]?*[^"]+' | grep -Eo '[^: ",]+' || echo $SPORT)
    AUTH_APP_PORT=$(cat $CONF_FILE | grep -i 'AuthPort' | grep -Eo ':[" ]?*[^"]+' | grep -Eo '[^: ",]+' || echo $AUTH_APP_PORT)
    PWD=$(cat $CONF_FILE | grep -i 'Password' | grep -Eo ':[" ]?*[^"]+' | grep -Eo '[^: "]+' || echo $PWD)
    TILESET_PATH=$(cat $CONF_FILE | grep -i 'TilesetPath' | grep -Eo ':[" ]?*[^"]+' | grep -Eo '[^: "]+' || echo $TILESET_PATH_DEFAULT)
  elif [ "$SOURCE" = "settings" ]; then
    if [ -f "$TARGET/docker-compose.yml" ]; then
      HOST=$(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'BS_HOST=*[^"]+' | cut -d'=' -f2)
      PORT=$(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'BS_PORT=*[^"]+' | cut -d'=' -f2)
      SPORT=$(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'BS_SPORT=*[^"]+' | cut -d'=' -f2)
      AUTH_APP_PORT=$(echo $(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'BA_PORT=*[^"]+' || echo $AUTH_APP_PORT) | cut -d'=' -f2)
      PWD=$(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'BS_PWD=*[^"]+' | cut -d'=' -f2)
      TILESET_PATH=$(echo $(parse_yaml $TARGET/docker-compose.yml | grep -Eo "[^'\"]+:/usr/local/tilesets" || echo $TILESET_PATH_DEFAULT) | cut -d":" -f1)
    else
      echo -e "${RED}You must run settings command after Bigemap Server installed.${NC}"
      exit 1
    fi
  fi

  VOL_CERTS=""
  mkdir -p "$TARGET" || exit 1
  if [ "$USE_HTTP" = "0" ]; then
    mkdir -p "$TARGET/certs" || exit 1
    if [ "$SELF_SIGNED" = "1" ]; then
      echo '--------------  Create self-signed SSL certificates --------------'
      self_signed $TARGET/certs
      if [ $? -ne 0 ]; then
        echo "----------------- Create self-signed SSL failed! -----------------"
        exit 1
      fi
      echo "---------------- Create self-signed SSL compiled! ----------------"
    elif [ -n $CERTS_PATH ]; then
      cp -f $CERTS_PATH/key.pem $TARGET/certs/key.pem
      cp -f $CERTS_PATH/cert.pem $TARGET/certs/cert.pem
      echo "Copy SSL certificate files compiled!"
    elif [ -n $CERTS_KEY && -n $CERTS_CERT ]; then
      cp -f $CERTS_KEY $TARGET/certs/key.pem
      cp -f $CERTS_CERT $TARGET/certs/cert.pem
      if [ -n $CERTS_CA ]; then
        cp -f $CERTS_CA $TARGET/certs/ca-cert.pem
      fi
    fi
    VOL_CERTS="
      - './certs:/usr/local/certs'"
  fi

  if [ "$SOURCE" != "settings" ]; then
    mkdir -p "$TARGET/.bm-server" || exit 1
    mkdir -p "$TARGET/docker" || exit 1
    if [ "$TILESET_PATH" = "$TILESET_PATH_DEFAULT" ]; then
      mkdir -p "$TARGET/tilesets" || exit 1
    else
      mkdir -p "$TILESET_PATH" || exit 1
    fi

    echo -e "Loading docker images...\n"

    TARGET_VERSION=$(find $SOURCE/docker -name "bm-server-*.tar.gz" | grep -Eo "v([0-9]+\.)+[0-9]+-slim[0-9]?" | sort -V | tail -n 1)
    DOCKER_IMAGE="bm-server-$TARGET_VERSION-$BM_ARCH.tar.gz"

    sudo docker load -i $SOURCE/docker/$DOCKER_IMAGE
    if [ $? -ne 0 ]; then
      echo -e "${RED}Docker load image failed!${NC}"
      exit 1
    fi
    
    mv -f $SOURCE/docker/* $TARGET/docker/

    echo -e "\n$DOCKER_IMAGE load completed."
  else
    TARGET_VERSION=$(parse_yaml $TARGET/docker-compose.yml | grep -Eo 'bigemap/bm-server:[^"]+' | cut -d':' -f2)

    if [ "$INIT_BM_AUTH" = "1" ]; then
      AUTH_APP_VERSION=$(find $TARGET/docker -name "bm-auth-*.tar.gz" | grep -Eo "v([0-9]+\.)+[0-9]+" | sort -V | tail -n 1)
      if [ "$AUTH_APP_VERSION" != "" ]; then
        echo -e "Extract bm-auth files...\n"
        AUTH_APP="bm-auth-$AUTH_APP_VERSION.tar.gz"
        if [ -f "$TARGET/docker/$AUTH_APP" ]; then
          mkdir -p "$TARGET/bm-auth" || exit 1
          tar zxf $TARGET/docker/$AUTH_APP -C $TARGET/bm-auth || exit 1
          VOL_AUTH_APP="
      - './bm-auth:/usr/local/bm-auth'"
          PORTS_AUTH_APP="
      - '$AUTH_APP_PORT:4388'"
          BA_PORT="
      - BA_PORT=$AUTH_APP_PORT"
        fi
      fi
    fi
  fi

  echo "
version: '2'
services:
  bm-server:
    image: bigemap/bm-server:$TARGET_VERSION
    container_name: bm-server
    restart: always
    privileged: true
    volumes:
      - './.bm-server:/usr/local/bm-server'
      - '$TILESET_PATH:/usr/local/tilesets'$VOL_CERTS$VOL_AUTH_APP
    ports:
      - '$PORT:3000'
      - '$SPORT:3001'$PORTS_AUTH_APP
    environment:
      - BS_HOST=$HOST
      - BS_PWD=$PWD
      - BS_PORT=$PORT
      - BS_SPORT=$SPORT$BA_PORT
      - BS_USEHTTP=$USE_HTTP
    devices:
      - '/dev/usb:/dev/usb'
      - '/dev/bus/usb:/dev/bus/usb'
" >$TARGET/docker-compose.yml

  VAR1='$1'
  VAR2='$?'

  case $USE_HTTP in
  1) PROTOCOL='http' ;;
  0) PROTOCOL='https' ;;
  esac

  echo "
#!/bin/bash
#
# Welcom to use Bigemap Server
# Copyright(c) 2019 BIGEMAP
#

start() {
  docker-compose up -d

  if [ $VAR2 -ne 0 ]; then
    exit 1
  fi

  echo '
Bigemap Server running ...

  $PROTOCOL://<your-ip-address>:$PORT
  
Default:

  $PROTOCOL://localhost:$PORT
'
}

stop() {
  docker-compose stop
}

logs() {
  docker-compose logs
}

version() {
  echo \"$TARGET_VERSION\"
}

usage() {
  echo \"
Welcom to use Bigemap Server
For more infomation, please visit http://www.bigemap.com/offlinemaps
Version: $TARGET_VERSION

Usage: ./bm-server [command]

Commands:
  start               Start Bigemap Server
  stop                Stop Bigemap Server
  restart             Restart Bigemap Server
  logs                View Bigemap Server logs

Notes:

  Publish offline map services:
  Copy the directory downloaded by Bigemap into $TARGET/tilesets
  see also http://www.bigemap.com/helps/doc20190104122.html

\"
}

case $VAR1 in
\"start\") start ;;
\"stop\") stop ;;
\"restart\") 
  stop
  start
  ;;
\"logs\") logs ;;
\"version\") version ;;
*) usage ;;
esac
" >$TARGET/bm-server.sh

  chmod +x $TARGET/bm-server.sh
  chmod +x $TARGET/docker-compose.yml

  if [ $SOURCE != "settings" ]; then
    rm -rf $SOURCE

    echo -e "${GREEN}Bigemap Server setup completed.${NC}"
  else
    echo -e "${GREEN}Bigemap Server settings completed.${NC}"
  fi

  echo -e "Now you can run (cd bm-server && ./bm-server.sh start) to start server."
}
