! Module  : spec_photsource_m
! Purpose : Define spec_photsource_t type, for representing a
!           source of photint_t basd on a corresponding specsource_t
!           and passband
!
! Copyright 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 spec_photsource_m

   ! Uses

   use forum_m

   use passband_m
   use photint_m
   use photsource_m
   use specint_m
   use specsource_m
   use stat_m

   use ISO_FORTRAN_ENV

   ! No implicit typing

   implicit none

   ! Derived-type definitions

   type, extends(photsource_t) :: spec_photsource_t
      private
      class(specsource_t), allocatable :: specsource
      type(passband_t)                 :: passband
      integer                          :: n
   contains
      private
      procedure, public :: get_n
      procedure, public :: fetch
   end type spec_photsource_t

   ! Interfaces

   interface spec_photsource_t
      module procedure spec_photsource_t_
   end interface spec_photsource_t

   ! Access photifiers

   private

   public :: spec_photsource_t

contains

   function spec_photsource_t_(specsource, passband) result(photsource)

      class(specsource_t), intent(in) :: specsource
      type(passband_t), intent(in)    :: passband
      type(spec_photsource_t)         :: photsource

      ! Construct photsource from specsource and passband

      photsource%specsource = specsource
      photsource%passband = passband

      call specsource%get_n(photsource%n)

      ! Finish

      return

   end function spec_photsource_t_

   !****

   subroutine get_n(self, n)

      class(spec_photsource_t), intent(in) :: self
      integer, intent(out)                 :: n

      ! Get n

      n = self%n

      ! Finish

      return

   end subroutine get_n

   !****

   subroutine fetch(self, i, photint, stat)

      class(spec_photsource_t), intent(in)       :: self
      integer, intent(in)                        :: i
      class(photint_t), allocatable, intent(out) :: photint
      integer, intent(out), optional             :: stat

      class(specint_t), allocatable :: specint

      ! Fetch the photint from the specsource

      if (i < 0 .OR. i > self%n) then
         if (PRESENT(stat)) then
            stat = STAT_INVALID_ARGUMENT
            return
         else
            @:ABORT('invalid argument')
         end if
      end if

      call self%specsource%fetch(i, specint, stat)
      if (PRESENT(stat)) then
         if (stat /= STAT_OK) return
      end if

      call specint%filter(self%passband, photint, stat)

      ! Finish

      return

   end subroutine fetch

end module spec_photsource_m
