#!/bin/sh

get_full_path()
{
  echo $1 | grep -q "^/"
  if [ $? -eq 0 ]; then
    echo $1
  else
    echo $2/$1
  fi
}

get_ext_ports()
{
  local TMP=/tmp/minipbx-start
  local CONFIG="$PATH_CONFIGS/configs.tar.gz"
  local DEST="sip_general.conf"
  local TCP_PORT=
  local UDP_PORT=5060

  if [ -f "$CONFIG" ]; then
    rm -rf "$TMP"
    mkdir -p "$TMP"
    tar xf "$CONFIG" -C "$TMP" "$DEST"
    if [ $? -eq 0 ]; then
      UDP_PORT=$(grep "^udpbindport=" "$TMP/$DEST" | cut -d= -f2)
      if [ -z "$UDP_PORT" ]; then
        UDP_PORT=5060
      fi
      grep -q "^tcpenable=yes" "$TMP/$DEST"
      if [ $? -eq 0 ]; then
        TCP_PORT=$(grep "^tcpbindport=" "$TMP/$DEST" | cut -d= -f2)
        if [ -z "$TCP_PORT" ]; then
          TCP_PORT=5060
        fi
      fi
    fi
    rm -rf "$TMP"
  fi

  echo "$TCP_PORT,$UDP_PORT"
}

check_ports()
{
  local PORTS=$(get_ext_ports)
  local ASTERISK_TCP_PORT=$(echo $PORTS | cut -d, -f1)
  local ASTERISK_UDP_PORT=$(echo $PORTS | cut -d, -f2)
  local TCPS="42050 12389 42010 8088 42002 9000 $ASTERISK_TCP_PORT"
  local UDPS="$ASTERISK_UDP_PORT"

  for PORT in $TCPS; do
    if [ "x$PORT" = "x$WEB_PORT" ]; then
      echo "Порт TCP $PORT не доступен для web-панели. Выберите другой."
      return 1
    fi
  done

  TCPS="$TCPS $WEB_PORT"

  for PORT in $TCPS; do
    netstat -ant | grep LISTEN | awk '{print $4}' | grep -q ":${PORT}$"
    if [ $? -eq 0 ]; then
      echo "Порт TCP $PORT занят."
      return 1
    fi
  done

  for PORT in $UDPS; do
    netstat -anu | awk '{print $4}' | grep -q ":${PORT}$"
    if [ $? -eq 0 ]; then
      echo "Порт UDP $PORT занят."
      return 1
    fi
  done

  return 0
}

get_paths()
{
  PATH_MISC=$(get_full_path "$PATH_MISC" "$DIR")
  PATH_LOGS=$(get_full_path "$PATH_LOGS" "$DIR")
  PATH_DB=$(get_full_path "$PATH_DB" "$DIR")
  PATH_CONFIGS=$(get_full_path "$PATH_CONFIGS" "$DIR")
  PATH_SOUNDS=$(get_full_path "$PATH_SOUNDS" "$DIR")
  PATH_KEYS=$(get_full_path "$PATH_KEYS" "$DIR")
  PATH_RECORDS=$(get_full_path "$PATH_RECORDS" "$DIR")
  PATH_REALTIME=$(get_full_path "$PATH_REALTIME" "$DIR")

  if [ -z "$TIMEZONE" ]; then
    TIMEZONE=$(LC_ALL=C timedatectl show 2>/dev/null | grep -i timezone | \
      cut -d= -f2)
    if [ -z "$TIMEZONE" ]; then
      TIMEZONE="Europe/Moscow"
    fi
  fi

  if [ -z "$WEB_PORT" ]; then
    WEB_PORT=80
  fi

  LOG="$PATH_LOGS/startup.log"
}

make_paths()
{
  get_paths

  mkdir -p "$PATH_MISC" "$PATH_LOGS" "$PATH_DB" "$PATH_CONFIGS" \
    "$PATH_SOUNDS" "$PATH_KEYS" "$PATH_RECORDS" "$PATH_REALTIME"

  if [ $? -ne 0 ]; then
    echo "Конфигурация:"
    echo "  misc     : $PATH_MISC"
    echo "  logs     : $PATH_LOGS"
    echo "  db       : $PATH_DB"
    echo "  configs  : $PATH_CONFIGS"
    echo "  sounds   : $PATH_SOUNDS"
    echo "  keys     : $PATH_KEYS"
    echo "  records  : $PATH_RECORDS"
    echo "  realtime : $PATH_REALTIME"
    echo "  timezone : $TIMEZONE"
    echo "Невозможно создать директории."
    return 1
  fi

  cat > "$LOG" << EOF
Конфигурация:
  misc     : $PATH_MISC
  logs     : $PATH_LOGS
  db       : $PATH_DB
  configs  : $PATH_CONFIGS
  sounds   : $PATH_SOUNDS
  keys     : $PATH_KEYS
  records  : $PATH_RECORDS
  realtime : $PATH_REALTIME
  timezone : $TIMEZONE
EOF

  return 0
}

make_startup_config()
{
  if [ ! -z "$DIALOUT" ]; then
    cut -d: -f3 /etc/group | grep -q "^${DIALOUT}$"
    local RES=$?
    local NM=$(echo "$DIALOUT" | grep -o '[[:digit:]]*' | head -1)
    if [ "x$DIALOUT" != "x$NM" -o "x$DIALOUT" = "x0" -o $RES -ne 0 ]; then
      DIALOUT=
    fi
  fi
  if [ -z "$DIALOUT" ]; then
    DIALOUT=$(grep "^dialout:" /etc/group | cut -d: -f3)
  fi
  if [ -z "$DIALOUT" ]; then
    DIALOUT=$(grep "^uucp:" /etc/group | cut -d: -f3)
  fi
  #if [ -z "$DIALOUT" ]; then
  #  GR=$(ls -la /dev/ttyUSB* 2>/dev/null | head -1 | cut -d' ' -f4)
  #  if [ ! -z "$GR" ]; then
  #    DIALOUT=$(grep "^${GR}:" /etc/group | cut -d: -f3)
  #  fi
  #fi

  cat > "$PATH_CONFIGS/startup.conf" << EOF
TIMEZONE=$TIMEZONE
NET_INTERFACE=$NET_INTERFACE
DIALOUT=$DIALOUT
WEB_PORT=$WEB_PORT
EOF

  return 0
}

show_log()
{
  echo
  echo "Невозможно запустить АТС"
  get_paths
  if [ -f "$LOG" ]; then
    if [ ! -z "$1" ]; then
      echo "$1" >> "$LOG"
    fi
    echo "Содержимое лог-файла:"
    echo "---------------------"
    cat "$LOG"
    echo "---------------------"
    echo
    echo "Ошибка при запуске АТС"
  fi

  echo "failed" > "$PSTAT_FILE"
}

systemd_start()
{
  rm -rf "$PSTAT_FILE"

  if [ ! -f "$TARGET/minipbx-ctrl" -o ! -f "$TARGET/minipbx.ver" ]; then
    echo "АТС не установлена."
    echo "failed" > "$PSTAT_FILE"
    return 1
  fi

  make_paths
  if [ $? -ne 0 ]; then
    show_log
    return 1
  fi

  check_ports >> "$LOG" 2>&1
  if [ $? -ne 0 ]; then
    show_log
    return 1
  fi

  make_startup_config >> "$LOG" 2>&1
  if [ $? -ne 0 ]; then
    show_log
    return 1
  fi

  local VERSION=$(cat "$TARGET/minipbx.ver")
  local IMAGE="$IMAGE_ID:$BRANCH-$VERSION"
  local CGROUP_FIX_OPT=

  if [ -z "$CGROUP_FIX" -o "x$CGROUP_FIX_OPT" = "xno" ]; then
    CGROUP_FIX_OPT="-v /sys/fs/cgroup:/sys/fs/cgroup:ro"
  fi

  if [ ! -z "$DEBUG_DONT_PULL" ]; then
    IMAGE="minipbx-pc:$BRANCH"
  fi

  echo "successed" > "$PSTAT_FILE"

  while :; do
    docker run \
      --mount type=tmpfs,destination=/tmp \
      --mount type=tmpfs,destination=/run \
      --mount type=tmpfs,destination=/run/lock \
      --mount type=bind,source="$PATH_LOGS",target=/var/log \
      --mount type=bind,source="$PATH_DB",target=/var/lib/mysql \
      -v "$PATH_RECORDS":/mnt/records \
      -v "$PATH_MISC":/mnt/misc \
      -v "$PATH_KEYS":/mnt/keys \
      -v "$PATH_SOUNDS":/mnt/sounds \
      -v "$PATH_CONFIGS":/mnt/configs \
      -v "$PATH_REALTIME":/mnt/realtime \
      -v /dev:/dev \
      $CGROUP_FIX_OPT \
      --network host \
      --privileged \
      --name minipbx \
      -t \
      --rm \
      "$IMAGE" >> "$LOG" 2>&1
      RES=$?
      if [ ! -f "$PATH_MISC/reboot" ]; then
        break
      else
        rm -rf "$PATH_MISC/reboot"
      fi
  done

  if [ $RES -eq 130 ]; then
    RES=0
  elif [ $RES -ne 0 ]; then
    show_log
  fi
  return $RES
}

systemd_stop()
{
  docker exec minipbx save_all
  docker stop minipbx 2>/dev/null
  return 0
}

run_config()
{
  docker exec -it minipbx config
  return 0
}

get_status()
{
  LC_ALL=C sudo docker ps -a | grep minipbx-pc | grep -i -q up
  if [ $? -eq 0 ]; then
    echo "АТС запущена"
    return 0
  else
    echo "АТС не запущена"
    return 1
  fi
}

services_ctrl_start()
{
  if [ "x$SERVICES_CTRL" = "xsystemd" ]; then
    rm -rf "$PSTAT_FILE"
    systemctl start minipbx
    local i=0
    while [ $i -lt 10 ]; do
      if [ -f "$PSTAT_FILE" ]; then
        break
      fi
      i=$(($i + 1))
      sleep 1
    done
    local OUTPUT=$(cat "$PSTAT_FILE" 2>/dev/null)
    if [ "x$OUTPUT" != "xsuccessed" ]; then
      show_log "Превышено время ожидания (pre)"
    else
      i=0
      while [ $i -lt 30 ]; do
        sleep 1
        get_status >/dev/null
        RES=$?
        if [ $RES -eq 0 ]; then
          break
        fi
        i=$(($i + 1))
      done
      if [ $RES -ne 0 ]; then
        show_log "Превышено время ожидания (docker)"
      fi
    fi
  elif [ "x$SERVICES_CTRL" = "x" -o "x$SERVICES_CTRL" = "xno" ]; then
    systemd_start
    RES=$?
  fi

  return $RES
}

services_ctrl_stop()
{
  if [ "x$SERVICES_CTRL" = "xsystemd" ]; then
    systemctl stop minipbx
  elif [ "x$SERVICES_CTRL" = "x" -o "x$SERVICES_CTRL" = "xno" ]; then
    systemd_stop
  fi

  return $?
}

services_ctrl_restart()
{
  services_ctrl_stop && services_ctrl_start
  return $?
}


if [ "x$(whoami)" != "xroot" ]; then
  echo "Требуются права суперпользователя. Выполните:"
  case "$1" in
    start)
      CMD="minipbx-start"
    ;;
    stop)
      CMD="minipbx-stop"
    ;;
    status)
      CMD="minipbx-status"
    ;;
    restart)
      CMD="minipbx-restart"
    ;;
    *)
      CMD="название_команды"
    ;;
  esac
  echo "  sudo $CMD"
  exit 1
fi

cd $(dirname $0)
DIR=$(pwd)
BRANCH=stable

if [ ! -f /etc/minipbx.cfg ]; then
  echo "Файл конфигурации /etc/minipbx.cfg не найден."
  exit 1
fi

. /etc/minipbx.cfg

IMAGE_ID="cr.yandex/crp9f1mct0nssd2k2cic/minipbx-pc"
PSTAT_FILE="/tmp/minipbx-pstat.txt"

if [ ! -z "$ADD_PATH" ]; then
  export PATH="$PATH:/usr/bin/$ADD_PATH"
else
  export PATH="$PATH:/usr/bin"
fi


case "$1" in
  status)
    get_status
  ;;
  start)
    services_ctrl_start
  ;;
  stop)
    services_ctrl_stop
  ;;
  restart)
    services_ctrl_restart
  ;;
  systemd-start)
    systemd_start
  ;;
  systemd-stop)
    systemd_stop
  ;;
  config)
    run_config
  ;;
  *)
    echo "Не запускайте эту программу напрямую."
    exit 1
  ;;
esac

exit $?
