#!/bin/bash

OCCA_DIR=$(cd $(dirname "$0")/.. && pwd)
EXAMPLE_DIR="${OCCA_DIR}/examples"

export ASAN_OPTIONS
ASAN_OPTIONS+=':protect_shadow_gap=0'
ASAN_OPTIONS+=':detect_container_overflow=0'

HEADER_CHARS=80

export LD_LIBRARY_PATH="${OCCA_DIR}/lib:${LD_LIBRARY_PATH}"
export DYLD_LIBRARY_PATH="${OCCA_DIR}/lib:${DYLD_LIBRARY_PATH}"

# Set default to running the C++ and C examples only
CPP_EXAMPLES=${CPP_EXAMPLES:-1}
C_EXAMPLES=${C_EXAMPLES:-1}
FORTRAN_EXAMPLES=${FORTRAN_EXAMPLES:-0}

declare -a examples=()
if [[ $CPP_EXAMPLES -eq 1 ]]; then
  examples+=(
    cpp/01_add_vectors
    cpp/02_for_loops
    cpp/03_arrays
    cpp/04_generic_inline_kernel
    cpp/05_custom_types
    cpp/06_shared_memory
    cpp/07_streams
    cpp/09_native_cpp_kernels
    cpp/10_native_c_kernels
    cpp/11_native_cuda_kernels
    cpp/12_native_opencl_kernels
    )
fi
if [[ $C_EXAMPLES -eq 1 ]]; then
  examples+=(
    c/01_add_vectors
    c/02_background_device
    c/03_generic_inline_kernel
    c/04_reduction
  )
fi
if [[ $FORTRAN_EXAMPLES -eq 1 ]]; then
  examples+=(
    fortran/01_add_vectors
    fortran/03_static_compilation
    fortran/04_reduction
    fortran/09_streams
  )
fi

failed_examples=""
for mode in $("${OCCA_DIR}/bin/occa" modes); do
    case "${mode}" in
        Serial) device="{mode: 'Serial'}";;
        OpenMP) device="{mode: 'OpenMP'}";;
        CUDA)   device="{mode: 'CUDA', device_id: 0}";;
        HIP)    device="{mode: 'HIP', device_id: 0}";;
        OpenCL) device="{mode: 'OpenCL', platform_id: 0, device_id: 0}";;
        Metal)  device="{mode: 'Metal', device_id: 0}";;
        dpcpp) device="{mode: 'dpcpp', platform_id: 0, device_id: 0}";;
    esac

    for example_dir in "${examples[@]}"; do
        flags=(--verbose --device "${device}")

        # Filters
        case "${example_dir}" in

            cpp/02_for_loops)
                if [[ "${mode}" == OpenCL ]]; then
                    continue
                fi;;
            cpp/03_arrays)
                if [[ "${mode}" == OpenCL ]]; then
                    continue
                fi;;
            cpp/04_generic_inline_kernel)
                if [[ "${mode}" == OpenCL ]]; then
                    continue
                fi;;
            cpp/05_custom_types)
                if [[ "${mode}" == OpenCL ]]; then
                    continue
                fi;;
            cpp/06_shared_memory)
                if [[ "${mode}" == OpenCL ]]; then
                    continue
                fi;;
            cpp/09_native_cpp_kernels)
                if [[ "${mode}" != Serial ]]; then
                    continue
                fi
                flags=(--verbose)
                ;;
            cpp/10_native_c_kernels)
                if [[ "${mode}" != Serial ]]; then
                    continue
                fi
                flags=(--verbose)
                ;;
            cpp/11_native_cuda_kernels)
                if [[ "${mode}" != CUDA ]]; then
                    continue
                fi
                flags=(--verbose)
                ;;
            cpp/12_native_opencl_kernels)
                if [[ "${mode}" != OpenCL ]]; then
                    continue
                fi
                flags=(--verbose)
                ;;
            c/04_reduction)
                if [[ "${mode}" == OpenCL ]]; then
                    continue
                fi;;
            fortran/09_streams)
                if [[ "${mode}" != Serial ]]; then
                    continue
                fi
                flags=(--verbose)
                ;;
        esac

        banner="(${mode}) ${example_dir}"
        chars=$(echo "${banner}" | wc -c)
        linechars=$((${HEADER_CHARS} - ${chars} - 6))
        line=$(printf '%*s' ${linechars} | tr ' ' '-')
        echo -e "\n---[ ${banner} ]${line}"

        cd "${EXAMPLE_DIR}/${example_dir}"
        make clean; make

        ./main "${flags[@]}"

        # Check for example failures
        if [ $? -ne 0 ]; then
            failed_examples+="  - ${mode}: ${example_dir}\n"
        fi

        # Test output footer
        printf '%*s\n' ${HEADER_CHARS} | tr ' ' '='
    done
done

if [[ "${failed_examples}" != "" ]]; then
    echo -e "\n\nFailed examples:"
    echo -e "${failed_examples}"
    exit 1
fi
