#!/usr/bin/env bash
. ./cmd/env

# From https://stackoverflow.com/a/44660519/702738
compare_version() {
    if [[ $1 == $2 ]]; then
        return 1
    fi
    local IFS=.
    local i a=(${1%%[^0-9.]*}) b=(${2%%[^0-9.]*})
    local arem=${1#${1%%[^0-9.]*}} brem=${2#${2%%[^0-9.]*}}
    for ((i=0; i<${#a[@]} || i<${#b[@]}; i++)); do
        if ((10#${a[i]:-0} < 10#${b[i]:-0})); then
            return 1
            elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
            return 0
        fi
    done
    if [ "$arem" '<' "$brem" ]; then
        return 1
        elif [ "$arem" '>' "$brem" ]; then
        return 0
    fi
    return 1
}


check_images () {
    # TODO: fix me
    test_solr=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$SOLR_IMAGE"`
    test_janus=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$JANUS_IMAGE"`
    test_postgres=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$POSTGRES_IMAGE"`
    test_s3=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$S3_IMAGE"`
    test_clearly`$docker_path images | awk '{print $1 ":" $2 }' | grep "$CLEARLY_IMAGE"`
    test_backend=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$BACKEND_IMAGE"`
    test_nginx=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$NGINX_IMAGE"`
    test_scylla=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$SCYLLA_IMAGE"`
    test_node=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$NODE_IMAGE"`
    test_redis=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$REDIS_IMAGE"`
    
    
    # arm experimental support is on a fixed tag, always pull
    if [ -z "$test_solr" ] || [ -z "$test_janus" ] || [ -z "$test_postgres" ] || [ -z "$test_s3" ] || [ -z "$test_clearly" ] || [ -z "$test_backend" ] || [ -z "$test_nginx" ] || [ -z "$test_scylla" ] || [ -z "$test_node" ] || [ -z "$test_redis" ] || [ $arm = true ]; then
        echo
        warning "WARNING: We are about to start downloading the base images for OSINTBuddy"
        warning "This process may take anywhere between 10 minutes to an hour, depending on your network speed"
        echo
        heading "Please be patient"
        echo
        
        ob_compose pull
    fi
}


install_docker() {
    error "Docker is not installed, you will need to install Docker in order to run the OSINTBuddy Launcher"
    info "      See https://docs.docker.com/installation/"
    exit 1
}


prepare_windows() {
    git_autocrlf=$(git config --get core.autocrlf)
    
    info "Windows Tip: \n\t\t\thttps://tabby.sh/ configured with a git bash profile is recommended for development"
    if [[ ! -z "$git_autocrlf" ]] && [[ "$git_autocrlf" == "true" ]]; then
        warning "Misconfiguration detected! For this project to work you need unix line endings (https://stackoverflow.com/a/13154031).\n\t\t\tTo fix this error try running the following commands:"
        info "      1. cd .. && rm -dr osintbuddy"
        info "      2. git config --global core.autocrlf false"
        info "      3. git clone --depth=1 --recurse-submodules https://github.com/jerlendds/osintbuddy.git"
        info "Windows Tip: https://willi.am/blog/2016/08/11/docker-for-windows-dealing-with-windows-line-endings/"
        abort
    else
        success "Unix line endings detected!"
    fi
}


check_prereqs() {
    node_min_version='18.0.0'
    node_rec_version='18.18.2'
    
    docker_min_version='23.0.0'
    docker_rec_version='24.0.7'
    
    git_min_version='1.8.0'
    git_rec_version='2.34.0'
    
    python_min_version='3.11.0'
    python_rec_version='3.11.4'
    
    # Test git crlf config for windows devices
    if [ $is_windows ]; then
        heading "Windows detected! Checking for environment issues..."
        prepare_windows
    fi

    if [ -z "$docker_path" ]; then
        install_docker
    fi

    # 1. docker daemon running?
    # we send stderr to /dev/null cause we don't care about warnings,
    # it usually complains about swap which does not matter
    test=`"$docker_path" info 2> /dev/null`
    if [[ $? -ne 0 ]] ; then
        error "Cannot connect to the docker daemon - verify it is running and you have access"
        exit 1
    fi
    
    # 2. running recommended docker version
    test=($("$docker_path" --version))  # Get docker version string
    test=${test[2]//,/}  # Get version alone and strip comma if exists

    # At least minimum docker version
    if compare_version "${docker_min_version}" "${test}"; then
        echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
        exit 1
    fi
    
    
    # 3. has node and running recommended node version
    if [ -z "$node" ]; then
        warning "Node environment not detected! We recommend installing Node 18.18.2 for this project."
        warning "Some ./launcher commands may not work without a node environment."
        heading "Attempting to continue without Node..."
    fi
    
    test=($("$node" --version))
    test=${test[0]//v/}  # Get version alone and strip the prefixed v
    
    if compare_version "${node_min_version}" "${test}"; then
        warning "WARNING: Node version ${test} not supported, please upgrade to at least ${node_min_version}, or recommended ${node_rec_version}"
    fi
    
    # Recommend best Node version
    if compare_version "${node_rec_version}" "${test}"; then
        warning "WARNING: Node version ${test} is old and may cause issues, recommend upgrade to ${node_rec_version} or newer."
    fi
    
    # 4. running recommended Python version
    test=($("$python3" --version))
    test=${test[1]///}  # Get version alone and strip the prefixed v
    
    if compare_version "${python_min_version}" "${test}"; then
        warning "WARNING: Python version ${test} not supported, please upgrade to at least ${python_min_version}, or recommended ${python_rec_version}"
    fi
    
    # Recommend best Python version
    if compare_version "${python_rec_version}" "${test}"; then
        warning "WARNING: Python version ${test} is old and may cause issues, recommend upgrade to ${python_rec_version} or newer."
    fi
    
    # TODO:
    # 5. are docker images downloadeded?
    # check_images
    
    arm=false
    case $(uname -m) in
        armv7l)
            error "ERROR: 32bit arm is not supported. Check if your hardware support arm64, which is supported in experimental capacity."
            exit 1
        ;;
        aarch64 | arm64)
            warning "WARNING: Support for aarch64 is experimental at the moment. Please report any problems at https://forum.osintbuddy.com/c/bug-reports/6"
            image=""
            arm=true
        ;;
        x86_64)
            success "x86_64 arch detected."
        ;;
        *)
            error "ERROR: unknown arch detected."
            exit 1
        ;;
    esac
    
    # 4. running recommended git version
    test=($("$git_path" --version))  # Get git version string
    test=${test[2]//,/}  # Get version alone and strip comma if exists
    
    # At least minimum version
    if compare_version "${git_min_version}" "${test}"; then
        warning "ERROR: Git version ${test} not supported, please upgrade to at least ${git_min_version}, or recommended ${git_rec_version}"
        exit 1
    fi
    
    # Recommend best version
    if compare_version "${git_rec_version}" "${test}"; then
        warning "WARNING: Git version ${test} deprecated, recommend upgrade to ${git_rec_version} or newer."
    fi
}


setup_python_env() {
    if [ -d "./venv" ]; then
        warning "Existing venv detected! Skipping python venv setup..."
    else
        cd ..
        git submodule update && \
        $python3 -m venv venv && \
        . ./venv/bin/activate && \
        python3 -m pip install --upgrade pip && \
        python3 -m pip install wheel && \
        python3 -m pip install -r backend/requirements.txt && \
        python3 -m pip install backend/osintbuddy-plugins
    fi
    info "Activate virtual environment:    . ./venv/bin/activate"
    cd "$OB_DIR"
}


setup_ui_env() {
    cd ../frontend/ && yarn && yarn install:hooks
    info "Generate the UI API client with: ./launcher api_gen"
    cd "$OB_DIR"
}


run_bootstrap() {
    trap 'abort' INT
    heading "Checking for prerequisities..."
    check_prereqs
    
    heading "Installing backend dependencies..."
    setup_python_env
    
    heading "Installing UI dependencies.."
    setup_ui_env
    
    heading "Pulling and building containers..."
    ob_compose build
    success "You can now launch OSINTBuddy:   ./launcher start"
}

run_bootstrap
