!
!----------------------------------------------------------------------
!
! <DOCUMENTATION name="modulePakoOnOff">
!   <VERSION>
!                Id: modulePakoOnOff.f90,v 1.2.4 2015-07-15 Hans Ungerechts
!                Id: modulePakoOnOff.f90,v 1.2.3 2014-10-27 Hans Ungerechts
!                Id: modulePakoOnOff.f90,v 1.2.3 2014-02-10 Hans Ungerechts
!                Id: modulePakoOnOff.f90,v 1.2.3 2014-02-03 Hans Ungerechts
!                                          1.2.0 2012-08-16 Hans Ungerechts
!                based on
!                Id: modulePakoOnOff.f90,v 1.1.0 2009-03-25 Hans Ungerechts
!   </VERSION>
!   <PROGRAM>
!                Pako
!   </PROGRAM>
!   <FAMILY>
!                Observing Modes
!   </FAMILY>
!   <SIBLINGS>
!                Calibrate
!                Focus
!                OnOff
!                OtfMap
!                Pointing
!                Tip
!                Track
!                VLBI
!   </SIBLINGS>        
!
!   Pako module for command: ONOFF
!
! </DOCUMENTATION> <!-- name="modulePakoOnOff" -->
!
!----------------------------------------------------------------------
!
Module modulePakoOnOff
  !
  Use modulePakoMessages
  Use modulePakoTypes
  Use modulePakoGlobalParameters
  Use modulePakoLimits
  Use modulePakoXML
  Use modulePakoUtilities
  Use modulePakoPlots
  Use modulePakoDisplayText
  Use modulePakoGlobalVariables
  Use modulePakoSubscanList
  Use modulePakoReceiver
  Use modulePakoBackend
  Use modulePakoSource
  Use modulePakoSwBeam
  Use modulePakoSwFrequency
  Use modulePakoSwWobbler
  Use modulePakoSwTotalPower
  !
  Use gbl_message
  !
  Implicit None
  Save
  Private
  !
  Public :: onOff
  Public :: displayOnOff
  Public :: saveOnOff
  Public :: startOnOff
  Public :: plotOMOnOff
  !     
  ! *** Variables for OnOff ***
  Include 'inc/variables/variablesOnOff.inc'
!!!   
!!!   
Contains
!!!
!!!
  Subroutine OnOff(programName, line, command, error)
    !
    ! *** Arguments ***
    Include 'inc/variables/headerForCommandHandler.inc'
    !
    ! *** standard working variables ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Integer                :: iQuery
    Character(len=lenCh)   :: nameQuery
    Logical                :: isSet
    Type(xyPointType)      :: pointResult
    !
    Logical               :: isConnected   = .False.
    !
    Include 'inc/ranges/rangesOnOff.inc'
    !
    ERROR = .False.
    !
    Call pako_message(seve%t,programName,                                        &
         &  " module OnOff, v 1.2.4 2015-07-15  --> SR: OnOff ")                 ! trace execution
    !
    ! *** initialize ***
    If (.Not.isInitialized) Then
       Include 'inc/variables/setDefaults.inc'
       isInitialized = .True.
    Endif
    !
    ! *** set In-values = previous Values ***
    If (.Not.ERROR) Then
       vars(iIn) = vars(iValue)
    End If
    !
    ! *** check N of Parameters: 0, n --> at  most n allowed  ***
    !     read Parameters, Options (to detect errors)            
    !     and check for validity and ranges                      
    Call checkNofParameters(command,                                             &
         &     0, 2,                                                             &
         &     nArguments,                                                       &
         &     errorNumber)                                                      !
    ERROR = ERROR .Or. errorNumber
    !
    If (.Not. ERROR) Then
       Call pakoMessageSwitch (setOn = .True.)
       !
       Include 'inc/parameters/parametersOffsetsSourceName.inc'
       Include 'inc/options/readOptionsOnOff.inc'
       !
       ! NB: swWobbler gets evaluated last, so that
       !     it  overrules other parameters and options 
       Include 'inc/options/optionSwWobbler.inc'
       !
    End If
    !
    ! *** set defaults ***
    Include 'inc/options/optionDefaults.inc'
    !
    ! *** read Parameters, Options (again, after defaults!) ***
    !     and check for validity and ranges 
    If (.Not. ERROR) Then
       Call pakoMessageSwitch (setOff = .True.)
       !
       Include 'inc/parameters/parametersOffsetsSourceName.inc'
       Include 'inc/options/readOptionsOnOff.inc'
       !
       ! NB: swWobbler gets evaluated last, so that
       !     it  overrules other parameters and options 
       Include 'inc/options/optionSwWobbler.inc'
       !
    End If
    Call pakoMessageSwitch (setOn = .True.)
    !
    ! *** check consistency and                           ***
    ! *** store into temporary (intermediate) variables   ***
    If (.Not.error) Then
       !
       errorInconsistent = .False.
       !
       l = Len_trim(command)
       !
       If (.Not. vars(iIn)%doReference) Then
          errorInconsistent = .True.
          Write (messageText,*) "is required for ONOFF"
          Call pakoMessage(priorityE,severityE,                                  &
               &           command(1:l)//"/"//"REFERENCE",messageText)           !
       End If
       !
       If (vars(iIn)%doReference                                                 &
            &  .And. vars(iIn)%systemNameRef.Ne.vars(iIn)%systemName) Then       !
          errorInconsistent = .True.
          GV%notReadyOnOff  = .True.
          Write (messageText,*) "different values for /SYSTEM ",                 &  
               &  "and /REFERENCE are not yet allowed "                          !
          Call pakoMessage(priorityE,severityE,                                  &
               &           command(1:l)//"/"//"REFERENCE",messageText)           !
       End If
       !
       If (vars(iIn)%tSubscan .Lt. 5*GV%tRecord) Then
          If (vars(iIn)%tSubscan .Lt. 3*GV%tRecord) Then
             errorInconsistent = .True.
             Write (messageText,*)    "must be at least 3 times "                &
                  &                // "tRecord = tPhase*nPhases*nCycles = "      &
                  &                 ,  GV%tRecord                                &
                  &                 , "of switching mode "//GV%switchingMode     !
             Call pakoMessage(priorityE,severityE,                               &
                  &           command(1:l)//"/"//"tSubscan",messageText)         !
          Else
             Write (messageText,*)    "should be at least 5 times "              &
                  &                // "tRecord = tPhase*nPhases*nCycles = "      &
                  &                 ,  GV%tRecord                                &
                  &                 , "of switching mode "//GV%switchingMode     !
             Call pakoMessage(priorityW,severityW,                               &
                  &           command(1:l)//"/"//"tSubscan",messageText)         !
          End If
       End If
       !
       If (Mod(vars(iIn)%nSubscans,2).Ne.0) Then
          errorInconsistent = .True.
          Write (messageText,*) "nSubscans must be a multiple of 2"
          Call pakoMessage(priorityE,severityE,                                  &
               &           command(1:l)//"/"//"nSubscans",messageText)           !
       End If
       !
       If (vars(iIn)%doSymmetric .And. Mod(vars(iIn)%nSubscans,4).Ne.0) Then
          errorInconsistent = .True.
          Write (messageText,*) "for option /SYMMETRIC yes, "//                  &
               &                "/nSubscans must be a multiple of 4"             !
          Call pakoMessage(priorityE,severityE,                                  &
               &           command(1:l),messageText)                             !
       End If
       !
       If (GV%switchingMode.Eq.swMode%Beam) Then
          errorInconsistent = .True.
          GV%notReadyOnOff  = .True.
          Write (messageText,*)  "will not work with switching mode ",           &
               &                 swModePako%Beam                                 !
          Call PakoMessage(priorityE,severityE,command(1:l),messageText)
       End If
       !
       If (GV%switchingMode.Eq.swMode%Freq) Then
          errorInconsistent = .True.
          GV%notReadyOnOff  = .True.
          Write (messageText,*)  "will not work with switching mode ",           &
               &                 swModePako%Freq                                 !
          Call PakoMessage(priorityE,severityE,command(1:l),messageText)
       End If
       !
       If      (       GV%switchingMode.Ne.swMode%Wobb                           &
            &    .And. (      vars(iIn)%doSwWobbler                              &
            &            .Or. vars(iIn)%doSwWobbler )                            &
            &  )                                                                 &
            &  Then                                                              !
          errorInconsistent = .True.
          GV%notReadyOnOff  = .True.
          Write (messageText,*)  "can not use /swWobbler with switching mode ",  &
               &                 GV%switchingMode                                !
          Call PakoMessage(priorityE,severityE,command(1:l),messageText)
          Write (messageText,*)  "first set ",                                   &            
               &                 COMpako%swWobbler                               !
          Call PakoMessage(priorityI,severityI,command(1:l),messageText)
       End If
       !
       Call queryReceiver(rec%bolo, isConnected)
       If (isConnected .And. GV%switchingMode.Eq.swMode%Wobb                     &
            &          .And. Abs(GV%secondaryRotation).GT.0.005) Then            !
          errorInconsistent = .True.
          GV%notReadyOnOff  = .True.
          Write (messageText,*)                                                  &
               &   "does not (yet) work with SWWOBBLER and SET 2ndRotation ",    &
               &                 GV%secondaryRotation                            !
          Call PakoMessage(priorityE,severityE,command(1:l),messageText)
       End If
       !
       iQuery    = vars(iIn)%iSystem
       nameQuery = GPnone
       Call  queryOffsets(iQuery,nameQuery,isSet,pointResult)
       !D              Write (6,*)    "     vars(iIn)%iSystem:   ", vars(iIn)%iSystem
       !D              Write (6,*)    "     isSet:               ", isSet
       If (isSet) Then
          doWarnOffsets = .True.
          Write (messageText,*)  " NOTE: the offsets set with OFFSETS /system "  &
               &                   //vars(iIn)%SystemName//                      &
                                 " will be ignored!"                             !
          Call PakoMessage(priorityW,severityW,command(1:l)//" /SYSTEM",         &
               &                               messageText)                      !
          Write (messageText,*)                                                  &
               &    " -- i.e., they are not added to those of the "              &
               &    //"observing mode ONOFF"                                     !
          Call PakoMessage(priorityW,severityW,                                  &
               &    command(1:l)//" /SYSTEM",                                    &
               &    messageText)                                                 !
       Else
          doWarnOffsets = .False.
       End If
       !
       If (.Not. errorInconsistent) Then
          vars(iTemp) = vars(iIn)
       End If
       !
    End If
    !
    ERROR = ERROR .Or. errorInconsistent
    !
    ! *** store from temporary into final variables ***
    If (.Not.ERROR) Then
       vars(iValue)    = vars(iTemp)
    End If
    !
    ! *** display values ***
    If (.Not. ERROR) Then
       Call displayOnOff
    End If
    !
    ! *** set "selected" observing mode & plot ***
    If (.Not.error) Then
       GV%observingMode     = OM%onOff
       GV%observingModePako = OMpako%onOff
       GV%omSystemName      = vars(iValue)%systemName 
       GV%notReadySWafterOM = .False.
       GV%notReadySecondaryRafterOM = .False.
       GV%notReadyOffsetsAfterOnOff  = .False.
       GV%notReadyOnOff     = .False.
       OnOffCommand         = line(1:lenc(line))
       Call analyzeOnOff (errorA)
       Call listSegmentList (errorA)
       Call plotOMOnOff (errorP)
    End If
    !
    Return
  End Subroutine OnOff
!!!
!!!
  Subroutine analyzeOnOff (errorA)
    !
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Integer                :: nScan 
    Character (len=lenCh)  :: aUnit, sUnit
    Integer                :: iSS           = 0     ! counts subcans/segment
    Integer                :: nSS           = 1
    !
    Integer                :: iQuery
    Character(len=lenCh)   :: nameQuery
    Logical                :: isSet
    Type(xyPointType)      :: pointResult
    !
    errorA    = .False.
    iSS       = 0
    nScan     = 1111
    aUnit     = GV%angleUnitC                        ! 
    sUnit     = GV%speedUnitC                        ! 
    !
    ! TBD: calibrate subscans 
    !
    segList(:) = segDefault
    !
    Call countSubscans(value=0)
    Call countSegments(value=0)
    !
    Do kk = 1, vars(iValue)%nSubscans, 1
       !
       Call countSubscans(ii)
       Call countSegments(jj)
       !
       If      (                                                                 &
            &       .Not.vars(iValue)%doSymmetric .And. Mod(kk,2) .Eq. 0         &
            &   .Or.     vars(iValue)%doSymmetric .And. Mod(kk,4) .Eq. 2         &
            &   .Or.     vars(iValue)%doSymmetric .And. Mod(kk,4) .Eq. 3         &
            &  ) Then                                                            !
          !!  ** ON-source 
          segList(ii)%newSubscan =  .True.
          segList(ii)%scanNumber =  nScan
          segList(ii)%ssNumber   =  ii
          segList(ii)%segNumber  =  1
          segList(ii)%ssType     =  ss%track
          segList(ii)%segType    =  seg%track
          segList(ii)%angleUnit  =  aUnit
          segList(ii)%speedUnit  =  sUnit
          segList(ii)%flagOn     =  .True.
          segList(ii)%flagRef    =  .False.
          segList(ii)%pStart     =  vars(iValue)%offset
          segList(ii)%pEnd       =  segList(ii)%pStart
          segList(ii)%speedStart =  0.0
          segList(ii)%speedEnd   =  0.0
          segList(ii)%systemName =  vars(iValue)%systemName
          segList(ii)%altOption  =  'tSegment'
          segList(ii)%tSegment   =  vars(iValue)%tSubscan
          segList(ii)%tRecord    =  0.1
       Else If (                                                                 &
            &        .Not.vars(iValue)%doSymmetric .And. Mod(kk,2) .Eq. 1        &
            &   .Or.      vars(iValue)%doSymmetric .And. Mod(kk,4) .Eq. 1        &
            &   .Or.      vars(iValue)%doSymmetric .And. Mod(kk,4) .Eq. 0        &
            &  ) Then                                                            !
          !!  ** OFF-source Reference
          segList(ii)%newSubscan =  .True.
          segList(ii)%scanNumber =  nScan
          segList(ii)%ssNumber   =  ii
          segList(ii)%segNumber  =  1
          segList(ii)%ssType     =  ss%track
          segList(ii)%segType    =  seg%track
          segList(ii)%angleUnit  =  aUnit
          segList(ii)%speedUnit  =  sUnit
          segList(ii)%flagOn     =  .False.
          segList(ii)%flagRef    =  .True.
          segList(ii)%pStart     =  vars(iValue)%offsetR
          segList(ii)%pEnd       =  segList(ii)%pStart
          segList(ii)%speedStart =  0.0
          segList(ii)%speedEnd   =  0.0
          segList(ii)%systemName =  vars(iValue)%systemNameRef
          segList(ii)%altOption  =  'tSegment'
          segList(ii)%tSegment   =  vars(iValue)%tSubscan
          segList(ii)%tRecord    =  0.1
          !
          iQuery    = iPro
          nameQuery = GPnone
          Call  queryOffsets(iQuery,nameQuery,isSet,pointResult)
          !
          If (ii.Eq.1) Then
             segList(ii)%updateDoppler = .True.
             If (vars(iValue)%systemName.Eq.offs%pro) Then
                segList(ii)%pDoppler      = vars(iValue)%offset
             Else
                segList(ii)%pDoppler      = xyPointType(0.0,0.0)
             End If
             If (isSet .And. vars(iValue)%systemName.Ne.offs%pro) Then  !  OFFSETS /SYS PROJ
                segList(ii)%pDoppler      = pointResult
             End If
          Else If (GV%doDopplerUpdates) Then
             segList(ii)%updateDoppler = .True.
             If (vars(iValue)%systemName.Eq.offs%pro) Then
                segList(ii)%pDoppler      = vars(iValue)%offset
             Else
                segList(ii)%pDoppler      = xyPointType(0.0,0.0)
             End If
             If (isSet .And. vars(iValue)%systemName.Ne.offs%pro) Then  !  OFFSETS /SYS PROJ
                segList(ii)%pDoppler      = pointResult
             End If
          End If
          !
       End If
       !
    End Do
    !
    Call getCountSegments(nSegments)
    !
   Return 
    !
  End Subroutine analyzeOnOff
!!!
!!!
  Subroutine displayOnOff
    !
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Character(len=24)  :: command
    !
    Include 'inc/display/commandDisplayOnOff.inc'
    !
  End Subroutine displayOnOff
!!!
!!!
  Subroutine plotOMOnOff (errorP)
    !
    !**   Variables  for Plots   ***
    Include 'inc/variables/headerForPlotMethods.inc'
    !
    !**   standard working variables   ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    errorP = .False.
    !
    Call configurePlots
    !
    Call plotOnOffStart(errorP)
    !
    Call plotSegmentList(errorP)
    !
    If (errorP)                                                                  &
         &        Call pakoMessage(priorityE,severityE,                          &
         &        'OnOff',' could not plot ')                                    !
    !
    Return
  End Subroutine plotOMOnOff
!!!
!!!
  Subroutine saveOnOff(programName,LINE,commandToSave,                           &
       &        iUnit, ERROR)                                                    !
    !
    !**   Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !      
    contC = contNN
    !
    Include 'inc/commands/saveCommand.inc'
    !
    contC = contCC
    !
    Include 'inc/parameters/saveOffsets.inc'
    !
    !TBD:      Include 'inc/options/saveBalance.inc'
    !TBD:      Include 'inc/options/saveCalibrate.inc'
    Include 'inc/options/saveNsubscans.inc'
    Include 'inc/options/saveReference.inc'
    Include 'inc/options/saveSymmetric.inc'
    Include 'inc/options/saveSystem.inc'
    !
    contC = contCN
    !
    Include 'inc/options/saveTsubscan.inc'
    !
    Write (iUnit,*) "!"
    !
    Return
  End Subroutine saveOnOff
!!!
!!!
  Subroutine startOnOff(programName,LINE,commandToSave,iUnit, ERROR)
    !
    ! *** Variables ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Integer                 :: ii
    Character (len=lenCh)   :: valueC
    Character (len=lenLine) :: valueComment
    Character (len=lenLine) :: messageText
    Logical                 :: errorL, errorXML
    !
    Call pakoXMLsetOutputUnit(iunit=iunit)
    Call pakoXMLsetIndent(iIndent=2)
    !
    Include 'inc/startXML/generalHead.inc'
    !
    ERROR = .False.
    !
    Call pako_message(seve%t,programName,                                        &
         &  " module OnOff, v 1.2.0  --> SR: startOnOff ")                       ! trace execution
    !
    Call writeXMLset(programName,LINE,commandToSave,iUnit, ERROR)
    !
    Call pakoXMLwriteStartElement("RESOURCE","pakoScript",                       &
         &                         comment="save from pako",                     &
         &                         error=errorXML)                               !
    Call pakoXMLwriteStartElement("DESCRIPTION",                                 &
         &                         doCdata=.True.,                               &
         &                         error=errorXML)                               !
    !
    Include 'inc/startXML/savePakoScriptFirst.inc'
    !
    Call saveOnOff        (programName,LINE,commandToSave, iUnit, errorL)
    !                                                                       
    Call pakoXMLwriteEndElement("DESCRIPTION",                                   &
         &                         doCdata=.True.,                               &
         &                         error=errorXML)                               !
    Call pakoXMLwriteEndElement  ("RESOURCE","pakoScript",                       &
         &                         space="after",                                &
         &                         error=errorXML)                               !
    !
    Call writeXMLantenna(programName,LINE,commandToSave,iUnit, ERROR)
    !
    Call writeXMLreceiver(programName,LINE,commandToSave,iUnit, ERROR)
    !
    Call writeXMLbackend(programName,LINE,commandToSave,iUnit, ERROR)
    !
    Include 'inc/startXML/switchingMode.inc'
    !
    Call writeXMLsource(programName,LINE,commandToSave,iUnit, ERROR)
    !
    Include 'inc/startXML/generalScanHead.inc'
    !
    ! **  Observing Mode to XML
    If (gv%doXMLobservingMode) Then
       messageText = "writing observing mode in XML format"
       Call PakoMessage(priorityI,severityI,                                     &
               &           commandToSave,messageText)                            !
       Call writeXMLonOff(programName,LINE,commandToSave,                        &
         &         iUnit, ERROR)                                                 !
    End If
    !
    ! **  subscan list to XML
    Call writeXMLsubscanList(programName,LINE,commandToSave,iUnit, ERROR)
    !   
    Include 'inc/startXML/generalTail.inc'
    !
    Return
  End Subroutine startOnOff
!!!
!!!
  Subroutine writeXMLonOff(programName,LINE,commandToSave,iUnit,ERROR)
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Integer                 :: ii, iMatch, nMatch, len1, len2
    Character (len=lenCh)   :: valueC, errorCode
    Character (len=lenLine) :: valueComment
    Logical                 :: errorL, errorM, errorXML
    !
    Call pako_message(seve%t,"PAKO",                                             &
         &  " module OnOff, v 1.2.3  --> SR: writeXMLOnOff 2014-10-27")          ! trace execution
    !
    ERROR = .False.
    !
    Call pakoXMLwriteStartElement("RESOURCE","observingMode",                    &
         &                         space ="before",                              &
         &                         error=errorXML)                               !
    !
    valueC = GV%observingMode
    Call pakoXMLwriteElement("PARAM","observingMode",valueC,                     &
         &                         dataType="char",                              &
         &                         error=errorXML)                               !
    !
    Include 'inc/startXML/parametersOffsetsXML.inc'
    !
    Include 'inc/startXML/optionSystemXML.inc'
    Include 'inc/startXML/optionReferenceXML.inc'
    Include 'inc/startXML/optionNsubscansXML.inc'
    Include 'inc/startXML/optionTsubscanXML.inc'
    Include 'inc/startXML/optionSymmetricXML.inc'
    Include 'inc/startXML/optionSwWobblerXML.inc'
    !
    Include 'inc/startXML/annotationsXML.inc'
    !
    Call pakoXMLwriteEndElement("RESOURCE","observingMode",                      &
         &                         error=errorXML)                               !
    !
    Return
  End Subroutine writeXMLonOff
!!!
!!!
End Module modulePakoOnOff
