!
! Procedures for handling of a dynamical (linked) list
!
!
!  Copyright © 2011,2014,2016-7 F.Hroch (hroch@physics.muni.cz)
!
!  This file is part of Munipack.
!
!  Munipack 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.
!
!  Munipack 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 Munipack.  If not, see <http://www.gnu.org/licenses/>.
!

Module LibList

  use fitsio

  implicit none

  type ImageType
     integer :: i
     real :: mean,stderr,stdsig,exptime,temp,saturate
     real,  pointer :: image(:,:), noise(:,:)
     character(len=FLEN_VALUE) :: dateobs, filter
     character(len=FLEN_FILENAME) :: filename
     type( ImageType ), pointer :: next
  end type ImageType

contains !---------------------------------------------------------------

  subroutine InitList(list)

    ! Initialize a new list

    type(Imagetype), pointer :: list

    nullify(list)
    Allocate(list)
    nullify(list%next)
    list%i = 0

  end subroutine InitList

  Subroutine DestroyList(list)

    type(Imagetype), pointer :: list,c,d

    c => list%next
    do while (associated(c))
       d => c
       c => c%next
       if( associated(d%image) ) deallocate(d%image)
       if( associated(d%noise) ) deallocate(d%noise)
       deallocate(d)
    end do
    deallocate(list)
    nullify(list)

  end Subroutine DestroyList

  !-------------------------------------------------------------------------

  Subroutine AddItem (current,image,filename,noise,mean,stderr,stdsig,&
       dateobs,exptime,filter,temp,satur)

    type(Imagetype), pointer :: current
    real, dimension(:,:), optional, pointer :: image, noise
    real, optional, intent(in) :: mean, stderr, stdsig, exptime, temp, satur
    character(len=*), optional, intent(in) :: filename,dateobs, filter
    integer :: i

    i = current%i + 1
    Allocate( current%next )
    nullify( current%next%next )
    current => current%next
    current%i = i
    if( present(image) ) then
       current%image => image
    else
       nullify(current%image)
    end if
    if( present(noise) ) then
       current%noise => noise
    else
       nullify(current%noise)
    end if
    if( present(filename) ) current%filename = filename
    if( present(mean) ) current%mean = mean
    if( present(stderr) ) current%stderr = stderr
    if( present(stdsig) ) current%stdsig = stdsig
    if( present(dateobs) ) current%dateobs = dateobs
    if( present(filter) ) current%filter = filter
    if( present(exptime) ) current%exptime = exptime
    if( present(temp) ) current%temp = temp
    if( present(satur) ) current%saturate = satur

  end subroutine AddItem

  ! -----------------------------------------------------------------------

  subroutine GetItem(current,image,noise,filename,mean,stderr,stdsig, &
       dateobs,exptime,filter,temp, satur)

    type(Imagetype) :: current
    real, dimension(:,:), optional, pointer :: image, noise
    real, optional, intent(out) :: mean,stderr,stdsig,exptime,temp,satur
    character(len=*), optional, intent(out) :: filename,dateobs,filter

    if( present(image) ) image => current%image
    if( present(noise) ) noise => current%noise
    if( present(filename) ) filename = current%filename
    if( present(mean) ) mean = current%mean
    if( present(stderr) ) stderr = current%stderr
    if( present(stdsig) ) stdsig = current%stdsig
    if( present(dateobs) ) dateobs = current%dateobs
    if( present(exptime) ) exptime = current%exptime
    if( present(filter) ) filter = current%filter
    if( present(temp) ) temp = current%temp
    if( present(satur) ) satur = current%saturate

  end subroutine GetItem

  ! ------------------------------------------------------------------------


  Subroutine GetImage(first, n, image, noise)

    type(Imagetype), pointer :: first, current
    integer, intent(in) :: n
    real, dimension(:,:), pointer :: image
    real, dimension(:,:), pointer, optional :: noise

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          image => current%image
          if( present(noise) ) noise => current%noise
          return
       endif
       current => current%next
    enddo

  end subroutine GetImage

  !----------------------------------------------------------------------

  Subroutine PutImage( first, n, image, noise)

    type(Imagetype), pointer :: first, current
    integer, intent(in) :: n
    real, dimension(:,:), pointer :: image
    real, dimension(:,:), pointer, optional :: noise

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          current%image => image
          if( present(noise) ) then
             current%noise = noise
          else
             nullify(current%noise)
          end if
          return
       endif
       current => current%next
    enddo

  end subroutine PutImage

  ! ---------------------------------------------------------------------

  function GetNext(current)

    type(Imagetype), pointer :: current, GetNext

    GetNext => current%next

  end function GetNext


  ! ----------------------------------------------------------------------

  function GetNo(current)

    type(Imagetype) :: current
    integer :: getno

    getno = current%i

  end function GetNo

  ! -----------------------------------------------------------------------

  subroutine GetSky(current, mean, stderr)

    type(Imagetype) :: current
    real, intent(out) :: mean, stderr

    mean = current%mean
    stderr = current%stderr

  end subroutine GetSky

  ! ---------------------------------------------------------------------

  Subroutine GetPar ( first, n, mean, stderr)

    type(Imagetype),pointer :: first, current
    integer, intent(in) :: n
    real, intent(out) :: mean, stderr

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          mean = current%mean
          stderr = current%stderr
          return
       endif
       current => current%next
    enddo

  end subroutine GetPar

  ! ------------------------------------------------------------------------

  Subroutine PutPar (first, n, mean, stderr)

    type(Imagetype),pointer :: first, current
    integer, intent(in) :: n
    real, intent(in) :: mean, stderr

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          current%mean = mean
          current%stderr = stderr
          return
       endif
       current => current%next
    enddo

  end subroutine PutPar

  subroutine SetItem(current,array,filename,mean,stderr,stdsig, &
       dateobs,exptime,filter,temp,satur)

    type(Imagetype) :: current
    real, dimension(:,:), optional, pointer :: array
    real, optional, intent(in) :: mean,stderr,stdsig,exptime,temp,satur
    character(len=*), optional, intent(in) :: filename,dateobs,filter

    if( present(array) )    current%image => array
    if( present(filename) ) current%filename  = filename
    if( present(mean) )     current%mean = mean
    if( present(stderr) )   current%stderr= stderr
    if( present(stdsig) )   current%stdsig= stdsig
    if( present(dateobs) )  current%dateobs = dateobs
    if( present(exptime) )  current%exptime = exptime
    if( present(filter) )   current%filter = filter
    if( present(temp) )     current%temp = temp
    if( present(satur) )    current%saturate = satur

  end subroutine SetItem

end module LibList
