! Module  : specsource_m
! Purpose : Define specsource_t abstract type, for representing a source
!           of specint_t's (via the abstract factory pattern)
!
! 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 specsource_m

   ! No implicit typing

   implicit none

   ! Derived-type definitions

   type, abstract :: specsource_t
   contains
      private
      procedure(get_n), deferred, public       :: get_n
      procedure(get_lam_min), deferred, public :: get_lam_min
      procedure(get_lam_max), deferred, public :: get_lam_max
      procedure(fetch), deferred, public       :: fetch
   end type specsource_t

   ! Interfaces

   abstract interface

      subroutine get_n(self, n)
         import specsource_t
         class(specsource_t), intent(in) :: self
         integer, intent(out)            :: n
      end subroutine get_n

      subroutine get_lam_min(self, lam_min)
         use forum_m
         import specsource_t
         class(specsource_t), intent(in) :: self
         real(RD), intent(out)           :: lam_min
      end subroutine get_lam_min

      subroutine get_lam_max(self, lam_max)
         use forum_m
         import specsource_t
         class(specsource_t), intent(in) :: self
         real(RD), intent(out)           :: lam_max
      end subroutine get_lam_max

      subroutine fetch(self, i, specint, stat)
         use specint_m
         import specsource_t
         class(specsource_t), intent(in)            :: self
         integer, intent(in)                        :: i
         class(specint_t), allocatable, intent(out) :: specint
         integer, intent(out), optional             :: stat
      end subroutine fetch

   end interface
      
   ! Access specifiers

   private

   public :: specsource_t

end module specsource_m
