#!/bin/bash
# This script installs Klipper

set -e
echo "Install klipper with parameter: $*"
echo "Shell: $SHELL"

KLIPPER_NAME="$1"
GIT_TARGET="$2"
INSTALL_VERSION=$3
GIT_URL="$4"
if [ "$GIT_TARGET" = "" ]; then
  echo "No version given, selecting 0.11"
  GIT_TARGET="tags/v0.11.0"
  INSTALL_VERSION="1"
  GIT_URL="https://github.com/Klipper3d/klipper.git"
fi
if [ "${REPETIER_DATA_DIR}" = "" ]; then
  REPETIER_DATA_DIR="/var/lib/Repetier-Server/"
fi

KLIPPER_DIR="klipper"
ROOT_DIR="/opt/${KLIPPER_DIR}"
SOCKET_DIR="/var/lib/${KLIPPER_DIR}/sockets"
SRC_DIR="${ROOT_DIR}/${KLIPPER_NAME}"
PYTHON_DIR="${SRC_DIR}/klippy-env"
PRINTER_CONFIG_DIR="${REPETIER_DATA_DIR}database/klipper"

package_exists() {
  NAME=$1
  R=$(apt-cache search --names-only "^$NAME" | wc -l)
  if [ "$R" -gt "0" ]; then
    echo 1
  else
    echo 0
  fi
}

# Step 1: Install system packages
install_packages() {
  # version 1 tries python 2
  if [ $INSTALL_VERSION -le "1" ]; then
    # Packages for python cffi
    HAS_PYTHON2=$(package_exists python2-dev)
    if [ "$HAS_PYTHON2" == "1" ]; then
      PKGLIST="python2-dev"
    else
      PKGLIST="python-dev"
    fi
    PKGLIST="${PKGLIST} virtualenv libffi-dev build-essential"
    # kconfig requirements
    PKGLIST="${PKGLIST} libncurses-dev"
    # hub-ctrl
    PKGLIST="${PKGLIST} libusb-dev"
    # AVR chip installation and building
    PKGLIST="${PKGLIST} avrdude gcc-avr binutils-avr avr-libc"
    # ARM chip installation and building
    PKGLIST="${PKGLIST} stm32flash dfu-util libnewlib-arm-none-eabi"
    PKGLIST="${PKGLIST} g++ gcc-arm-none-eabi binutils-arm-none-eabi libusb-1.0"
    # Git
    PKGLIST="${PKGLIST} git"
    # Update system package info
    report_status "Running apt-get update"
    apt-get update --allow-releaseinfo-change || apt-get update

    # Install desired packages
    report_status "Installing packages"
    apt-get install --yes ${PKGLIST}
    apt-get --yes --fix-broken install
  fi
  # version 2 tries python 3
  if [ $INSTALL_VERSION -eq "2" ]; then
    # Packages for python cffi
    HAS_PYTHON3=$(package_exists python3-dev)
    if [ "$HAS_PYTHON3" == "1" ]; then
      PKGLIST="python3-dev"
    else
      PKGLIST="python-dev"
    fi
    HAS_PYTHON3_VE=$(package_exists python3-virtualenv)
    if [ "$HAS_PYTHON3_VE" == "1" ]; then
      VIRTENV="virtualenv python3-virtualenv"
    else
      VIRTENV="virtualenv"
    fi
    PKGLIST="${PKGLIST} ${VIRTENV} libffi-dev build-essential"
    # kconfig requirements
    PKGLIST="${PKGLIST} libncurses-dev"
    # hub-ctrl
    PKGLIST="${PKGLIST} libusb-dev"
    # AVR chip installation and building
    PKGLIST="${PKGLIST} avrdude gcc-avr binutils-avr avr-libc"
    # ARM chip installation and building
    PKGLIST="${PKGLIST} stm32flash dfu-util libnewlib-arm-none-eabi"
    PKGLIST="${PKGLIST} g++ gcc-arm-none-eabi binutils-arm-none-eabi libusb-1.0"
    # Git
    PKGLIST="${PKGLIST} git"
    # Update system package info
    report_status "Running apt-get update"
    apt-get update --allow-releaseinfo-change

    # Install desired packages
    report_status "Installing packages"
    apt-get install --yes ${PKGLIST}
    apt-get --yes --fix-broken install
  fi
}

# Step 2: Install startup script
setup_klipper() {
  report_status "Installing Klipper"
  mkdir -p ${ROOT_DIR}
  mkdir -p ${PRINTER_CONFIG_DIR}
  mkdir -p ${SOCKET_DIR}
  git clone ${GIT_URL} ${SRC_DIR}
  cd ${SRC_DIR}
  git checkout ${GIT_TARGET}

  #make menuconfig
  #make
  touch ${PRINTER_CONFIG_DIR}/${KLIPPER_NAME}.cfg
  report_status "Moving File-Ownership to repetierserver"
  chmod 777 ${ROOT_DIR}
  chmod 777 "/var/lib/${KLIPPER_DIR}"
  chmod 777 "${SOCKET_DIR}"
  chown repetierserver ${ROOT_DIR}
  chown -R repetierserver ${SOCKET_DIR}
  chown -R repetierserver ${PRINTER_CONFIG_DIR}
  echo 'OK'
}

# Step 3: Create python virtual environment
create_virtualenv() {
  report_status "Updating python virtual environment"

  # Create virtualenv if it doesn't already exist
  if [ $INSTALL_VERSION -le "1" ]; then
    [ ! -d ${PYTHON_DIR} ] && virtualenv -p python2 ${PYTHON_DIR}
      # Install/update dependencies
      ${PYTHON_DIR}/bin/pip install -r ${SRC_DIR}/scripts/klippy-requirements.txt
  fi
  if [ $INSTALL_VERSION -eq "2" ]; then
    [ ! -d ${PYTHON_DIR} ] && virtualenv -p python3 ${PYTHON_DIR}
      # Install/update dependencies
      ${PYTHON_DIR}/bin/pip3 install -r ${SRC_DIR}/scripts/klippy-requirements.txt
  fi
  chown -R repetierserver ${SRC_DIR}
}

# Step 4: Install startup script
install_script() {
  report_status "Installing system start script"
  cp "${SRC_DIR}/scripts/klipper-start.sh" /etc/init.d/klipper_${KLIPPER_NAME}
}

# Step 5: Install startup script config
install_config() {
  FIND='\[ -r \$DEFAULTS_FILE \] \&\& \. \$DEFAULTS_FILE'
  REPLACE="\# Set Klipper installation made by the Repetier installer script\n"
  REPLACE="${REPLACE}KLIPPY_USER=repetierserver\n"
  REPLACE="${REPLACE}KLIPPY_EXEC=${PYTHON_DIR}/bin/python\n"
  REPLACE="${REPLACE}KLIPPY_ARGS=\"${SRC_DIR}/klippy/klippy.py ${PRINTER_CONFIG_DIR}/${KLIPPER_NAME}.cfg -l /tmp/klippy_${KLIPPER_NAME}.log -I ${SOCKET_DIR}/${KLIPPER_NAME} -a ${SOCKET_DIR}/${KLIPPER_NAME}.api\""
  sed -i "s|$FIND|$REPLACE|g" /etc/init.d/klipper_${KLIPPER_NAME}

  sed -i "s|# Read defaults file||g" /etc/init.d/klipper_${KLIPPER_NAME}
  sed -i "s|NAME=\"klipper\"|NAME=\"klipper_${KLIPPER_NAME}\"|g" /etc/init.d/klipper_${KLIPPER_NAME}
  sed -i "s|DESC=\"klipper daemon\"|DESC=\"klipper_${KLIPPER_NAME} deamon\"|g" /etc/init.d/klipper_${KLIPPER_NAME}
  sed -i "s|DEFAULTS_FILE=/etc/default/klipper||g" /etc/init.d/klipper_${KLIPPER_NAME}
  sed -i "s|PIDFILE=/var/run/klipper.pid|\PIDFILE=/var/run/klipper_${KLIPPER_NAME}.pid|g" /etc/init.d/klipper_${KLIPPER_NAME}
  sed -i "s|rm -f \$PIDFILE|rm -f \$PIDFILE ${SOCKET_DIR}/${KLIPPER_NAME}|g" /etc/init.d/klipper_${KLIPPER_NAME}

  FIND='log_action_msg \"Usage\: \/etc\/init\.d\/klipper {start\|stop\|status\|restart\|reload\|force-reload}\"'
  REPLACE='log_action_msg \"Usage\: \/etc\/init\.d\/klipper_'"${KLIPPER_NAME}"' {start\|stop\|status\|restart\}"'
  sed -i "s|$FIND|$REPLACE|g" /etc/init.d/klipper_${KLIPPER_NAME}
  report_status "Installing system start configuration"
  systemctl daemon-reload
  update-rc.d klipper_${KLIPPER_NAME} defaults
}

# Step 6: Start host software
start_software() {
  report_status "Launching Klipper host software"
  /etc/init.d/klipper_${KLIPPER_NAME} restart
}

# Step 7: Report finished
finish_text() {
  report_status "Installation finished!"
  printf "\n\n##########################\n"
  echo "Please proceed with your installation by compiling the firmware for your printer board next. To do that please go to \"Klipper Configuration\" and click on \"Build Micro-Controller\"."
  printf "\nKlipper Installation Path: ${SRC_DIR}\n"
  echo "Printer configuration: ${PRINTER_CONFIG_DIR}/${KLIPPER_NAME}.cfg"
  echo "Printer socket: ${SOCKET_DIR}/${KLIPPER_NAME}"
  printf "\n############################\n\n\n"
}
# Helper functions
report_status() {
  printf "\n\n###### $1 ######\n\n"
}

# Force script to exit if an error occurs
# set -e

# Find SRCDIR from the pathname of this script

# Run installation steps defined above

if [ "$#" -eq "0" ]; then
  echo 'Please start the script with a printer name!'
  exit 1
fi

install_packages
setup_klipper
create_virtualenv
install_script
install_config
start_software
finish_text
