#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# globle values
INLONG_HOME=$(
  cd $(dirname $0)
  cd ..
  pwd
)
source $INLONG_HOME/conf/inlong.conf

command_help() {
  echo "Usage: ./inlong-daemon (start|stop) <command>
    where command is one of:
    audit               Run a Audit Service
    manager             Run a Manager Service
    dashboard           Run a Dashboard Service
    dataproxy           Run a Dataproxy Service
    agent               Run a Agent Service
    standalone          Run a Standalone mode(All Service)"
}

# wait the service to start
wait_port_to_listen() {
  service_name=$1
  service_port=$2
  result=$(lsof -Pi :${service_port} -sTCP:LISTEN)
  while [[ -z "$result" ]]; do
    echo "waiting $service_name to start, sleep 3s ..."
    sleep 3
    result=$(lsof -Pi :${service_port} -sTCP:LISTEN)
  done
}

# if less than two arguments supplied
if [ $# -lt 2 ]; then
  command_help
  exit 1
fi

COMMAND=$1
SERVICE=$2
init_compo() {
  if [[ "$SERVICE" != standalone ]]; then
    cd $INLONG_HOME/bin
    echo "init $SERVICE"
    bash +x ./init-config.sh $SERVICE
  fi
}

start_inlong_audit() {
  init_compo
  echo "init apache_inlong_audit"
  cd $INLONG_HOME/inlong-audit
  select_db_sql="SELECT COUNT(*) FROM information_schema.TABLES WHERE table_schema = 'apache_inlong_audit'"
  inlong_audit_count=$(mysql --protocol=tcp -h${spring_datasource_hostname} -P${spring_datasource_port} -u${spring_datasource_username} -p${spring_datasource_password} -e "${select_db_sql}")
  inlong_num=$(echo $inlong_audit_count | tr -cd "[0-9]")
  if [ $inlong_num -eq 0 ]; then
    mysql --protocol=tcp -h${spring_datasource_hostname} -P${spring_datasource_port} -u${spring_datasource_username} -p${spring_datasource_password} <sql/apache_inlong_audit.sql
  fi
  echo "start audit proxy"
  if [ "${mq_type}" = "pulsar" ]; then
    bash +x ./bin/proxy-start.sh pulsar
  fi
  if [ "${mq_type}" = "tubemq" ]; then
    bash +x ./bin/proxy-start.sh tube
  fi
  if [ "${mq_type}" = "kafka" ]; then
    bash +x ./bin/proxy-start.sh kafka
  fi
  echo "start audit store"
  bash +x ./bin/store-start.sh
  # wait to start
  wait_port_to_listen audit ${audit_proxys_port}
}

start_inlong_manager() {
  init_compo
  echo "start manager"
  cd $INLONG_HOME/inlong-manager
  # Whether the database table exists. If it does not exist, initialize the database and skip if it exists.
  select_db_sql="SELECT COUNT(*) FROM information_schema.TABLES WHERE table_schema = 'apache_inlong_manager'"
  inlong_manager_count=$(mysql --protocol=tcp -h${spring_datasource_hostname} -P${spring_datasource_port} -u${spring_datasource_username} -p${spring_datasource_password} -e "${select_db_sql}")
  inlong_num=$(echo $inlong_manager_count | tr -cd "[0-9]")
  if [ $inlong_num -eq 0 ]; then
    echo "init apache_inlong_manager database"
    mysql --protocol=tcp -h${spring_datasource_hostname} -P${spring_datasource_port} -u${spring_datasource_username} -p${spring_datasource_password} <sql/apache_inlong_manager.sql
  fi
  bash +x ./bin/startup.sh
  # wait to start
  wait_port_to_listen manager ${manager_server_port}
}

start_inlong_dashboard() {
  echo "start dashboard"
  if [[ "${manager_server_hostname}" = "localhost" || "${manager_server_hostname}" = "127.0.0.1" ]]; then
    manager_server_hostname=$local_ip
  fi
  docker run -d --name dashboard -e MANAGER_API_ADDRESS=${local_ip}:${manager_server_port} -p ${dashboard_mapping_port}:80 ${dashboard_docker_image}
}

start_inlong_dataproxy() {
  init_compo
  echo "start dataproxy"
  cd $INLONG_HOME/inlong-dataproxy
  if [ "${mq_type}" = "pulsar" ]; then
    bash +x ./bin/dataproxy-start.sh pulsar
  fi
  if [ "${mq_type}" = "tubemq" ]; then
    bash +x ./bin/dataproxy-start.sh tubemq
  fi
  if [ "${mq_type}" = "kafka" ]; then
    bash +x ./bin/dataproxy-start.sh kafka
  fi
  # wait to start
  wait_port_to_listen dataproxy ${dataproxy_port}
}

start_inlong_agent() {
  init_compo
  echo "start agent"
  cd $INLONG_HOME/inlong-agent
  bash +x ./bin/agent.sh start
  # wait to start
  wait_port_to_listen agent ${agent_port}
}

# start inlong
start_inlong_all() {
  echo "init configuration"
  cd $INLONG_HOME/bin
  bash +x ./init-config.sh
  # start inlong manager
  start_inlong_manager
  # start inlong audit
  start_inlong_audit
  # start inlong dashboard
  start_inlong_dashboard
  # start inlong dataproxy
  start_inlong_dataproxy
  # start inlong agent
  start_inlong_agent
}

stop_inlong_manager() {
  echo "stop manager"
  cd $INLONG_HOME/inlong-manager/bin
  bash +x ./shutdown.sh
}

stop_inlong_dashboard() {
  docker stop dashboard
  docker rm dashboard
}

stop_inlong_dataproxy() {
  echo "stop dataproxy"
  cd $INLONG_HOME/inlong-dataproxy/bin
  bash +x ./dataproxy-stop.sh
}

stop_inlong_audit() {
  echo "stop audit"
  cd $INLONG_HOME/inlong-audit/bin
  bash +x ./proxy-stop.sh
  bash +x ./store-stop.sh
}

stop_inlong_agent() {
  echo "stop agent"
  cd $INLONG_HOME/inlong-agent/bin
  bash +x ./agent.sh stop
}

# stop inlong
stop_inlong_all() {
  # stop inlong dashboard
  stop_inlong_dashboard
  # stop inlong dataproxy
  stop_inlong_dataproxy
  # stop inlong agent
  stop_inlong_agent
  # stop inlong audit
  stop_inlong_audit
  # stop inlong manager
  stop_inlong_manager
}

if [[ "${COMMAND}" = start || "${COMMAND}" = stop ]]; then
  case $SERVICE in
  manager | dashboard | dataproxy | agent | audit)
    ${COMMAND}_inlong_${SERVICE}
    ;;
  standalone)
    ${COMMAND}_inlong_all
    ;;
  *)
    command_help
    exit 1
    ;;
  esac
else
  command_help
  exit 1
fi
