#!/bin/bash

process_user_config() {
    while IFS= read -r line; do
        [[ -z $line ]] && continue

        # Check if the line starts with nvtool and execute it using eval
        if [[ ${line:0:7} = "nvtool " ]]; then
            eval "$line"
        else
            # Remove spaces only from the beginning of the line
            line=$(echo "$line" | sed 's/^[[:space:]]*//')
            
            # Extract parameter and value using sed
            param=$(echo "$line" | sed -E 's/^"?([^"]*)"?\s*:.*/\1/')
            value=$(echo "$line" | sed -E 's/^"?[^"]*"?\s*:\s*//')

            # Store username for pool address construction
            if [[ "$param" == "username" ]]; then
                USERNAME=$value
                continue
            fi

            # Convert parameter to lowercase for cpuOnly check
            param_low=$(echo "$param" | tr '[:upper:]' '[:lower:]')

            # Check for CPU only mode
            if [[ "$param_low" == "cpuonly" && ("$value" == "true" || "$value" == "\"true\"" || "$value" == "yes" || "$value" == "\"yes\"") ]]; then
                CPU_ONLY=true
                continue
            fi

            # Store amountOfThreads parameter
            if [[ "$param" == "amountOfThreads" ]]; then
                AMOUNT_OF_THREADS=$value
                continue
            fi

            # Store trainer configuration
            if [[ "$param" == "trainer" ]]; then
                TRAINER_CONFIG=$line
                continue
            fi
            
            # Handle XMR settings
            if [[ "$param" == "xmrMining" ]]; then
                if [[ "$value" == "true" || "$value" == "\"true\"" ]]; then
                    XMR_MINING=true
                else
                    XMR_MINING=false
                fi
                continue
            fi
            
            if [[ "$param" == "xmrGpu" ]]; then
                if [[ "$value" == "true" || "$value" == "\"true\"" ]]; then
                    XMR_GPU=true
                else
                    XMR_GPU=false
                fi
                continue
            fi
            
            if [[ "$param" == "xmrPool" ]]; then
                XMR_POOL=$value
                continue
            fi
            
            if [[ "$param" == "xmrCustom" ]]; then
                XMR_CUSTOM=$value
                continue
            fi

            # Convert parameter to uppercase for other processing
            param_high=$(echo "$param" | tr '[:lower:]' '[:upper:]')

            # Perform replacements in the parameter
            modified_param=$(echo "$param_high" | sed '
                s/QUBICADDRESS/qubicAddress/g;
                s/CPUTHREADS/cpuThreads/g;
                s/ACCESSTOKEN/accessToken/g;
                s/ALLOWHWINFOCOLLECT/allowHwInfoCollect/g;
                s/HUGEPAGES/hugePages/g;
                s/ALIAS/alias/g;
                s/OVERWRITES/overwrites/g;
                s/IDLESETTINGS/Idling/g;
                s/PPS=/\"pps\": /g;
                s/USELIVECONNECTION/useLiveConnection/g;
                s/TRAINER/trainer/g;
            ')

            # Use modified parameter if changes were made
            [[ "$param" != "$modified_param" ]] && param=$modified_param

            # General processing for other parameters
            if [[ ! -z "$value" ]]; then
                if [[ "$param" == "overwrites" ]]; then
                    Settings=$(jq -s '.[0] * .[1]' <<< "$Settings {$line}")
                elif [[ "$param" == "Idling" ]]; then
                    Settings=$(jq --argjson Idling "$value" '
                        .Idling = $Idling | 
                        .Idling.preCommand = ($Idling.preCommand // null) |
                        .Idling.preCommandArguments = ($Idling.preCommandArguments // null) |
                        .Idling.command = ($Idling.command // null) |
                        .Idling.arguments = ($Idling.arguments // null) |
                        .Idling.postCommand = ($Idling.postCommand // null) |
                        .Idling.postCommandArguments = ($Idling.postCommandArguments // null)
                    ' <<< "$Settings")
                elif [[ "$param" == "pps" || "$param" == "useLiveConnection" ]]; then
                    if [[ "$value" == "true" || "$value" == "false" ]]; then
                        Settings=$(jq --argjson value "$value" '.[$param] = $value' <<< "$Settings")
                    else
                        echo "Invalid value for $param: $value. It must be 'true' or 'false'. Skipping this entry."
                    fi
                else
                    if [[ "$param" == "trainer.cpuThreads" ]]; then
                        Settings=$(jq --arg value "$value" '.trainer.cpuThreads = ($value | tonumber)' <<< "$Settings")
                    elif [[ "$param" == "trainer.gpu" ]]; then
                        Settings=$(jq --argjson value "$value" '.trainer.gpu = $value' <<< "$Settings")
                    elif [[ "$value" == "null" ]]; then
                        Settings=$(jq --arg param "$param" '.[$param] = null' <<< "$Settings")
                    elif [[ "$value" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
                        Settings=$(jq --arg param "$param" --argjson value "$value" '.[$param] = ($value | tonumber)' <<< "$Settings")
                    else
                        Settings=$(jq --arg param "$param" --arg value "$value" '.[$param] = $value' <<< "$Settings")
                    fi
                fi
            fi
        fi
    done <<< "$CUSTOM_USER_CONFIG"
}

# Main script logic

# Always check for updates first
LOCAL_FILE="/hive/miners/custom/downloads/QLAB.XM-latest.tar.gz"
REMOTE_FILE_URL="https://poolsolution.s3.eu-west-2.amazonaws.com/QLAB.XM-latest.tar.gz"
REMOTE_HASH_URL="https://poolsolution.s3.eu-west-2.amazonaws.com/QLAB.XM.tar.gz/QLAB.XM-latest.hash"

# Check the availability of the remote hash
if curl --output /dev/null --silent --head --fail "$REMOTE_HASH_URL"; then
    # Download the remote hash
    REMOTE_HASH=$(curl -s -L "$REMOTE_HASH_URL")

    # Calculate the SHA256 hash of the local file
    LOCAL_HASH=$(sha256sum "$LOCAL_FILE" | awk '{print $1}')

    # Compare the hashes
    if [ "$LOCAL_HASH" != "$REMOTE_HASH" ]; then
        echo "Hashes of local and remote ($REMOTE_FILE_URL) miners are different. Downloading new update!"
        # Remove old local miner and restart the miner
        rm "$LOCAL_FILE"
        echo "Miner restarting in 10 sec..."
        screen -d -m miner restart
    fi
fi

# Process global settings
GlobalSettings=$(jq -r '.ClientSettings' "/hive/miners/custom/$CUSTOM_NAME/appsettings_global.json" | envsubst)

# Initialize Settings
Settings="$GlobalSettings"

# Delete old settings
eval "rm -rf /hive/miners/custom/$CUSTOM_NAME/appsettings.json"

# Extract worker name from CUSTOM_TEMPLATE
if [[ ! -z $CUSTOM_TEMPLATE ]]; then
    Settings=$(jq --arg alias "$CUSTOM_TEMPLATE" '.alias = $alias' <<< "$Settings")
fi

# Process user configuration
[[ ! -z $CUSTOM_USER_CONFIG ]] && process_user_config

# Set pool address using username from config
if [[ ! -z "$USERNAME" ]]; then
    if [[ ! -z $CUSTOM_URL ]]; then
        if [[ "$CUSTOM_URL" == *"pps-cn"* ]]; then
            # Set PPS mode to true and use the CN endpoint
            Settings=$(jq --arg ipps true '.pps = $ipps' <<< "$Settings")
            Settings=$(jq --arg pool "wss://pps-cn.minerlab.io/ws/$USERNAME" '.poolAddress = $pool' <<< "$Settings")
        elif [[ "$CUSTOM_URL" == *"solo-cn"* ]]; then
            # Set PPS mode to false and use the CN SOLO endpoint
            Settings=$(jq --arg ipps false '.pps = $ipps' <<< "$Settings")
            Settings=$(jq --arg pool "wss://solo-cn.minerlab.io/ws/$USERNAME" '.poolAddress = $pool' <<< "$Settings")
        elif [[ "$CUSTOM_URL" == *"pps"* ]]; then
            # Set PPS mode to true for global endpoint
            Settings=$(jq --arg ipps true '.pps = $ipps' <<< "$Settings")
            Settings=$(jq --arg pool "wss://pps.minerlab.io/ws/$USERNAME" '.poolAddress = $pool' <<< "$Settings")
        elif [[ "$CUSTOM_URL" == *"wps"* ]]; then
            # Set PPS mode to false for global WPS
            Settings=$(jq --arg ipps false '.pps = $ipps' <<< "$Settings")
            Settings=$(jq --arg pool "wss://wps.minerlab.io/ws/$USERNAME" '.poolAddress = $pool' <<< "$Settings")
        fi
    fi
fi

# Configure hugePages
if [[ $(jq '.hugePages' <<< "$Settings") != null ]]; then
    hugePages=$(jq -r '.hugePages' <<< "$Settings")
    if [[ ! -z $hugePages && $hugePages -gt 0 ]]; then
        eval "sysctl -w vm.nr_hugepages=$hugePages"
    fi
fi

# Store existing trainer settings
if [[ ! -z "$TRAINER_CONFIG" ]]; then
    EXISTING_TRAINER=$(jq -r '.trainer' <<< "$Settings")
fi

# Remove cpuOnly from settings
Settings=$(jq 'del(.cpuOnly)' <<< "$Settings")

# Configure CPU/GPU settings
if [[ "$CPU_ONLY" == "true" ]]; then
    if [[ ! -z "$AMOUNT_OF_THREADS" ]]; then
        Settings=$(jq --arg threads "$AMOUNT_OF_THREADS" '
            .trainer.cpu = true | 
            .trainer.gpu = false |
            .trainer.cpuThreads = ($threads | tonumber)
        ' <<< "$Settings")
    else
        Settings=$(jq '.trainer.cpu = true | .trainer.gpu = false' <<< "$Settings")
    fi
elif [[ ! -z "$AMOUNT_OF_THREADS" ]]; then
    Settings=$(jq --arg threads "$AMOUNT_OF_THREADS" '
        .trainer.cpu = true |
        .trainer.gpu = true |
        .trainer.cpuThreads = ($threads | tonumber)
    ' <<< "$Settings")
else
    Settings=$(jq '.trainer.cpu = false | .trainer.gpu = true' <<< "$Settings")
fi

# Apply trainer configuration
if [[ ! -z "$TRAINER_CONFIG" ]]; then
    Settings=$(jq -s '.[0] * .[1]' <<< "$Settings {$TRAINER_CONFIG}")
fi

# Update idling settings if username and CUSTOM_TEMPLATE are available
if [[ "$CUSTOM_PASS" == *"aleo"* ]]; then
    if [[ ! -z "$USERNAME" && ! -z "$CUSTOM_TEMPLATE" ]]; then
        Settings=$(jq --arg username "ml$USERNAME" --arg worker "$CUSTOM_TEMPLATE" '
            .idling = {
                "command": "aleominer",
                "arguments": "-u stratum+ssl://aleo.minerlab.io:6688 -w \($username).\($worker)"
            }
        ' <<< "$Settings")
    fi
fi

if [[ "$CUSTOM_PASS" == *"xel"* ]]; then
    if [[ ! -z "$USERNAME" && ! -z "$CUSTOM_TEMPLATE" ]]; then
        Settings=$(jq --arg username "ml$USERNAME" --arg worker "$CUSTOM_TEMPLATE" '
            .idling = {
                "command": "rigel",
                "arguments": "-a xelishashv2 -o stratum+ssl://xelis-pool.minerlab.io:3333 -u '$CUSTOM_PASS' -w \($worker) --api-bind 0.0.0.0:5000"
            }
        ' <<< "$Settings")
    fi
fi

if [[ "$CUSTOM_PASS" == *"xmr"* ]]; then
    if [[ ! -z "$USERNAME" && ! -z "$CUSTOM_TEMPLATE" ]]; then
        Settings=$(jq --arg username "ml$USERNAME" --arg worker "$CUSTOM_TEMPLATE" '
            .idling = {
                "command": "xmrig-qlab",
                "arguments": "-o qxmr.minerlab.io:3333 -u ${CUSTOM_PASS}.${worker} -a rx/0 --rig-id minerlab"
            }
        ' <<< "$Settings")
    fi
fi

if [[ "$CUSTOM_PASS" == *"quai:"* ]]; then
    if [[ ! -z "$CUSTOM_PASS" && ! -z "$CUSTOM_TEMPLATE" ]]; then
        CUSTOM_PASS=$(echo "$CUSTOM_PASS" | cut -d':' -f2-)
        Settings=$(jq --arg username "ml$USERNAME" --arg worker "$CUSTOM_TEMPLATE" '
            .idling = {
                "command": "rigel",
                "arguments": "-a quai -o stratum+tcp://quai-pool.minerlab.io:3333 -u '$CUSTOM_PASS' -w \($worker) --api-bind 0.0.0.0:5000"
            }
        ' <<< "$Settings")
    fi
fi

# Apply XMR settings if provided
if [[ ! -z "$XMR_MINING" || ! -z "$XMR_GPU" || ! -z "$XMR_POOL" || ! -z "$XMR_CUSTOM" ]]; then
    # Create or update xmrSettings object
    if [[ $(jq '.xmrSettings' <<< "$Settings") == "null" ]]; then
        Settings=$(jq '. += {"xmrSettings": {}}' <<< "$Settings")
    fi
    
    # Apply XMR mining status
    if [[ ! -z "$XMR_MINING" ]]; then
        if [[ "$XMR_MINING" == "true" ]]; then
            Settings=$(jq '.xmrSettings.disable = false' <<< "$Settings")
        else
            Settings=$(jq '.xmrSettings.disable = true' <<< "$Settings")
        fi
    fi
    
    # Apply XMR GPU setting
    if [[ ! -z "$XMR_GPU" ]]; then
        if [[ "$XMR_GPU" == "true" ]]; then
            Settings=$(jq '.xmrSettings.enableGpu = true' <<< "$Settings")
        else
            Settings=$(jq '.xmrSettings.enableGpu = false' <<< "$Settings")
        fi
    fi
    
    # Apply XMR pool address if provided
    if [[ ! -z "$XMR_POOL" ]]; then
        # Remove quotes if present
        XMR_POOL=$(echo "$XMR_POOL" | sed 's/^"//;s/"$//')
        Settings=$(jq --arg pool "$XMR_POOL" '.xmrSettings.poolAddress = $pool' <<< "$Settings")
    fi
    
    # Apply XMR custom parameters if provided
    if [[ ! -z "$XMR_CUSTOM" ]]; then
        # Remove quotes if present
        XMR_CUSTOM=$(echo "$XMR_CUSTOM" | sed 's/^"//;s/"$//')
        Settings=$(jq --arg custom "$XMR_CUSTOM" '.xmrSettings.customParameters = $custom' <<< "$Settings")
    fi
fi

# Create final settings file
echo "{\"ClientSettings\":$Settings}" | jq . > "/hive/miners/custom/$CUSTOM_NAME/appsettings.json"

echo "Settings created successfully."