!>  basis structures for generating test output for testing changes in Adgfem
module test_output_mod

   use define_state
   use dwr_mod
   use mesh_mod
   use paramets

implicit none

   type :: TestingEnvironment_t

      integer :: mesh_size  = 1
      integer :: total_cpu_time = 2
      character(len=20) :: file_name = "test_output.txt"

   contains

      procedure :: writeTestOutputFile

   end type TestingEnvironment_t

contains

   subroutine writeTestOutputFile( this, state, grid)
      class( TestingEnvironment_t ) :: this
      type(solver_state), intent(in) :: state
      type(mesh), intent(in) :: grid
      !type(DWR_t), intent(in), optional :: dwr


      integer :: iFile = 42

      open(iFile, file = this%file_name, action="write", status="replace")
        !!! Mesh adaptation !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        write(iFile,"(a)") "--- Mesh adaptation ---"
        write(iFile,"(a, i8)" ) &
          "Final number of elements:", grid%nelem
        write(iFile,"(a, i8)" ) &
          "Final number of unknowns:", state%nsize
        write(iFile,"(a, i8)" ) &
          "Number of mesh adaptations:", state%space%adapt%adapt_level
        ! TODO:  maximal P, etc. ?
        ! maxval(grid%elem(:)%deg )

        !!! Time dependent !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        write(iFile,"(a)") "--- Time dependent ---"
        write(iFile,"(a, f9.2)") &
          "Tau:", state%time%tau(1)
        write(iFile,"(a, i8)") &
          "Time degree:", state%time%deg
        write(iFile,"(a, i8)") &
          "Time steps (iterations):", state%time%iter
        write(iFile,"(a, f9.2)") &
          "End time:", state%time%ttime ! state%time%FinTime
        write(iFile,"(a, i8)") &
          "Time quadrature Qnum:", state%time%Qnum

        !!! CPU times !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        write(iFile,"(a)") "--- CPU times ---"
        write(iFile,"(a, f9.2)") &
          "Total time:", state%cpuTime%totalTime()
        write(iFile,"(a, f9.2)") &
          "Prepare time:", state%cpuTime%prepare
        write(iFile,"(a, f9.2)") &
          "Solve time:", state%cpuTime%solve
        write(iFile,"(a, f9.2)") &
          "Estimate time:", state%cpuTime%estim
        write(iFile,"(a, f9.2)") &
          "Adapt time:", state%cpuTime%adapt

        !!! Computations !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        write(iFile,"(a)") "--- Computations ---"
        write(iFile,"(a, i8)") &
          "Number of nonlinear iterations:", state%nlSolver%Aiter
        write(iFile,"(a, i8)") &
          "Number of linear iterations:", state%linSolver%iter_tot
        write(iFile,"(a, f9.2)") &
          "DG penalization:", state%space%C_W
        write(iFile,"(a, i8)") &
          "Maximal number of space quadrature integration nodes:", &
          state%space%max_Qdof

        !!! Error estimates !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        write(iFile,"(a)") "--- Error estimates ---"
        ! TODO: space, time, nonlin, lin, quadrature errors
        write(iFile,"(a, f9.2)") &
          "Space L2 error:", state%err(L2)
        write(iFile,"(a, f9.2)") &
          "Space H1 error:", state%err(H1)
        write(iFile,"(a, f9.2)") &
          "Space J_h_sigma error:", state%err(Ejumps)

        ! state%err(CFD_cD)
        ! state%err(CFD_cL)

        if (state%space%estim_space == 'DWR') then
          write(iFile,"(a, f9.2)") &
            "DWR etaI aver:", sqrt( abs(state%estim(dwrEtaI_aver, 1)) )
          write(iFile,"(a, f9.2)") &
            "DWR etaII primal:", sqrt( abs(state%estim(dwrS, 1)) )
          write(iFile,"(a, f9.2)") &
            "DWR etaII dual aver:", sqrt( abs(state%estim(dwr_dualS, 1)) )
          ! TODO algebraic errors

        else
          ! not implemented
        end if

      close(iFile)

      print*, "The output for testing purposes was successfully written to:", &
       this%file_name

  end subroutine writeTestOutputFile



end module test_output_mod
