DEFAULT_UPDATES_SERVER="https://cli-cloud-update.3dprinteros.com"
THIRD_PARTY_PACKAGE_SERVER="https://thirdpartypackages.3dprinteros.com"
DEFAULT_BRANCH=testing
CLIENT_DOWNLOAD_PATH=/tmp/3dprinteros-client.zip
PYTHON=python3
PIP=pip3
DEFAULT_USER_NAME=printeros
SERVICE="3dprinteros"
SERVICE_FILENAME="$SERVICE".service
INSTALL_DIR=$HOME/3dprinteros-client
APPDATA_DIR=$HOME/.3dprinteros
DTOKEN=""

if [ -z $1 ]; then
    BRANCH=$DEFAULT_BRANCH
else
    BRANCH=$1
    echo Installing 3DPrinterOS Client of branch $BRANCH
fi

if [ -z $2 ]; then
    UPDATES_SERVER=$DEFAULT_UPDATES_SERVER
else
    UPDATES_SERVER=$(echo $DEFAULT_UPDATES_SERVER | sed "s/cli-cloud/$2/")
fi

CLIENT_URL_PAYLOAD=$(printf '{"platform": "rpi", "client_version": "0.0.0", "branch": "%s", "build": "git"}' "$BRANCH")

# check if root
if [ "$(id -u)" -ne 0 ]; then
  SUDO=sudo
else
  SUDO=''
fi

SUDO_GROUP='wheel'

unpack_client_code() {
    mkdir -p $INSTALL_DIR || true
    echo Unpacking to: $INSTALL_DIR
    $PYTHON -m zipfile -e $CLIENT_DOWNLOAD_PATH $INSTALL_DIR
    rm $CLIENT_DOWNLOAD_PATH
}

default_installation() {
    echo "Running default installation... "
    if [ -e /usr/bin/apt-get ]; then
        echo "Installing dependencies using apt-get..."
        echo "Please type sudo password"
        $SUDO sed -i -E 's/(#\s*)(deb-src)/\2/' /etc/apt/sources.list
        $SUDO apt-get update
        $SUDO apt-get upgrade
        $SUDO apt-get install curl python3-requests python3-serial python3-usb python3-aiohttp python3-pampy python3-pip net-tools
        #$SUDO apt-get install python3-opencv
        $SUDO pip install opencv-python numpy --break-system-packages
        SUDO_GROUP='sudo'
    elif [ -e /usr/bin/pacman ]; then
        echo "Installing dependencies using pacman..."
        echo "Please type sudo password"
        $SUDO pacman -S curl python-requests python-pyserial python-pyusb python-opencv python-aiohttp net-tools
        PYTHON=python
        PIP=pip
    elif [ -e /usr/bin/zypper ]; then # OpenSUSE
        echo "Installing dependencies using zypper..."
        echo "Please type sudo password"
        $SUDO zypper install curl python3-requests python3-pyserial python3-usb python3-opencv python3-aiohttp net-tools
        PYTHON=python3
        PIP=pip
    elif [ -e /usr/bin/dnf ]; then # Fedora
        echo "Installing dependencies using dnf..."
        echo "Please type sudo password"
        $SUDO dnf install curl python3-requests python3-pyserial python3-pyusb python3-opencv python3-aiohttp net-tools
        PYTHON=python3
        PIP=pip
    elif [ -e /usr/bin/yum ]; then # CentOS
        echo "Installing dependencies using yum..."
        echo "Please type sudo password"
        $SUDO yum install curl python3-requests python3-pyserial python3-pyusb python3-opencv python3-aiohttp net-tools
        PYTHON=python3
        PIP=pip
    else
        echo "Installing python packages using pip to ~/.local folder"
        $PIP --user install requests pyserial pyusb aiohttp opencv-python numpy
        if [ $? -eq 1 ]; then
            $PIP --break-system-packages install requests pyserial pyusb aiohttp opencv-python numpy
        fi
    fi
    echo $CLIENT_URL_PAYLOAD
    CLIENT_DOWNLOAD_URL=$(curl -sS -H "Content-Type: application/json" -d "$CLIENT_URL_PAYLOAD" $UPDATES_SERVER)
    echo Downloading: $CLIENT_DOWNLOAD_URL
    curl -L $CLIENT_DOWNLOAD_URL -o $CLIENT_DOWNLOAD_PATH
    unpack_client_code
    echo Adding the user to groups to access printer ports and etc
    $SUDO usermod -a -G $SUDO_GROUP $USER
    $SUDO usermod -a -G uucp,video $USER
    $SUDO usermod -a -G dialout $USER || true
    $SUDO usermod -a -G gpio $USER || true
    echo 'SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664", GROUP='$SUDO_GROUP | $SUDO tee /etc/udev/rules.d/99-pyusb.rules
    # echo -e 'SUBSYSTEM=="meson-gpiomem", KERNEL=="gpiomem", GROUP="gpio", MODE="0660"\nSUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio", MODE="0660"\nSUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c \'chown -R root:gpio /sys/class/gpio && chmod -R 660 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 660 /sys/devices/virtual/gpio; chown -R root:gpio /sys/devices/platform/soc/*.gpio/gpio && chmod -R 660 /sys/devices/platform/soc/*.gpio/gpio; chown -R root:gpio /sys/devices/platform/pinctrl/*.gpio/gpio && chmod -R 660 /sys/devices/platform/pinctrl/*.gpio/gpio; chown root:gpio /dev/gpiochip* && chmod 660 /dev/gpiochip*\'"\nSUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c \'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport /dev/gpiochip* ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport\'"\nSUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c \'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value\'"' | sudo tee /etc/udev/rules.d/98-gpio.rules

    if [ ! -f "${INSTALL_DIR}"/$SERVICE_FILENAME ]; then
        curl -L https://builds.3dprinteros.com/3dprinteros.service -o $INSTALL_DIR/3dprinteros.service
    fi
    echo Creating customizing and enabling service
    if [ -e /usr/local/bin/systemctl ] || [ -e /usr/bin/systemctl ]; then
        if [ "$USER" = "$DEFAULT_USER_NAME" ]; then
            SERVICE_FILE_PATH="${INSTALL_DIR}"/$SERVICE_FILENAME
        else
            $SUDO mkdir -p /opt/3dprinteros || true
            SERVICE_FILE_PATH=/opt/3dprinteros/$SERVICE_FILENAME
            $SUDO cp "${INSTALL_DIR}"/$SERVICE_FILENAME $SERVICE_FILE_PATH
            if [ "$USER" = "root" ]; then
                    $SUDO sed -i "s/home\/printeros/root/" $SERVICE_FILE_PATH || true
                else
                    $SUDO sed -i "s/printeros/${USER}/" $SERVICE_FILE_PATH || true
            fi
            #$SUDO sed -i "s/python\s/${PYTHON}\s/" $SERVICE_FILE_PATH || true
        fi
        $SUDO systemctl link $(realpath "${SERVICE_FILE_PATH}")
        $SUDO systemctl enable $SERVICE
        $SUDO systemctl start $SERVICE
        echo -e "3DPrinterOS client service is enabled - it will start automatically with your OS.\nIf you don't want this, please execute: systemctl disable $SERVICE."
    elif [ -e /usr/local/bin/update-rc.d ] || [ -e /usr/bin/update-rc.d ]; then
        $SUDO cp $INSTALL_DIR/3dprinteros.init.d /etc/init.d/3dprinteros
        if [ "$USER" = "root" ]; then
            $SUDO sed -i "s/home\/printeros/root/" /etc/init.d/3dprinteros || true
        else
            $SUDO sed -i "s/home\/printeros/home\/${USER}/" /etc/init.d/3dprinteros || true
        fi
        #sudo sed -i "s/python/${PYTHON}/" /etc/init.d/3dprinteros || true
        $SUDO update-rc.d 3dprinteros start
        $SUDO update-rc.d 3dprinteros defaults
        echo -e "3DPrinterOS client service is enabled - it will start automatically with your OS.\nIf you don't want this, please execute: update-rc.d -f 3dprinteros remove. That will remove the service completely. So after this to run 3DPrinterOS Client you will have to navigate to ~/3dprinteros-client and run $PYTHON launcher.py"
    fi
}

download_file_via_python() {
    local url="$1"
    local path="$2"
    $PYTHON - <<EOF
import requests
import sys
url = '$url'
path = '$path'
chunk_size = 8192
try:
    with requests.get(url, stream=True) as response:
        response.raise_for_status()
        with open(path, 'wb') as file:
            for chunk in response.iter_content(chunk_size):
                if chunk:
                    file.write(chunk)
except Exception as e:
    print(e)
    sys.exit(1)
EOF
}

creality_mips_installation() {
    echo "Running Creality (K1 Series, Ender-3V3KE) specific installation..."
    SUDO=''
    CLIENT_DOWNLOAD_PATH=/usr/data/3dprinteros-client.zip
    INSTALL_DIR=/usr/data/3dprinteros-client
    PYTHON_LIB_INSTALL_DIR=/usr/lib/python3.8/site-packages
    AIOHTTP_URL=$THIRD_PARTY_PACKAGE_SERVER/mips32/python3.8/aiohttp-mips.zip
    AIOHTTP_ZIP_TMP=/usr/data/aiohttp-mips.zip
    APPDATA_DIR=/usr/data/.3dprinteros
    
    echo 'Checking if moonraker service is installed'
    moonraker_service=$(find /etc/init.d/ -maxdepth 1 -type f | grep -E 'S([0-9]|[0-9][0-9])moonraker_service$')
    if [ -z "$moonraker_service" ]; then
        echo "Moonraker not detected! Please install it before using 3DPrinterOS"
        read -p "Install the moonraker? [Y/n]: " user_input
        case "$user_input" in
            [Yy]* | "" )
                git clone https://github.com/3DPrinterOS-SDK/Creality-Helper-Script.git /usr/data/helper-script
                echo -e "1\n1\ny\nq\n" | /usr/data/helper-script/helper.sh
                ;;
            [Nn]* )
                echo "Moonraker installation aborted by user."
                ;;
            * )
                echo "Invalid input. Moonraker installation aborted."
                ;;
        esac
    fi
    
    MOONRAKER_ENV_PATH=/usr/data/moonraker/moonraker-env
    if [ -d $MOONRAKER_ENV_PATH ]; then
        PYTHON_LIB_INSTALL_DIR=$MOONRAKER_ENV_PATH/lib/python3.8/site-packages
        PYTHON=$MOONRAKER_ENV_PATH/bin/python3
        PIP="$PYTHON -m pip"
        echo $PIP
    fi
    
    PYTHON_VERSION=$($PYTHON --version 2>&1)
    # Check if Python 3.8 is installed
    if [ "$PYTHON_VERSION" != "${PYTHON_VERSION/Python 3.8/}" ]; then
        echo "Python 3.8 detected."
    else
        echo "Python 3.8 is not installed. Exiting."
        exit 1
    fi

    # use python version to download file on K1 becuase system wget and curl not supports SSL 
    $PIP install requests
    echo "Installing aiohttp from $THIRD_PARTY_PACKAGE_SERVER"
    download_file_via_python "$AIOHTTP_URL" "$AIOHTTP_ZIP_TMP"
    #wget --no-check-certificate "$AIOHTTP_URL" -o "$AIOHTTP_ZIP_TMP"

    if [ $? -ne 0 ]; then
        echo "Failed to download aiohttp lib."
        exit 1
    fi
    echo "$PYTHON -m zipfile -e $AIOHTTP_ZIP_TMP $PYTHON_LIB_INSTALL_DIR"
    $PYTHON -m zipfile -e $AIOHTTP_ZIP_TMP $PYTHON_LIB_INSTALL_DIR
    if [ $? -ne 0 ]; then
        echo "Failed to extract aiohttp lib."
        exit 1
    fi
    
    rm $AIOHTTP_ZIP_TMP

    echo "Installing python packages using pip"
    $PIP install pyserial pyusb pam multidict attr yarl asyncio async-timeout attrs frozenlist aiosignal PyDispatcher
    if [ $? -eq 1 ]; then
        echo "Installing python packages failed. Exiting."
    fi
    
    #sed -i "s/python3\/printeros/root/" $SERVICE_FILE_PATH || true

    # Use python to send the POST request and capture the response
    CLIENT_DOWNLOAD_URL=$($PYTHON -c "import sys, json, requests; branch=sys.argv[1]; url=sys.argv[2]; payload=json.dumps({'platform': 'rpi', 'client_version': '0.0.0', 'branch': branch, 'build': 'git'}); headers={'Content-Type': 'application/json'}; response=requests.post(url, data=payload, headers=headers); print(response.text)" "$BRANCH" "$UPDATES_SERVER")
    download_file_via_python "$CLIENT_DOWNLOAD_URL" "$CLIENT_DOWNLOAD_PATH"
    if [ $? -ne 0 ]; then
        echo "Failed to download 3DPrinterOS Client."
        exit 1
    fi
    
    unpack_client_code

    echo Creating, customizing and enabling service
    FORCED_SETTINGS_JSON=$INSTALL_DIR/forced_settings.json
    cp $INSTALL_DIR/default_settings.json $FORCED_SETTINGS_JSON 
  
    jq '.active_detectors.KlipperDetector = false |
        .active_detectors.LocalMoonrakerDetector = true |
        .active_detectors.USBDetector = false |
        .local_moonraker.always_on = true |
        .web_interface.port_https = 0 |
        .custom_settings_home = "/usr/data" |
        .camera.default = "MJPGS camera" |
        .camera.snap_cam_url = "http://127.0.0.1:8080/?action=snapshot" |
        .camera.switch_type = false' "$FORCED_SETTINGS_JSON" > "$FORCED_SETTINGS_JSON.tmp" && mv "$FORCED_SETTINGS_JSON.tmp" "$FORCED_SETTINGS_JSON"

    # K1 Firmware doesn't have update-rc. Installing manually
    sed -i "s|python3|${PYTHON}|g" $INSTALL_DIR/S99printeros
    cp $INSTALL_DIR/S99printeros /etc/init.d/S99printeros
    if [ $? -ne 0 ]; then
        echo "Failed to copy S99printeros"
        exit 1
    fi
    chmod +x /etc/init.d/S99printeros

    if [ -n "$DTOKEN" ]; then
        echo "Detected DTOKEN; Downloading stuff.bin to $APPDATA_DIR"
        mkdir -p $APPDATA_DIR
        STUFF_PATH=$APPDATA_DIR/stuff.bin
        STUFF_URL="https://cloud.3dprinteros.com/noauth/download_auth_file?remove_token=1&dtoken=$DTOKEN"
        download_file_via_python "$STUFF_URL" "$STUFF_PATH"
        if [ $? -ne 0 ]; then
            echo "Failed to download stuff.bin"
            exit 1
        fi
    fi

    echo -e "3DPrinterOS client service is enabled - it will start automatically with your OS.\nIf you don't want this, please remove /etc/init.d/S99printeros. That will remove the service completely. So after this to run 3DPrinterOS Client you will have to navigate to /usr/data/3dprinteros-client and run $PYTHON launcher.py"
    sh /etc/init.d/S99printeros start
}

default_installation_confirmation() {
    read -p "Proceed with default installation? [Y/n]: " user_input
    case "$user_input" in
        [Yy]* | "" )
            default_installation
            finalize_installation
            ;;
        [Nn]* )
            echo "Installation aborted by user"
            ;;
        * )
            echo "Invalid input"
            default_installation_confirmation
            ;;
    esac
}

creality_mips_installation_confirmation() {
    if [[ $? -eq 0 ]]; then
        read -p "Detected Creality (K1 Series, Ender-3V3KE) . Do you want to proceed with the specific Creality (K1 Series, Ender-3V3KE) installation? [Y/n]: " user_input
        case "$user_input" in
            [Yy]* | "" )
                creality_mips_installation
                finalize_installation
                ;;
            [Nn]* )
                echo "Installation aborted"
                exit 0
                ;;
            * )
                echo "Invalid input"
                creality_mips_installation_confirmation
                ;;
        esac
    fi
}

autoselect_installation_type() {
    CFG_FILE="/usr/data/printer_data/config/printer.cfg"
    if [ -e "$CFG_FILE" ]; then
        machine_name=$(head -n 1 "$CFG_FILE")
        if [ "$machine_name" != "${machine_name/K1-MAX/}" ] || [ "$machine_name" != "${machine_name/K1/}" ] || [ "$machine_name" != "${machine_name/Ender-3V3KE/}" ]; then
            creality_mips_installation_confirmation
        else
            default_installation_confirmation
        fi
    else
        default_installation_confirmation
    fi
}

finalize_installation() {    
    if [ -z "$DTOKEN" ]; then
        echo "Log-in with 3DPrinterOS account:"
        cd $INSTALL_DIR
        $PYTHON console_login.py
        if [ $? -eq 0 ]; then
            echo "Login success. 3DPrinterOS Client is ready."    
            echo "Web interface is running on ports 8008 and 8443"
        else
            echo "Login failed. You can retry with by typing: $PYTHON $INSTALL_DIR/console_login.py"    
        fi
    fi    
    echo "Installation complete"
    
}

echo
echo "======= You are about to install 3DPrinterOS Client ======="
echo
autoselect_installation_type
