!#########################################################################
!		
!    Copyright (C) 2003-2012 Department of Physics and Astronomy,
!                            University of Rochester,
!                            Rochester, NY
!
!    io_control.f90 is part of AstroBEAR.
!
!    AstroBEAR is free software: you can redistribute it and/or modify	  
!    it under the terms of the GNU General Public License as published by 
!    the Free Software Foundation, either version 3 of the License, or    
!    (at your option) any later version.
!
!    AstroBEAR is distributed in the hope that it will be useful, 
!    but WITHOUT ANY WARRANTY; without even the implied warranty of
!    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!    GNU General Public License for more details.
!
!    You should have received a copy of the GNU General Public License
!    along with AstroBEAR.  If not, see <http://www.gnu.org/licenses/>.
!
!#########################################################################
!> @dir io
!! @brief Contains modules for managing input and output

!> @defgroup IO Input/Output
!! @brief Contains modules for managing input and output

!> @file io_control.f90
!! @brief Main file for module IOControl

!> @defgroup IOControl IO Control
!! @brief Provides a format-agnostic interface for AstroBEAR to read and write data files.
!! @ingroup IO

!> Provides a format-agnostic interface for AstroBEAR to read and write data files.
!! @ingroup IOControl
!! @author Brandon D. Shroyer
!! @date 7-13-2010
MODULE IOControl

    USE GlobalDeclarations
#if defined _MPI
    USE CommunicationDeclarations
#endif
    USE IODeclarations
#if defined _HDF5
    USE HDF5Declarations
    USE IOChombo
#endif
    USE IOOkc
    USE IOCurve
    USE IOBOV
    USE DataDeclarations
    USE Timing
    IMPLICIT NONE
    PRIVATE

!    INCLUDE 'mpif.h'

    PUBLIC IOInit, WriteDataFrame, IORestartInit, IORestartFinalize, IOReloadLevel, IOClose, PostIO
    
    SAVE
CONTAINS

   SUBROUTINE PostIO(frame)
      INTEGER :: frame
      CHARACTER(21) :: syscmd
      LOGICAL :: ex
      IF (MPI_ID == 0) THEN
         Inquire(file="postprocess.s", exist=ex)
         IF (ex) THEN
            write(syscmd,'(A16,I5.5)') './postprocess.s ', frame
            CALL System(syscmd)
         END IF
      END IF
   END SUBROUTINE PostIO
   
    !> Reads in any generic IO data contained in the io.data file.
    SUBROUTINE IOInit

        ! Read in scheme value.
!        READ(GLOBAL_DATA_HANDLE,NML=IOData,IOStat=iErr)
        
!        IF(iErr/=0) THEN
!           PRINT *, "IOInit() error:  unable to read ", GLOBAL_DATA_FILE, "."
!           STOP
!        END IF

!        iDataFileType=IO_CHOMBO

        SELECT CASE (iDataFileType)
            CASE (IO_CHOMBO)
#if defined _HDF5
               CALL HDF5Init()
#else
               CALL Abort('Cannot store data files in chombo format without HDF5 support')
#endif
               t_io_cumulative = 0.d0
               
            CASE (IO_CURVE)
               IF (MaxLevel /= 0 .OR. nDim > 1) THEN
                  PRINT *, "Warning - curve files only allowed for 1D fixed grid"
                  STOP
               END IF
            CASE (IO_BOV)
!               PRINT *, "WriteDataFrame() error:  BOV output format not yet implemented."
!               STOP
                
            CASE DEFAULT
                PRINT "('WriteDataFrame() error: invalid data file output ', i2, '.')", iDataFileType
                STOP

        END SELECT
        
    END SUBROUTINE IOInit

    !> Closes any remaining files and releases any remaining I/O resources.
    SUBROUTINE IOClose

        SELECT CASE (iDataFileType)
            CASE (IO_CHOMBO)
#if defined _HDF5              
               CALL HDF5Finalize()
#else
               CALL ABORT('Cannot store data files in chombo format without HDF5 support')
#endif
            CASE (IO_CURVE)
               
            CASE (IO_BOV)
 !               PRINT *, "IOClose() error:  BOV output format not yet implemented."
 !               STOP
                
            CASE DEFAULT
                PRINT "('IOClose() error: invalid data file output ', i2, '.')", iDataFileType
                STOP

        END SELECT

    END SUBROUTINE IOClose
    
    !> Writes a data frame
    !! @param nframe the sequence number of the frame to be written.
    SUBROUTINE WriteDataFrame(nframe, text_opt)

#if defined _HDF5
      USE ChomboDeclarations, ONLY: CHOMBO_DOMAIN_LEVEL
#endif
      INTEGER :: nframe

       INTEGER :: finest_level
       CHARACTER(LEN=*), OPTIONAL :: text_opt


      IF (MPI_ID == 0) t_io_start = MPI_Wtime()
      FinestLevel = GetFinestLevel()
      CALL StartTimer(iWriteData, -2)


      IF (MPI_ID == 0) t_io_start = MPI_Wtime()

      ! The iDataFileType variable is read in from the GlobalData namelist.
      SELECT CASE (iDataFileType)

      CASE (IO_CHOMBO)
#if defined _HDF5
         !                finest_level = GetFinestLevel()
         finest_level = MaxLevel


            ! Write the chombo file (timing the process).

            IF (PRESENT(text_opt)) THEN
               CALL MakeChomboFile(nframe, text_opt)
            ELSE
               CALL MakeChomboFile(nframe,'')
            END IF
  
            IF (MPI_id == Master) THEN
               IF (.not. lRegrid) CALL MakeOKCFile(nframe)                
          END IF

#else
         CALL ABORT('Cannot store data in chombo format without HDF5 support')
#endif
      CASE (IO_CURVE)
         CALL WriteCurveFile(nFrame)
      CASE (IO_BOV)

         CALL IOWriteBOVFrame(nframe)
!         PRINT *, "WriteDataFrame() error:  BOV output format not yet implemented."
!         STOP

      CASE DEFAULT
         PRINT "('WriteDataFrame() error: invalid data file output ', i2, '.')", iDataFileType
         STOP

      END SELECT

      ! print statistics on how much time is spent writing output.
      IF (MPI_id == Master) THEN
         t_io_end=MPI_WTime()           
         t_io_cumulative=t_io_end-t_io_start
         PRINT "('Time to make output file ', i4, ': ', f8.4, ' seconds.')", nframe,  t_io_end - t_io_start
         !          PRINT "('Cumulative output file time: ', f11.4, ' seconds.')", t_io_cumulative
      END IF

      !Erica's fix for ticket 339:      
      IF (MPI_id == 0) THEN 
         OPEN(UNIT=FRAME_DATA_HANDLE, FILE=FRAME_DATA_FILE)
         WRITE(FRAME_DATA_HANDLE, *) '&FrameData'
         WRITE(FRAME_DATA_HANDLE, *) 'last_printed_frame =', nframe
         WRITE(FRAME_DATA_HANDLE, *) '/ '
         CLOSE(FRAME_DATA_HANDLE)
      END IF
       
      !Convert the mass the mass flux in totals.dat to unit of solar mass& solar mass per year
      
      IF (lJetClump .AND. lSolarMassTotal) THEN
        CALL convertTotalsData()
      END IF

      CALL StopTimer(iWriteData, -2)


    END SUBROUTINE WriteDataFrame

    !> Uses the contents of the frame restart_frame to reconstruct a simulation.
    !! @param nframe The frame being used to restart the problem.
    SUBROUTINE IORestartInit(nframe)

        INTEGER :: nframe



        IF (MPI_id == Master) t_io_start=MPI_WTIME()

        ! The iDataFileType variable is read in from the GlobalData namelist.
        SELECT CASE (iDataFileType)
            CASE (IO_CHOMBO)
#if defined _HDF5
                CALL ChomboRestartInit(nframe)
#else
                CALL ABORT('Cannot restart from chombo file without HDF5 support')
#endif
            CASE (IO_BOV)
                PRINT *, "IORestartInit() error:  BOV restarts not yet implemented."
                STOP
                
            CASE DEFAULT
                PRINT "('IORestartInit() error: invalid data file output ', i2, '.')", iDataFileType
                STOP
                
        END SELECT

     END SUBROUTINE IORestartInit



    !> Uses the contents of the frame restart_frame to reconstruct a simulation.
    !! @param nframe The frame being used to restart the problem.
     SUBROUTINE IORestartFinalize(nframe)

        INTEGER :: nframe

        ! The iDataFileType variable is read in from the GlobalData namelist.
        SELECT CASE (iDataFileType)
            CASE (IO_CHOMBO)
#if defined _HDF5
                CALL ChomboRestartFinalize(nframe)
#else
                CALL ABORT('Cannot restart from chombo file without HDF5 support')
#endif

            CASE (IO_BOV)
                PRINT *, "IORestartFinalize() error:  BOV output format not yet implemented."
                STOP
                
            CASE DEFAULT
                PRINT "('IORestartFinalize() error: invalid data file output ', i2, '.')", iDataFileType
                STOP
                
        END SELECT

      ! print statistics on how much time is spent restarting.
      IF (MPI_id == 0) THEN
          t_io_end=MPI_WTime()           
          t_io_cumulative=t_io_end-t_io_start
          PRINT "('Time to restart from output file ', i4, ': ', f8.4, ' seconds.')", restart_frame,  t_io_end - t_io_start
!          PRINT "('Cumulative output file time: ', f8.4, ' seconds.')", t_io_cumulative          
       END IF

     END SUBROUTINE IORestartFinalize

    !> Uses the contents of the frame restart_frame to reconstruct a simulation.
    !! @param nframe The frame being used to restart the problem.
     SUBROUTINE IOReloadLevel(n)

        INTEGER :: n

        ! The iDataFileType variable is read in from the GlobalData namelist.
        SELECT CASE (iDataFileType)
            CASE (IO_CHOMBO)
#if defined _HDF5
                CALL ReadLevel(n)
#else
                CALL ABORT('Cannot restart from chombo file without HDF5 support')
#endif

            CASE (IO_BOV)
                PRINT *, "ReLoadLevel() error:  BOV output format not yet implemented."
                STOP
                
            CASE DEFAULT
                PRINT "('ReLoadLevel() error: invalid data file output ', i2, '.')", iDataFileType
                STOP
                
        END SELECT


     END SUBROUTINE IOReloadLevel

     
   SUBROUTINE convertTotalsData()
       INTEGER :: i, n, io, iErr
       REAL(KIND=qPREC) :: ct_time, ct_rho, ct_px, ct_py, ct_pz
       IF (MPI_id == 0) THEN
           open(134,file='out/totals.dat',iostat=io,status='old')

           open(135,file='out/totals_JetClump.dat',status='old', iostat=iErr)
           if (iErr /=0) then
             open(135,file='out/totals_JetClump.dat',status='new', iostat=iErr)
             if (iErr/=0) then
                print*, 'Error - cannot open files as old or new'
                stop
              end if
           end if
           
           write(135,'(A10,4A22,/)',advance='no') 'Time(yr)', 'Mass(solarMass)','Px(solarMass*km/s','Py(solarMass*km/s)','Pz(solarMass*km/s)'
           read(134,*)

           read(134,*,iostat=io) ct_time, ct_rho, ct_px, ct_py, ct_pz
           do while (io .eq. 0)
              ct_time=ct_time*timeScale/yr
              ct_rho=ct_rho*mScale/mSolar
              ct_px=ct_px*mScale*velScale/mSolar/1E5
              ct_py=ct_py*mScale*velScale/mSolar/1E5
              ct_pz=ct_pz*mScale*velScale/mSolar/1E5
              write(135,'(5E20.11)') ct_time, ct_rho, ct_px, ct_py, ct_pz
              read(134,*,iostat=io) ct_time, ct_rho, ct_px, ct_py, ct_pz
           end do
           close(134)
           close(135)
       END IF
     END SUBROUTINE convertTotalsData 

END MODULE IOControl

