	PRO LIST_COM_TIMES, START, EEND, COM, N_FOUND, ERRMSG=ERRMSG
;+
; Project     :	SOHO - CDS
;
; Name        :	LIST_COM_TIMES
;
; Purpose     :	List the SoHO command contact times for a given period
;
; Explanation :	Extracts all the SoHO Deep Space Network (COM) contact periods
;		in the input time range.
;
; Use         :	LIST_COM_TIMES, START, END, COM, N_FOUND
;
; Inputs      :	START, END = The range of date/time values to use in searching
;			     the database.  Can be in any standard CDS time
;			     format.
;
; Opt. Inputs :	None.
;
; Outputs     :	COM	= A structure variable containing the following tags
;			  for each planned contact period:
;
;			START_TIME   = Date/time of beginning of the command
;				       contact period, in TAI format
;			END_TIME     = Date/time of end of command contact
;				       period, in TAI format
;
;		N_FOUND	= Number of planned contact periods found.
;
; Opt. Outputs:	None.
;
; Keywords    :	
;       ERRMSG    = If defined and passed, then any error messages will be
;                   returned to the user in this parameter rather than
;                   depending on the MESSAGE routine in IDL.  If no errors are
;                   encountered, then a null string is returned.  In order to
;                   use this feature, ERRMSG must be defined first, e.g.
;
;                       ERRMSG = ''
;                       LIST_COM_TIMES, ERRMSG=ERRMSG, ... 
;                       IF ERRMSG NE '' THEN ...
;
;
; Calls       :	DATATYPE, DBOPEN, DBFIND, DBEXT, DBCLOSE, TRIM, GET_INSTRUMENT
;
; Common      :	None.
;
; Restrictions:	None.
;
; Side effects:	If the number of planned contact periods found is zero, then
;		the output parameter COM is not modified.
;
; Category    :	Planning, Database.
;
; Prev. Hist. :	None.
;
; Written     :	William Thompson, GSFC, 31 March 1995
;
; Modified    :	Version 1, William Thompson, GSFC, 3 April 1995
;
; Version     :	Version 1, 3 April 1995
;-
;
	ON_ERROR, 2
;
;  Check the number of parameters.
;
        IF N_PARAMS() LT 4 THEN BEGIN
           MESSAGE = 'Syntax:  LIST_COM_TIMES, START, END, COM, N_FOUND'
	   GOTO, HANDLE_ERROR
        ENDIF
;
;  Check the input parameters.
;
	N_FOUND = 0
	IF N_ELEMENTS(START) NE 1 THEN BEGIN
           MESSAGE = 'START must be a scalar'
           GOTO, HANDLE_ERROR
	END ELSE IF N_ELEMENTS(EEND) NE 1 THEN BEGIN
           MESSAGE = 'END must be a scalar'
           GOTO, HANDLE_ERROR
	ENDIF
;
;  Convert the input dates to TAI format.
;
	IF DATATYPE(START,1) EQ 'Double' THEN TAI_START = START ELSE	$
		TAI_START = UTC2TAI(START)
	IF DATATYPE(EEND,1) EQ 'Double' THEN TAI_END = EEND ELSE	$
		TAI_END = UTC2TAI(EEND)
;
;  Open the resource database.
;
	DBOPEN, 'resource,resource_type'
;
;  Find all the entries in the requested time range.
;
	ENTRIES1 = DBFIND('END_TIME>' + TRIM(TAI_START,'(F15.3)') +	$
		',START_TIME<' + TRIM(TAI_END,'(F15.3)') +	$
		',RES_TYPE=THROUGHPUT_RCR', /SILENT)
	ENTRIES2 = DBFIND('END_TIME>' + TRIM(TAI_START,'(F15.3)') +	$
		',START_TIME<' + TRIM(TAI_END,'(F15.3)') +	$
		',RES_TYPE=THROUGHPUT_NORCR', /SILENT)
	IF (ENTRIES1(0) LE 0) AND (ENTRIES2(0) LE 0) THEN BEGIN
		N_FOUND = 0
		GOTO, FINISH
	END ELSE IF ENTRIES1(0) LE 0 THEN BEGIN
		ENTRIES = ENTRIES2
	END ELSE IF ENTRIES2(0) LE 0 THEN BEGIN
		ENTRIES = ENTRIES1
	END ELSE BEGIN
		ENTRIES = [ENTRIES1,ENTRIES2]
	ENDELSE
	N_FOUND = N_ELEMENTS(ENTRIES)
;
;  Extract the requested entries, sorted by start times.
;
	ENTRIES = DBSORT(ENTRIES,'start_time')
	DBEXT, ENTRIES, 'start_time,end_time', START_TIME, END_TIME
;
;  Remove any entries that only touch the requested time range.
;
	W = WHERE((END_TIME NE TAI_START) AND (START_TIME NE TAI_END), N_FOUND)
	IF N_FOUND EQ 0 THEN GOTO, FINISH
	START_TIME = START_TIME(W)
	END_TIME = END_TIME(W)
;
;  Define the structure that the data will be returned in.
;
	COM = { START_TIME: 0.0D0,	$
		END_TIME: 0.0D0}
;
	IF N_FOUND EQ 1 THEN BEGIN
		COM.START_TIME	= START_TIME(0)
		COM.END_TIME	= END_TIME(0)
	END ELSE BEGIN
		COM = REPLICATE(COM, N_FOUND)
		COM.START_TIME	= START_TIME
		COM.END_TIME	= END_TIME
	ENDELSE
;
;  Get the first start time and the last end time.
;
	FIRST_START = START_TIME(0)
	LAST_END = END_TIME(N_ELEMENTS(END_TIME)-1)
;
;  Find all the instrument NRT reserved times that overlap the relevant time
;  range.
;
	LIST_NRT_RES, FIRST_START, LAST_END, RES, N_RESERVED
	IF N_RESERVED EQ 0 THEN GOTO, FINISH
;
;  Only pay attention to those which are confirmed, and which are for
;  instruments other than CDS.
;
	W = WHERE((RES.INSTRUME NE 'C') AND (RES.STATUS EQ 'C'), N_RESERVED)
	IF N_RESERVED EQ 0 THEN GOTO, FINISH
;
;  For each reserved time, remove that time period from the available command
;  times.
;
	FOR I = 0,N_RESERVED-1 DO BEGIN
		RES_START = RES(I).START_TIME
		RES_END   = RES(I).END_TIME
;
;  First, remove any command times which are entirely reserved.
;
		W = WHERE((RES_START GT COM.START_TIME) OR	$
			(RES_END LT COM.END_TIME), N_FOUND)
		IF N_FOUND EQ 0 THEN GOTO, FINISH
		COM = COM(W)
;
;  Next, truncate any command times where the beginning of the time period is
;  reserved.
;
		W = WHERE((RES_START LE COM.START_TIME) AND	$
			(RES_END GT COM.START_TIME), COUNT)
		IF COUNT GT 0 THEN COM(W).START_TIME = RES_END
;
;  Next, truncate any command times where the end of the time period is
;  reserved.
;
		W = WHERE((RES_START LT COM.END_TIME) AND	$
			(RES_END GE COM.END_TIME), COUNT)
		IF COUNT GT 0 THEN COM(W).END_TIME = RES_START
;
;  Finally, split in two any command times which has a reserved time in the
;  middle of it.  Because of the previous changes above, if a reserved time
;  overlaps a command time, then it must be somewhere inbetween two valid
;  command times.
;
		W = WHERE((RES_START LT COM.END_TIME) AND	$
			(RES_END GT COM.START_TIME), COUNT)
		IF COUNT GT 0 THEN BEGIN
			IF COUNT GT 1 THEN BEGIN
				MESSAGE = 'There appear to be overlapping ' + $
					'throughput times'
				GOTO, HANDLE_ERROR
			ENDIF
			SAVE = COM
			N_FOUND = N_FOUND + 1
			COM = REPLICATE(COM(0),N_FOUND)
			COM(0) = SAVE(0:W(0))
			COM(W(0)+1) = SAVE(W(0):*)
			COM(W(0)).END_TIME = RES_START
			COM(W(0)+1).START_TIME = RES_END
		ENDIF
	ENDFOR
;
	GOTO, FINISH
;
;  Handle any errors encountered.
;
HANDLE_ERROR:
	IF N_ELEMENTS(ERRMSG) NE 0 THEN		$
		ERRMSG = 'LIST_COM_TIMES: ' + MESSAGE ELSE MESSAGE, MESSAGE 
;
;  Close the database and return.
;
FINISH:
	DBCLOSE
;
	RETURN
	END
