! Module  : photint_m
! Purpose : Define photint_t abstract type, for representing photometric
!           intensity
!
! Copyright 2021-2022 Rich Townsend & The MSG Team
!
! This file is part of MSG. MSG 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, version 3.
!
! MSG 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 this program.  If not, see <http://www.gnu.org/licenses/>.

#:include 'forum.inc'

module photint_m

   ! No implicit typing

   implicit none

   ! Derived-type definitions

   type, abstract :: photint_t
   contains
      private
      procedure(get_precise), deferred, public :: get_precise
      procedure(get_ssize), deferred, public   :: get_ssize
      #:for name in ('intensity', 'E_moment', 'D_moment', 'flux')
         procedure(interp_${name}$), deferred, public :: interp_${name}$
      #:endfor
      procedure(read), deferred, public  :: read
      procedure(write), deferred, public :: write
   end type photint_t

   ! Interfaces

   abstract interface

      #:for name, type in (('precise', 'logical'), &
                           ('ssize', 'integer(ID)'))

         subroutine get_${name}$(self, ${name}$)
            use forum_m
            import photint_t
            class(photint_t), intent(in) :: self
            ${type}$, intent(out)        :: ${name}$
         end subroutine get_${name}$
      
      #:endfor

      #:for name, arg_var, arg_type in (('intensity', 'mu', 'real(RD)'), &
                                        ('E_moment', 'k', 'integer'), &
                                        ('D_moment', 'l', 'integer'))

         subroutine interp_${name}$(self, ${arg_var}$, res, stat)
            use forum_m
            import photint_t
            class(photint_t), intent(in)   :: self
            ${arg_type}$, intent(in)       :: ${arg_var}$
            real(RD), intent(out)          :: res
            integer, intent(out), optional :: stat
         end subroutine interp_${name}$

      #:endfor
      
      #:for name, var in (('flux', 'F'),)

         subroutine interp_${name}$(self, res, stat)
            use forum_m
            import photint_t
            class(photint_t), intent(in)   :: self
            real(RD), intent(out)          :: res
            integer, intent(out), optional :: stat
         end subroutine interp_${name}$

      #:endfor

      subroutine read(self, hdf5io, stat)
         use forum_m
         import photint_t
         class(photint_t), intent(out)  :: self
         type(hdf5io_t), intent(inout)  :: hdf5io
         integer, intent(out), optional :: stat
      end subroutine read
         
      subroutine write(self, hdf5io, stat)
         use forum_m
         import photint_t
         class(photint_t), intent(in)   :: self
         type(hdf5io_t), intent(inout)  :: hdf5io
         integer, intent(out), optional :: stat
      end subroutine write
         
   end interface
         
   interface photint_t

      module function photint_t_type_(type) result(photint)
         character(*), intent(in)      :: type
         class(photint_t), allocatable :: photint
      end function photint_t_type_

   end interface photint_t
   
   ! Access specifiers

   private

   public :: photint_t

end module photint_m
