module gwcs_interfaces_private
  interface
    subroutine gwcs_message(mkind,procname,message)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      ! Messaging facility for the current library. Calls the low-level
      ! (internal) messaging routine with its own identifier.
      !---------------------------------------------------------------------
      integer,          intent(in) :: mkind     ! Message kind
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      character(len=*), intent(in) :: message   ! Message string
    end subroutine gwcs_message
  end interface
  !
  interface
    subroutine chgref(matrix, oldref, newref)
      !---------------------------------------------------------------------
      ! @ private
      ! Computes the coordinates of the reference direction in the new system
      !---------------------------------------------------------------------
      real(kind=8), intent(in)  :: matrix(3,3)  ! Rotation matrix
      real(kind=8), intent(in)  :: oldref(2)    ! Old coordinates (radians)
      real(kind=8), intent(out) :: newref(2)    ! New coordinates (radians)
    end subroutine chgref
  end interface
  !
  interface
    subroutine chgoff(matrix,oldref,oldoff,newref,newoff)
      !---------------------------------------------------------------------
      ! @ private
      ! Compute offsets in the new system
      !------------------------------------------------------------------------
      real(kind=8), intent(in)  :: matrix(3,3)  ! Rotation matrix
      real(kind=8), intent(in)  :: oldref(2)    ! Old coordinates (radians)
      real(kind=4), intent(in)  :: oldoff(2)    ! Old offsets (radians)
      real(kind=8), intent(in)  :: newref(2)    ! New coordinates (radians)
      real(kind=4), intent(out) :: newoff(2)    ! New offsets (radians)
    end subroutine chgoff
  end interface
  !
  interface
    subroutine full_b1950_to_j2000(obs_epoch,lambda,beta,mu_alph,mu_delt,  &
      parallax,radvel)
      !---------------------------------------------------------------------
      ! @ private
      ! Convert Besselian coordinates to J2000.
      ! Implementation of the general formulas given in Aoki et al AA 128,
      ! 263 (1983), modified (not totally sure the modification is totally
      ! consistent, but the potentially remaining inconsistencies should be
      ! small for practical cases) to handle the case of a non-B1950 observing
      ! epoch.
      !
      ! NOT YET FINISHED, STILL RESTRICTED TO NO PM, NO PARALLAX, NO RV,
      ! BUT WORKS AS BEFORE IN THIS RESTRICTED CASE
      !---------------------------------------------------------------------
      real(kind=8), intent(in)    :: obs_epoch  !
      real(kind=8), intent(inout) :: lambda     !
      real(kind=8), intent(inout) :: beta       !
      real(kind=8), intent(in)    :: mu_alph    !
      real(kind=8), intent(in)    :: mu_delt    !
      real(kind=8), intent(in)    :: parallax   !
      real(kind=8), intent(in)    :: radvel     !
    end subroutine full_b1950_to_j2000
  end interface
  !
  interface
    subroutine rel_to_abs_sfl(proj,x,y,a,d,n)
      use phys_const
      use gwcs_types
      !---------------------------------------------------------------------
      ! @ private
      ! SFL: see Calabretta and Greisen 2002
      !
      ! Their general idea, as described in section 2, is that
      ! 1) you convert from (x,y) projected coordinates to the "native"
      !    absolute spherical coordinate: (x,y) are converted to
      !    (phi,theta).
      ! 2) you rotate the absolute native coordinates (phi,theta) to
      !    absolute celestial coordinates (alpha,delta) (Euler rotation of
      !    the native sphere).
      ! => those 2 steps are grouped in Eq. 2, 8, 9, 10.
      !
      ! In the context of SFL, these equations can be simplified. As per
      ! section 5.3, SFL projection is a pseudo-spherical projection with
      ! coordinates of the reference point (phi_0,theta_0) = (0,0). Also,
      ! (phi,theta) are defined in Eq. 92, 93 for SFL projection.
      !---------------------------------------------------------------------
      type(projection_t), intent(in)  :: proj  ! Description of projection
      real(kind=8),       intent(in)  :: x(*)  ! Array of offsets in X
      real(kind=8),       intent(in)  :: y(*)  ! Array of offsets in Y
      real(kind=8),       intent(out) :: a(*)  ! Array of R.A. (radians)
      real(kind=8),       intent(out) :: d(*)  ! Array of declinations
      integer(kind=8),    intent(in)  :: n     ! Size of arrays
    end subroutine rel_to_abs_sfl
  end interface
  !
  interface
    subroutine abs_to_rel_sfl(proj,a,d,x,y,n)
      use gwcs_types
      !---------------------------------------------------------------------
      ! @ private
      ! SFL: see Calabretta and Greisen 2002
      !
      ! See comments in rel_to_abs_sfl
      !---------------------------------------------------------------------
      type(projection_t), intent(in)  :: proj  ! Description of projection
      real(kind=8),       intent(in)  :: a(*)  ! Array of R.A. (radians)
      real(kind=8),       intent(in)  :: d(*)  ! Array of declinations
      real(kind=8),       intent(out) :: x(*)  ! Array of offsets in X
      real(kind=8),       intent(out) :: y(*)  ! Array of offsets in Y
      integer(kind=8),    intent(in)  :: n     ! Size of arrays
    end subroutine abs_to_rel_sfl
  end interface
  !
  interface
    function arcsin (x)
      use phys_const
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      real(kind=8) :: arcsin         !
      real(kind=8), intent(in) :: x  !
    end function arcsin
  end interface
  !
  interface
    function arccos (x)
      use phys_const
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      real(kind=8) :: arccos         !
      real(kind=8), intent(in) :: x  !
    end function arccos
  end interface
  !
  interface
    subroutine gwcs_observatory_internal(arg,lonlat,altitude,slimit,diam,found)
      !---------------------------------------------------------------------
      ! @ private
      !  Internal subroutine, do not call directly! Use generic API
      ! 'gwcs_observatory' to retrieve a known observatory parameters, or
      ! use 'gwcs_observatory_exists' to check if it is known here.
      ! ---
      !  Return the observatory parameters given its name, with a flag
      ! 'found' if it was found or not.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: arg        ! Telescope name
      real(kind=8),     intent(inout) :: lonlat(2)  !
      real(kind=8),     intent(inout) :: altitude   !
      real(kind=8),     intent(inout) :: slimit     !
      real(kind=4),     intent(inout) :: diam       !
      logical,          intent(out)   :: found      !
    end subroutine gwcs_observatory_internal
  end interface
  !
end module gwcs_interfaces_private
