module beams
  use, intrinsic :: iso_fortran_env
  implicit none
  private

  public :: beam_data_t

  type :: smatrix_t
     private
     complex, dimension(:), allocatable :: value
   contains
     procedure :: write => smatrix_write
  end type smatrix_t

  type :: beam_data_t
     type(smatrix_t), dimension(:), allocatable :: smatrix
   contains
     procedure :: write => beam_data_write
     procedure :: init => beam_data_init
  end type beam_data_t

contains

  subroutine smatrix_write (object, unit)
    class(smatrix_t), intent(in) :: object
    integer, intent(in) :: unit
    integer :: u, i
    u = unit 
    if (allocated (object%value)) then
       if (size (object%value) > 0) then
          do i = 1, 2
             write (u, "(1x,A,'@(')", advance="no") 
          end do
       end if
    else
       write (u, "(1x,A)", advance="no")  
       write (u, "(A)")  "[undefined matrix]"
    end if
  end subroutine smatrix_write
  
  subroutine beam_data_write (beam_data, unit)
    class(beam_data_t), intent(in) :: beam_data
    integer, intent(in) :: unit
    integer :: u
    u = unit
    print *, "output unit = ", u
    write (u, "(1x,A)") "Beam data: [undefined]"    
    call beam_data%smatrix(1)%write (unit = u)          
    call beam_data%smatrix(2)%write (unit = u)
  end subroutine beam_data_write

  subroutine beam_data_init (beam_data, smatrix)
    class(beam_data_t), intent(out) :: beam_data
    type(smatrix_t), dimension(:), intent(in), optional :: smatrix
    integer :: i, unit1
    character(len=32) :: md5sum
    allocate (beam_data%smatrix (2))
    unit1 = 13 
    open (unit = unit1, status = "scratch", action = "readwrite")
    call beam_data%write (unit1)
    rewind (unit1)
    md5sum = md5sum_from_unit (unit1)
    close (unit1)
  end subroutine beam_data_init

  function md5sum_from_unit (u) result (digest)
    integer, intent(in) :: u
    character(len=32) :: digest
    character :: char
    integer :: iostat_foo
    READ_CHARS: do
       read (u, "(A)", advance="no", iostat=iostat_foo)  char
       print *, "char = ", char
       print *, "iostat = ",  iostat_foo
       select case (iostat_foo)
       case (0)
          print *, "character = ", char
       case (iostat_eor)
          print *, "EOR"
       case (iostat_end)
          exit READ_CHARS
       case default
          print *, "ERROR"
          stop
       end select
    end do READ_CHARS
  end function md5sum_from_unit

end module beams

!!!!!

program main
  use beams
  integer :: u 
  u = 12 
  call beams_test (u)

contains
  
  subroutine beams_test (u_log)
    integer, intent(in) :: u_log
    type(beam_data_t), target :: beam_data
    integer :: u_test, u_ref, u_err
    logical :: exist
    character(256) :: buffer1, buffer2
    integer :: iostat1, iostat2
    write (*, "(A)", advance="no")  "Running test: foo"
    write (u_log, "(A)")  "Test: foo"
    u_test = 11
    open (u_test, status="scratch", action="readwrite")
    call beam_data%init ()
    rewind (u_test)
    close (u_test)
    print *, "FINISH"
    stop
  end subroutine beams_test

end program main
