include(processorcount)
INCLUDE(coloroutput)

# Grub
find_program(GRUB_MKRESCUE "grub-mkrescue")
if(NOT GRUB_MKRESCUE)
		message(FATAL_ERROR "grub-mkrescue not found, cannot create bootable iso :(")
endif()

set(STARTUP_SCRIPTS ${PROJECT_BINARY_DIR}/scripts)
file(MAKE_DIRECTORY ${STARTUP_SCRIPTS})

set(PREPARE_ISO ${STARTUP_SCRIPTS}/prepareISO.sh)
set(FAILWRAPPER ${STARTUP_SCRIPTS}/fail.sh)
configure_file(${PROJECT_SOURCE_DIR}/emu/qrun.sh.in    ${STARTUP_SCRIPTS}/qrun.sh)
configure_file(${PROJECT_SOURCE_DIR}/emu/findport.pl   ${STARTUP_SCRIPTS}/findport.pl)
configure_file(${PROJECT_SOURCE_DIR}/emu/prepareISO.sh ${PREPARE_ISO})
configure_file(${PROJECT_SOURCE_DIR}/emu/fail.sh ${FAILWRAPPER} COPYONLY)


macro(ADDEMU TGT)
  # Prepare some useful variable for use in config files
  set(TGT_ELF "${CMAKE_CURRENT_BINARY_DIR}/${TGT}.elf")

  # Start qemu
  add_custom_target(run_${TGT}
    DEPENDS ${TGT_ELF} ${TGT}
    COMMAND echo "Running ${TGT_ELF}..."
    COMMAND ${STARTUP_SCRIPTS}/qrun.sh ${TGT_ELF}
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )

  add_custom_target( ddd_${TGT}
    # Start Qemu in Debug mode.
    DEPENDS ${TGT}
    DEPENDS ${TGT_ELF} ${TGT}
    COMMAND ${STARTUP_SCRIPTS}/qrun.sh ${TGT_ELF} ddd
    COMMENT "Debugging in Qemu"
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )

  add_custom_target( gdb_${TGT}
    # Start Qemu in Debug mode.
    DEPENDS ${TGT}
    DEPENDS ${TGT_ELF} ${TGT}
    COMMAND ${STARTUP_SCRIPTS}/qrun.sh ${TGT_ELF} gdb
    COMMENT "Debugging in Qemu"
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )

  add_custom_target( gdbtui_${TGT}
    # Start Qemu in Debug mode.
    DEPENDS ${TGT}
    DEPENDS ${TGT_ELF} ${TGT}
    COMMAND ${STARTUP_SCRIPTS}/qrun.sh ${TGT_ELF} gdbtui
    COMMENT "Debugging in Qemu"
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )


  add_custom_target( cgdb_${TGT}
    # Start Qemu in Debug mode.
    DEPENDS ${TGT_ELF} ${TGT}
    COMMAND ${STARTUP_SCRIPTS}/qrun.sh ${TGT_ELF} cgdb
    COMMENT "Debugging in Qemu"
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )

  # add legacytargets
  if( NOT TARGET run )
    add_custom_target(run DEPENDS run_${TGT})
    add_custom_target(ddd DEPENDS ddd_${TGT})
    add_custom_target(gdb DEPENDS gdb_${TGT})
    add_custom_target(gdbtui DEPENDS gdbtui_${TGT})
    add_custom_target(cgdb DEPENDS cgdb_${TGT})
  endif()
endmacro(ADDEMU TGT)

macro(ADDFAIL TGT)
  # Prepare some useful variable for use in config files
  set(TGT_ELF "${CMAKE_CURRENT_BINARY_DIR}/${TGT}.elf")
  set(ISODIR_TGT "${PROJECT_BINARY_DIR}/${TGT}")

  set(ISOFILE_TGT "${ISODIR_TGT}/system.iso")
  set(FAILELF_TGT "${ISODIR_TGT}/system.elf")

  set(TGT_RESULT_CSV "${CMAKE_CURRENT_BINARY_DIR}/${TGT}_result.csv")
  set(TGT_RESULT_MEM "${CMAKE_CURRENT_BINARY_DIR}/${TGT}_mem.done")
  set(TGT_RESULT_IP "${CMAKE_CURRENT_BINARY_DIR}/${TGT}_ip.done")
  set(TGT_RESULT_REGS "${CMAKE_CURRENT_BINARY_DIR}/${TGT}_regs.done")

  add_custom_command(
    DEPENDS ${TGT_ELF} ${TGT}
    COMMAND ${CMAKE_COMMAND} -E copy ${TGT_ELF} ${FAILELF_TGT}
    COMMAND ${CMAKE_COMMAND} -E make_directory ${ISODIR_TGT}
    COMMAND ${PREPARE_ISO} ${TGT_ELF} ${ISOFILE_TGT}
    COMMAND objdump -CDS ${TGT_ELF} > ${PROJECT_BINARY_DIR}/${TGT}.dis
    COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/${TGT}.dis ${ISODIR_TGT}/system.dis
    OUTPUT ${ISOFILE_TGT} ${FAILELF_TGT} ${PROJECT_BINARY_DIR}/${TGT}.dis ${ISODIR_TGT}/system.dis
    COMMENT "Generating bootable grub iso."
    )

  # Create bootable ISO
  add_custom_target( iso_${TGT} DEPENDS ${ISOFILE_TGT} )
  add_custom_command(
    DEPENDS ${ISOFILE_TGT} ${FAILELF_TGT}
    COMMAND ${FAILWRAPPER} trace ${ISODIR_TGT} base
    OUTPUT  ${ISODIR_TGT}/trace.pb
    COMMENT "${BoldGreen}[FAIL] Tracing ${ISOFILE_TGT} and import pilots to database${ColourReset}"
    )
  add_custom_target(trace_${TGT} DEPENDS ${ISODIR_TGT}/trace.pb)

  add_custom_command(
    DEPENDS ${ISODIR_TGT}/trace.pb
    COMMAND ${FAILWRAPPER} inject ${ISODIR_TGT} base
    COMMENT "\n${BoldGreen}[FAIL] Injecting bit errors to ${ISOFILE_TGT}\n${BoldGreen}[FAIL] This may take some time${ColourReset}"
    OUTPUT ${TGT_RESULT_CSV}
    )

  add_custom_command(
    DEPENDS ${ISODIR_TGT}/trace.pb
    COMMAND ${FAILWRAPPER} inject_mem ${ISODIR_TGT} base
    COMMAND touch ${TGT_RESULT_MEM}
    COMMENT "\n${BoldGreen}[FAIL] Injecting bit errors to ${ISOFILE_TGT}\n${BoldGreen}[FAIL] This may take some time${ColourReset}"
    OUTPUT ${TGT_RESULT_MEM}
    )

  add_custom_command(
    DEPENDS ${ISODIR_TGT}/trace.pb
    COMMAND ${FAILWRAPPER} inject_ip ${ISODIR_TGT} base
    COMMAND touch ${TGT_RESULT_IP}
    COMMENT "\n${BoldGreen}[FAIL] Injecting bit errors to ${ISOFILE_TGT}\n${BoldGreen}[FAIL] This may take some time${ColourReset}"
    OUTPUT ${TGT_RESULT_IP}
    )

  add_custom_command(
    DEPENDS ${ISODIR_TGT}/trace.pb
    COMMAND ${FAILWRAPPER} inject_regs ${ISODIR_TGT} base
    COMMAND touch ${TGT_RESULT_REGS}
    COMMENT "\n${BoldGreen}[FAIL] Injecting bit errors to ${ISOFILE_TGT}\n${BoldGreen}[FAIL] This may take some time${ColourReset}"
    OUTPUT ${TGT_RESULT_REGS}
    )

  add_custom_target(inject_${TGT}
    DEPENDS ${TGT_RESULT_CSV}
    )
  add_custom_target(inject_mem_${TGT}
    DEPENDS ${TGT_RESULT_MEM}
    )
  add_custom_target(inject_regs_${TGT}
    DEPENDS ${TGT_RESULT_REGS}
    )
  add_custom_target(inject_ip_${TGT}
    DEPENDS ${TGT_RESULT_IP}
    )

  add_custom_target(shortresults_${TGT}
    COMMAND ${FAILWRAPPER} shortresult ${ISODIR_TGT} base
    )

  add_custom_target(resultbrowser_${TGT}
    COMMAND ${FAILWRAPPER} resultbrowser ${ISODIR_TGT} base
    )

  if(NOT TARGET trace)
    add_custom_target(trace         DEPENDS trace_${TGT})
    add_custom_target(inject        DEPENDS inject_${TGT})
    add_custom_target(inject_mem    DEPENDS inject_mem_${TGT})
    add_custom_target(inject_regs   DEPENDS inject_regs_${TGT})
    add_custom_target(inject_ip     DEPENDS inject_ip_${TGT})
    add_custom_target(shortresults  DEPENDS shortresults_${TGT})
    add_custom_target(resultbrowser DEPENDS resultbrowser_${TGT})
  endif()
endmacro(ADDFAIL TGT)