#!/bin/bash

# Shared utility functions for GitLab CI scripts
# Contains common functions used across multiple release and build scripts

set -e

# Function: Get file size (cross-platform compatible)
function get_file_size(){
    local file="$1"
    if [[ "$OSTYPE" == "darwin"* ]]; then
        # macOS compatibility
        eval `stat -s "$file"`
        local res="$?"
        echo "$st_size"
        return $res
    else
        # Linux/Unix
        stat --printf="%s" "$file"
        return $?
    fi
}

# Function: Calculate SHA256 (cross-platform compatible)
function get_file_sha256(){
    local file="$1"
    if [[ "$OSTYPE" == "darwin"* ]]; then
        # macOS compatibility
        shasum -a 256 "$file" | cut -f 1 -d ' '
    else
        # Linux/Unix
        sha256sum "$file" | cut -d' ' -f1
    fi
}

# Function: Upload file to server
function upload_to_server(){
    local local_file="$1"
    local remote_path="$2"
    local filename=$(basename "$local_file")
    
    echo "Uploading $filename to server..."
    
    # Check for SSH key or password
    if [ -z "$SSH_PRIVATE_KEY" ] && [ -z "$UPLOAD_PASSWORD" ]; then
        echo "Error: SSH_PRIVATE_KEY or UPLOAD_PASSWORD environment variable required"
        return 1
    fi
    
    # Use SSH key
    if [ ! -z "$SSH_PRIVATE_KEY" ]; then
        mkdir -p ~/.ssh
        echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
        chmod 600 ~/.ssh/id_rsa
        ssh-keyscan -H "$UPLOAD_SERVER" >> ~/.ssh/known_hosts 2>/dev/null || true
        
        if scp "$local_file" "$UPLOAD_USER@$UPLOAD_SERVER:$remote_path/$filename"; then
            echo "$filename upload successful"
            return 0
        else
            echo "$filename upload failed"
            return 1
        fi
    fi
    
    # Use password
    if [ ! -z "$UPLOAD_PASSWORD" ]; then
        if command -v sshpass >/dev/null 2>&1; then
            if sshpass -p "$UPLOAD_PASSWORD" scp "$local_file" "$UPLOAD_USER@$UPLOAD_SERVER:$remote_path/$filename"; then
                echo "$filename upload successful"
                return 0
            else
                echo "$filename upload failed"
                return 1
            fi
        else
            echo "Error: sshpass not installed"
            return 1
        fi
    fi
}

# Function: Create package directory and copy core files
function create_package_structure(){
    local pkg_dir="$1"
    local workspace="$2"
    
    mkdir -p "$pkg_dir"
    echo "Copying core files..."
    cp -Rf "$workspace/cores"                   "$pkg_dir/"
    cp -Rf "$workspace/libraries"               "$pkg_dir/"
    cp -Rf "$workspace/variants"                "$pkg_dir/"
    cp -f  "$workspace/boards.txt"              "$pkg_dir/"
    cp -f  "$workspace/package.json"            "$pkg_dir/"
    cp -f  "$workspace/programmers.txt"         "$pkg_dir/"
    cp -Rf "$workspace/tools"                   "$pkg_dir/"
    
    # Clean up unnecessary files
    echo "Cleaning package directory..."
    find "$pkg_dir" -name '*.DS_Store' -exec rm -f {} \; 2>/dev/null || true
    find "$pkg_dir" -name '*.git*' -type f -delete 2>/dev/null || true
    find "$pkg_dir" -name '__pycache__' -type d -exec rm -rf {} \; 2>/dev/null || true
}

# Function: Generate version header
function generate_version_header(){
    local pkg_dir="$1"
    local version="$2"
    local git_hash="$3"
    local build_type="$4"  # "DEV" or "STABLE"
    
    echo "Generating version information..."
    echo "#define ARDUINO_K230_GIT_VER 0x$git_hash" > "$pkg_dir/cores/k230/core_version.h"
    echo "#define ARDUINO_K230_GIT_DESC \"$version\"" >> "$pkg_dir/cores/k230/core_version.h"
    echo "#define ARDUINO_K230_RELEASE \"$version\"" >> "$pkg_dir/cores/k230/core_version.h"
    
    if [ "$build_type" == "DEV" ]; then
        echo "#define ARDUINO_K230_DEV_BUILD 1" >> "$pkg_dir/cores/k230/core_version.h"
    else
        echo "#define ARDUINO_K230_STABLE_BUILD 1" >> "$pkg_dir/cores/k230/core_version.h"
    fi
}

# Function: Update platform.txt version
function update_platform_version(){
    local workspace="$1"
    local pkg_dir="$2"
    local version="$3"
    
    if [ -f "$workspace/platform.txt" ]; then
        sed "s/version=.*/version=$version/g" "$workspace/platform.txt" > "$pkg_dir/platform.txt"
    fi
}

# Function: Update JSON package template with size and checksum
function update_json_template(){
    local template_file="$1"
    local output_file="$2"
    local package_size="$3"
    local package_sha256="$4"
    local package_url="$5"
    local archive_filename="$6"
    local version="$7"
    
    if [ ! -f "$template_file" ]; then
        echo "Error: Template file not found: $template_file"
        return 1
    fi
    
    if ! command -v jq >/dev/null 2>&1; then
        echo "Error: jq not installed"
        return 1
    fi
    
    # Construct JQ argument with package data
    local jq_arg=".packages[0].platforms[0].size = \"$package_size\" |
        .packages[0].platforms[0].checksum = \"SHA-256:$package_sha256\""
    
    # Add optional fields if provided
    if [ ! -z "$package_url" ]; then
        jq_arg="$jq_arg | .packages[0].platforms[0].url = \"$package_url\""
    fi
    
    if [ ! -z "$archive_filename" ]; then
        jq_arg="$jq_arg | .packages[0].platforms[0].archiveFileName = \"$archive_filename\""
    fi
    
    if [ ! -z "$version" ]; then
        jq_arg="$jq_arg | .packages[0].platforms[0].version = \"$version\""
    fi
    
    cat "$template_file" | jq "$jq_arg" > "$output_file"
    return $?
}

# Function: Create simple local package (like release.sh)
function create_local_package(){
    local workspace="$1"
    local output_dir="$2"
    local package_name="${3:-arduino-k230}"
    
    echo "Creating local ZIP package..." >&2
    echo "  Workspace: $workspace" >&2
    echo "  Output dir: $output_dir" >&2
    echo "  Package name: $package_name" >&2
    
    # Check if zip command is available
    if ! command -v zip >/dev/null 2>&1; then
        echo "Error: zip command not found. Please install zip package." >&2
        return 1
    fi
    
    # Validate workspace
    if [ ! -d "$workspace" ]; then
        echo "Error: Workspace directory does not exist: $workspace" >&2
        return 1
    fi
    
    pushd "$workspace" >/dev/null
    
    local zip_file="$package_name.zip"
    
    # Remove old package
    rm -rf "$zip_file"
    
    echo "  Creating ZIP with contents:" >&2
    ls -la | head -10 >&2
    
    # Create ZIP package excluding .git files, build directory, and logs
    echo "  Running: zip -qr $zip_file . -x '.git/*' 'build/*' '*.log'" >&2
    zip -qr "$zip_file" . -x '.git/*' 'build/*' '*.log'
    local zip_result=$?
    
    if [ $zip_result -ne 0 ]; then 
        echo "Error: zip command failed with exit code $zip_result" >&2
        popd >/dev/null
        return 1
    fi
    
    # Check if zip file was created
    if [ ! -f "$zip_file" ]; then
        echo "Error: ZIP file was not created: $zip_file" >&2
        popd >/dev/null
        return 1
    fi
    
    echo "  ZIP file created: $(ls -lh $zip_file)" >&2
    
    # Move to output directory if specified
    if [ ! -z "$output_dir" ] && [ "$output_dir" != "." ]; then
        mkdir -p "$output_dir"
        mv "$zip_file" "$output_dir/"
        zip_file="$output_dir/$zip_file"
    fi
    
    local final_path="$(cd $(dirname $zip_file) && pwd)/$(basename $zip_file)"
    
    popd >/dev/null
    
    echo "Package created successfully: $final_path" >&2
    echo "$final_path"  # Return only the absolute path to stdout
}

# Function: Validate build environment
function validate_build_environment(){
    local workspace="$1"
    
    echo "Validating build environment..."
    if [ ! -d "$workspace/cores" ] || [ ! -d "$workspace/libraries" ]; then
        echo "Error: Missing required core files"
        exit 1
    fi
    echo "Build files validation passed"
}