#ifndef __RECEIVERS_BOSS_IDL__
#define __RECEIVERS_BOSS_IDL__

/***************************************************************\
 *  Authors: 
 *      Marco Buttu <mbuttu@oa-cagliari.inaf.it>
 *      Andrea Orlati <a.orlati@ira.inaf.it>
 *
 *  Created: Thu Oct 21 15:33:10 CEST 2010 
\***************************************************************/

#include <baci.idl>
#include <ComponentErrors.idl>
#include <ReceiversErrors.idl>
#include <ManagmentDefinitions.idl>
#include "CommonReceiverInterface.idl"
#include "ReceiversDefinitions.idl"
#include <AntennaDefinitions.idl>

#pragma prefix "alma"

module Receivers { 
	
	/** 
	 * This is a notification channel name, it publishes information about the receivers subsystem that can be used to other
	 * subsystems. Boss will be the data producer for this channel. Anyone interested in these information  must register
	 *  to this channel as a consumer. Data will be published on this channel when one of the members of the
	 *  <i>ReceiversDataBlock</i> structure changes its value or when at least 1 second has elapsed since last publication. 
	 *  In case of errors and one second elapsed since last publication, the last known good data is published until   the error
	 *  is fixed.
	*/
	const string RECEIVERS_DATA_CHANNEL="ReceiversData";
	
	/**
     * Notification channel data structure. The boss informs all registered consumers when one of these members change 
     * its status or value (not including time). In any case data are published at least once a second. In case there are problems 
     * retrieving the information or other, the last available data are published until the problem is fixed. 
	 * Time represents the number of 100 ns since 1582-10-15 00:00:00, it is defined in baci.idl and it is mapped over a
	 *  longlong type.	 
	*/
	struct ReceiversDataBlock {
		ACS::Time timeMark;	  /*!< this is the absolute time mark that reports exactly when the published events occurred */
		boolean tracking;			              /*!< true when the receivers are ready and the dewar positioner is tracking   */
		Management::TSystemStatus status; /*!< this report the subsystem status. @sa the attribute <i>status</i> */
	};
	
	/**
	 * This structure is used to pass the receivers parameters to the <i>startScan()</i> routine on subscan basis.
	 * Empty at the moment.
	*/
	typedef struct RecvPoint {
		long dummy;
	} TReceiversParameters;
    
		
    /**
     * <h2>Interface of a generic receiver</h2>
     * <p>This CORBA interface exports properties and methods defined for a generic 
     * <em>Receiver</em>.</p>
     */
    interface ReceiversBoss : ACS::CharacteristicComponent, CommonReceiverInterface, Management::CommandInterpreter, Management::Subsystem {

        /** **** THIS PROPERTY SHOULD BE MOVED IN THE SUBSYSTEM INTERFACE ****
         *
         * This attribute reports the current configuration name of the receiver subsystem (the configuration commanded by a subsystem setup). 
         * This string can be either a valid configuration name or 'unknown' when the system is in an unknown status 
         */
        readonly attribute ACS::ROstring actualSetup;

        /**
         * This attribute can be used as readout of the actual derotator position
         */
        readonly attribute ACS::ROdouble derotatorPosition;

 
        /***************************************************\
         *           COMMON_RECEIVER_INTERFACE             *
         ***************************************************

            readonly attribute ACS::ROdoubleSeq LO;
            
            readonly attribute ACS::ROlong feeds;
            
            readonly attribute ACS::ROlong IFs;

            readonly attribute ACS::ROlongSeq polarization;

            void calOn() raises (ComponentErrors::ComponentErrorsEx);

            void calOff() raises (ComponentErrors::ComponentErrorsEx);

            void setLO(in ACS::doubleSeq lo1) raises (ComponentErrors::ComponentErrorsEx);

            ACS::doubleSeq getCalibrationMark(in ACS::doubleSeq freqs,in ACS::doubleSeq bandwidths,in ACS::longSeq feeds,in ACS::longSeq ifs) 
               raises (ComponentErrors::ComponentErrorsEx);

            long getFeeds(out ACS::doubleSeq X,out ACS::doubleSeq Y,out ACS::doubleSeq power) raises (ComponentErrors::ComponentErrorsEx);

            double getTaper(in double freq,in double bandWidth,in long feed,in long ifNumber,out double waveLen) 
                raises (ComponentErrors::ComponentErrorsEx);


        /***************************************************\
         *               COMMAND_INTERPRETER               *
         ***************************************************

            string  command(in string command) raises (ManagementErrors::CommandLineErrorEx);


        /***************************************************\
         *                  SUBSYSTEM                      *
         ***************************************************

            readonly attribute Management::ROTSystemStatus status;
            
            void setup(in string config) raises (ManagementErrors::ConfigurationErrorEx);
            
            void park() raises (ManagementErrors::ParkingErrorEx);

        \***************************************************/

        /**
         * This method prepares the system for the derotation but it does not start it.
         * if the no derotator is supported, or no receiver has been configured or the current receiver does not have a derotator
         * an error is raised.
         * @param mode specifies how to manage the derotation, if <i>RCV_UNDEF_DEROTCONF</i> the current value is kept
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorsEx
         */
        void derotatorSetConfiguration(in TDerotatorConfigurations conf) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);

        /**
         * This method prepares the system for derotation but not starting it. If the no derotator is supported, or no receiver has been configured or the current receiver
         * does not have a derotator an error is raised.
         * @param mode specifies how to manage the derotation, if <i>RCV_UNDEF_DEROTCONF</i> the current value is kept
         * @param rewind specifies how to manage the rewind, when it is needed. If <i>RCV_UNDEF_REWIND</i> the current value is kept
         * @param feeds give the number of feeds when the number. if -1 the current value is kept 
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorsEx
         */
        //void derotatorMode(in TDerotatorConfigurations mode,in TRewindModes rewind,in long feeds) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);
        
        /**
         *  This method parks the current derotator. In order to start the derotator again, another <i>derotatorSetup</i> must be called.
         *  It is implicitly called by the <i>park()</i> method of the boss. 
         *  @throw ReceiversErrors::ReceiversErrorsEx
         *  @throw ComponentErrors::ComponentErrorsEx
         */
        void derotatorPark() raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);

        /**
         * This method allows to set the starting position of the derotator. Allowed only if FIXED or CUSTOM modes are setup.
         * @param position the initial position (degrees)
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorEx
         */
        void derotatorSetPosition(in double position) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);

        /**
         * It allows to configure how the dewar positioner behaves in case the derotator hits a final limit and need to rewind.
         * @param rewind specifies how to manage the rewind, when it is needed. If <i>RCV_UNDEF_REWIND</i> the current value is kept
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorEx
         */
        void derotatorSetRewindingMode(in TRewindModes rewind) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);

        /**
         * It sets the number of fixed length steps (it depends on the particular derotator) the dewar positioner moves when an auto
         * rewind have to be taken
         * @param steps number of configured auto rewinding steps.
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorEx
         */
        void derotatorSetAutoRewindingSteps(in long steps) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);

        /**
         * Allows to perform a manual rewind of the derotator.
         * @param steps number of steps (it depends on the currently configured receiver)
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorsEx
         */
        void derotatorRewind(in long steps)  raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);
              
        /**
         * This method allows to collect the current position of the derotator, if derotator is not available or it is not activated an error is thrown.
         * @return the position of the derotator in degrees. Used only internally.
         * @param epoch the returned position refers to the given epoch
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorsEx
         */
        double getDerotatorPositionFromHistory(in ACS::Time epoch) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);
        
        /**
         * This method collects the configuration of the dewar
         * @param mod this is the mode currently configured, BSC, ALIGN, OPTIM,....
         * @param pos starting position for the derotator. It could be given by the user or by the system according the selected mode.
         *        It includes the angle added for the rewind.
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorsEx
         */
        void getDewarParameter(out TDerotatorConfigurations mod,out double pos)raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);

        /**
         * This method allows to prepare the receivers for scan 
         * @param startUT exact time the scan is required to start. If it is zero, the call is intended to start the scan asap.
         *         As output (in case the input value is zero) it returns the expected start time.
         * @param param structure containing all the information required in order to prepare the receiver for the scan.
         * @param antennaInfo auxiliary information from the antenna
         * @throw ReceiversErrors::ReceiversErrorsEx
         * @throw ComponentErrors::ComponentErrorsEx
         */
        void startScan(inout ACS::Time startUT,in TReceiversParameters param,in Antenna::TRunTimeParameters antennaInfo) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);
        
		/**
		 * This method virtually stops the current scan. The boss indeed is not required to do anything.
		 * @param timeToStop stores the expected epoch in which the scan will be stopped (closed). It could be zero mening the
		 *         scan will be closed immediately
		 * @throw ComponentErrors::ComponentErrorsEx
		 * @throw ReceiversErrors::ReceiversErrorsEx
		 */
		void closeScan(out ACS::Time timeToStop) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);


		/**
		 * This method is only be used internally. Anyone that needs to know if the receiver subsystem could perform a given scan before a given time, can call this. 
		 * @throw CORBA::SystemExcpetion
		 * @throw ComponentErrors::ComponentErrorsEx
		 * @throw ReceiversErrors::ReceiversErrorsEx
		 * @param startUt this is the time before which the receivers are supposed to be ready for the scan. 
		 * @param param structure that describes the scan to be performed.
		 * @param antennaInfo structure that contains desired information from the antenna subsystem
		 * @param runTime stores the runtime parameters regarding the current scan from the receivers
		 * @return true if the subsystem could accomplish the required scan.
		 */
		boolean checkScan(in ACS::Time startUt,in TReceiversParameters param,in Antenna::TRunTimeParameters antennaInfo,
		 out TRunTimeParameters runTime) raises (ComponentErrors::ComponentErrorsEx,ReceiversErrors::ReceiversErrorsEx);
        
    };
    
    
};

#endif
