module telcal_interfaces_public
  interface
    subroutine telcal_chopper(chopper,error)
      use gbl_message
      use chopper_definitions
      !----------------------------------------------------------------------
      ! @ public
      !
      ! Compute Trec, Tcal, Tsys from the chop and atm values observed
      ! according to the usual chopper method (ulich and haas) Double side band
      ! operation.
      !
      ! Note that each for each frequency, an error status is set in
      ! chopper%errors(ifreq). It indicates if the operation could be performed
      ! or not. It is the responsibility of the caller to check them or not,
      ! e.g.
      !
      !   call telcal_chopper(chopper,error)
      !   if (error .or. any(chopper%errors(:))  return
      !
      ! If the error status of a given frequency is set to .true., the output
      ! parameters are also nullified to the value chopper%bad, so that the
      ! caller can identify them as bad values.
      ! ----------------------------------------------------------------------
      type(chopper_t), intent(inout) :: chopper
      logical,         intent(inout) :: error
    end subroutine telcal_chopper
  end interface
  !
  interface
    subroutine telcal_chopper_nullify(chopper,ifreq)
      use chopper_definitions
      !---------------------------------------------------------------------
      ! @ public
      !  Nullify the chopper results (only the outputs, not the inputs) e.g.
      ! in case of error
      !---------------------------------------------------------------------
      type(chopper_t), intent(inout) :: chopper
      integer(kind=4) :: ifreq
    end subroutine telcal_chopper_nullify
  end interface
  !
  interface
    function airmass(el,error)
      use gbl_message
      !----------------------------------------------------------------------
      ! @ public
      ! Compute airmass number corresponding to elevation EL
      ! Use a curved atmosphere, equivalent height 5.5 km
      !----------------------------------------------------------------------
      real(8), intent(in)  :: el      ! Elevation [radian]
      logical, intent(out) :: error   ! Error flag
      real(8)              :: airmass ! Airmass
    end function airmass
  end interface
  !
  interface
    subroutine fit_1d(dat,fun,verbose)
      use fit_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! General unidimensional fitting routine
      !----------------------------------------------------------------------
      type(simple_1d), intent(in)  :: dat ! Data vectors
      type(fit_fun), intent(inout) :: fun ! Fitting function description
      logical, intent(in)      :: verbose ! Verbose or quiet?
    end subroutine fit_1d
  end interface
  !
  interface
    subroutine null_simple_1d(dat)
      use fit_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine of its derived types
      ! Purpose: Initialize a simple precision data vector
      !----------------------------------------------------------------------
      type(simple_1d), intent(inout) :: dat ! Data vector
    end subroutine null_simple_1d
  end interface
  !
  interface
    subroutine null_parameter(par)
      use fit_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine of its derived types
      ! Purpose: Initialize a fitted parameter
      !----------------------------------------------------------------------
      type(fit_par), intent(inout) :: par ! Fitted parameter
    end subroutine null_parameter
  end interface
  !
  interface
    subroutine null_function(fun)
      use fit_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine of its derived types
      ! Purpose: Initialize a fitted function description
      !----------------------------------------------------------------------
      type(fit_fun), intent(inout) :: fun ! Description of the fitted function
    end subroutine null_function
  end interface
  !
  interface
    subroutine copy_simple_1d(in,out)
      use fit_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine of its derived types
      ! Purpose: Copy a simple precision data vector
      !----------------------------------------------------------------------
      type(simple_1d), intent(in)    :: in  ! Original vector
      type(simple_1d), intent(inout) :: out ! Copied vector
    end subroutine copy_simple_1d
  end interface
  !
  interface
    subroutine copy_function(in,out)
      use fit_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine of its derived types
      ! Purpose: Copy the description of a fitted function
      !----------------------------------------------------------------------
      type(fit_fun), intent(in)    :: in  ! Original function
      type(fit_fun), intent(inout) :: out ! Copied function
    end subroutine copy_function
  end interface
  !
  interface
    subroutine solve_focus(line,error)
      use fit_definitions
      use focus_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine for command
      !    FOCUS [Polynomial|Lorentzian|Gaussian]
      !----------------------------------------------------------------------
      character(*), intent(in)  :: line  ! Command line
      logical,      intent(out) :: error ! Error flag
    end subroutine solve_focus
  end interface
  !
  interface
    subroutine init_focus(ndat)
      use focus_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine for focus
      ! Purpose:
      !----------------------------------------------------------------------
      integer, intent(in) :: ndat ! Number of data points
    end subroutine init_focus
  end interface
  !
  interface
    subroutine load_telcal
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL Support routine
      ! Purpose: Language is loaded
      !----------------------------------------------------------------------
      ! Global
    end subroutine load_telcal
  end interface
  !
  interface
    subroutine run_telcal(line,comm,error)
      !----------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      ! TELCAL Main library entry point
      ! Purpose: Call appropriate subroutine according to COMM
      !----------------------------------------------------------------------
      character(len=*), intent(in)    :: line  ! Command line
      character(len=*), intent(in)    :: comm  ! Typed command
      logical,          intent(inout) :: error ! Error flag
    end subroutine run_telcal
  end interface
  !
  interface
    subroutine telcal_pack_set(pack)
      use gpack_def
      !----------------------------------------------------------------------
      ! @ public
      !----------------------------------------------------------------------
      type(gpack_info_t), intent(out) :: pack
    end subroutine telcal_pack_set
  end interface
  !
  interface
    subroutine default_pointing_guess(guess)
      use point_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine for pointing
      ! Purpose: Try to make clever guesses to prepare to solve for pointing
      !          parameters. A few comments:
      !            * It is safe to leave offset and slope values to zero as
      !              the fit easily find good values from those guesses
      !            * The initial guesses of area and position will anyway
      !              be changed in the solving process. They are present here
      !              for generality
      !            * The area_ratio and width_ratio guesses are quite easy.
      !            * Nevertheless, to obtain a robust fitting, it is mandatory
      !              that the user gives (outside this routine) useful guesses
      !              of the width (probably the beam FWHM) and the beam throw
      !          We have at most 8 parameters to fit. At high SNR, without bias
      !          this will be easy. However, this is rarely the case. Fixing
      !          the value of the area_ratio, beam_throw and width_ratio is a
      !          good way to obtain a robust value of the position (the goal).
      !          Indeed, it is easy to have good guesses for those values. While
      !          it is true that those guesses are not perfect, simulations
      !          show that this gives robust determination of the pointing
      !          error even when the fit looks biased.
      !----------------------------------------------------------------------
      type(point_guess_t), intent(out) :: guess ! User guesses from command line
    end subroutine default_pointing_guess
  end interface
  !
  interface
    subroutine init_pointing(ndat,nsol,psys,pdir,ptype,point,error)
      use point_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine for pointing
      ! Purpose: Free, reallocate and initialize the POINT structure
      !          according to user defined input. Data must be filled
      !          outside
      !----------------------------------------------------------------------
      integer, intent(in) :: ndat             ! Number of data points
      integer, intent(in) :: nsol             ! Number of solution points
      integer, intent(in) :: psys             ! Pointing coordinate system
      character(len=*), intent(in) :: pdir    ! Pointing direction in above system
      character(len=*), intent(in) :: ptype   ! Pointing type (SINGLE|DUAL)
      type(pointing_t), intent(out) :: point  ! Pointing structure
      logical, intent(out) :: error           ! Error flag
    end subroutine init_pointing
  end interface
  !
  interface
    subroutine solve_pointing(point,guess,verbose,error)
      use point_definitions
      use phys_const
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine for pointing
      ! Purpose: Find the first guesses, fit and compute profile of fit
      !          solution. The fit is iterated with position guess every half
      !          FWHM in the x coordinate range. The best fit is then selected.
      !          In real cases, this implies of the order of 20 fits if the width
      !          parameter. This scheme provides a very robust solution.
      !----------------------------------------------------------------------
      type(pointing_t), intent(inout) :: point ! FORTRAN 90 pointing structure
      type(point_guess_t), intent(in) :: guess ! User guesses from command line
      logical, intent(in)  :: verbose          ! Verbose or quiet solving?
      logical, intent(out) :: error            ! Error flag
    end subroutine solve_pointing
  end interface
  !
  interface
    subroutine free_pointing(point)
      use point_definitions
      !----------------------------------------------------------------------
      ! @ public
      ! TELCAL support routine for pointing
      ! Purpose: Free memory associated to the FORTRAN 90 pointing structure
      !----------------------------------------------------------------------
      type(pointing_t), intent(inout) :: point ! FORTRAN 90 pointing structure
    end subroutine free_pointing
  end interface
  !
end module telcal_interfaces_public
