!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer,
!                     version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer
!version 3 or (at your option) any later version that should be found at:
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software;
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec),
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
!

subroutine tovs_calc_jo(pjo,llprint,lobsSpaceData,dest_obs) 1,25
#if defined (doc)
!
!**s/r tovs_calc_jo  - computation of jo and the residuals to the tovs observations
!                     (adapted from part of code of dobstovs)
!
!
!author        : j. halle *cmda/aes  december 14, 2004
!
!revision 001  : a. beaulne *cmda/smc  june 2006
!                  -modifications for AIRS (codtyp 183)
!
!revision 002  : r. sarrazin cmda  april 2008
!                  -modifications for CSR (codtyp 185)
!
!revision 003  : s. heilliette
!                  -modifications for IASI (codtyp 186)
!
!revision 004  : s. heilliette
!                  -modifications for RTTOV-10 (December 2010)
!
!revision 005  : s. macpherson
!                  -modifications for ATMS (codtyp 192)
!                  -modifications for CrIS (codtyp 193)
!revision 006  : s. macpherson  nov 2012
!                  - remove #include "comtovst.cdk"
!    -------------------
!     purpose:
!
!arguments
!     pjo: total value of jo for tovs
!
#endif
  use rmatrix_mod
  use tovs_nl_mod
  use obsSpaceData_mod

  implicit none

  real(8) :: pjo
  logical :: llprint
  type(struct_obs) :: lobsSpaceData
  integer, intent(in) :: dest_obs       ! probably set to OBS_OMP or OBS_OMA

  integer :: isens, indxchn, indxtovs
  real*8 dlsum, zdtb, zjon,zgami,zqcarg
  real*8 zjoch  (0:jpchmax,jpnsatmax)
  real*8 zavgnrm(0:jpchmax,jpnsatmax)
  integer j, i, krtid, nchanperline, indxs, indxe
  integer inobsjo, incanjo
  integer idatyp
  integer ichn, ichOBS_A, jl
  integer inobsch(0:jpchmax,jpnsatmax)
  integer lcanjo(jpchmax)
  integer :: index_header, index_body
 
  real (8) :: x(jpchmax),y(jpchmax)
  integer :: list_chan(jpchmax)
  integer :: count

  integer  isrcheq
  external isrcheq
  external abort3d

  write(*,*) "Entering tovs_calc_jo subroutine"

  if(NOBTOV.eq.0) return    ! exit if there are not tovs data

  ! 1.  Computation of (hx - z)/sigma for tovs data only
  !     ------------------------------------------------

  dlsum    = 0.D0
  inobsjo  = 0
  do j = 1, nsensors
     do i = 0, jpchmax
        inobsch(i,j) = 0
        zjoch  (i,j) = 0.0D0
        zavgnrm(i,j) = 0.0D0
     enddo
  enddo

  ! loop over all header indices of the 'TO' family
  call obs_set_current_header_list(lobsSpaceData,'TO')
  HEADER: do
     index_header = obs_getHeaderIndex(lobsSpaceData)
     if (index_header < 0) exit HEADER

     ! 1.1  Extract general information for this observation point
     !      ------------------------------------------------------

     ! process only radiance data to be assimilated?
     idatyp = obs_headElem_i(lobsSpaceData,OBS_ITY,index_header)
     if ( .not. tvs_Is_idburp_tovs(idatyp) ) cycle HEADER

     indxtovs = ltovsno(index_header)
     if ( indxtovs .eq. 0 ) then
        write(*,fmt=9203)
9203    format(' tovs_calc_jo: error with indxtovs')
        call abort3d('tovs_calc_jo    ')
     endif

     isens = lsensor(indxtovs)

     ! Set the body list
     ! (& start at the beginning of the list)
     call obs_set_current_body_list(lobsSpaceData, index_header)
     count=0
     BODY: do 
        index_body = obs_getBodyIndex(lobsSpaceData)
        if (index_body < 0 ) then
           if (count>0 .and. rmat_lnondiagr) then
              call rmat_sqrtRm1(isens,count,x(1:count),y(1:count),list_chan(1:count),indxtovs)
              dlsum =  dlsum + 0.5d0*dot_product(y(1:count),y(1:count))
           endif
           exit BODY
        endif

        ! Only consider if flagged for assimilation
        if ( obs_bodyElem_i(lobsSpaceData,OBS_ASS,index_body).ne.1 ) cycle BODY                

        ichn = nint(obs_bodyElem_r(lobsSpaceData,OBS_PPP,index_body))
        ichn = max(0,min(ichn,jpchmax+1))
        ichOBS_A = max(0,min(ichn,jpchmax+1))
        ichn=ichn-chanoffset(isens)
        indxchn = isrcheq (ichan(:,isens),nchan(isens),ichn)
        if ( indxchn .eq. 0 ) then
           write(*,fmt=9202)
9202       format(' tovs_calc_jo: error with channel number')
           call abort3d('tovs_calc_jo    ')
        endif

        zdtb =   obs_bodyElem_r(lobsSpaceData,OBS_PRM,index_body) - &
                 radiance_d (indxtovs) % bt(indxchn)
        if ( ldbgtov ) then
           write(*,'(a,i4,2f8.2,f6.2)') ' ichn,sim,obs,diff= ', &
                        ichn,  radiance_d (indxtovs) % bt(indxchn), &
                        obs_bodyElem_r(lobsSpaceData,OBS_PRM,index_body), -zdtb
        endif
        call obs_bodySet_r(lobsSpaceData,dest_obs,index_body, zdtb)

        ! Comment out the modification of Jobs due to varqc for now, since this is probably
        ! only needed for use of nonlinear obs operator in minimization, which is not yet
        ! functional, but this interferes with doing ensemble of analyses (M. Buehner, Dec. 2013)
        !if (.not. min_lvarqc .or. obs_bodyElem_r(lobsSpaceData,OBS_POB,index_body).eq.0.0d0) then
        dlsum =  dlsum &
             + (obs_bodyElem_r(lobsSpaceData,dest_obs,index_body)* &
                obs_bodyElem_r(lobsSpaceData,dest_obs,index_body)) &
             / (2.D0 * obs_bodyElem_r(lobsSpaceData,OBS_OER,index_body) &
              * obs_bodyElem_r(lobsSpaceData,OBS_OER,index_body))
        !else
        !  compute contribution of data with varqc
 
        !   zgami = obs_bodyElem_r(lobsSpaceData,OBS_POB,index_body)
        !   zjon = (obs_bodyElem_r(lobsSpaceData,dest_obs,index_body)* &
        !           obs_bodyElem_r(lobsSpaceData,dest_obs,index_body))/2.D0
        !   zqcarg = zgami + exp(-1.0D0*zjon)
        !   dlsum= dlsum - log(zqcarg/(zgami+1.D0))
        !endif
        count=count+1
        x(count)=zdtb
        list_chan(count)=ichn

        inobsjo = inobsjo + 1
        inobsch(ichOBS_A,Isens) = inobsch(ichOBS_A,Isens) + 1
        zjoch(ichOBS_A,Isens)   = &
             zjoch(ichOBS_A,Isens) &
             + obs_bodyElem_r(lobsSpaceData,dest_obs,index_body)* &
               obs_bodyElem_r(lobsSpaceData,dest_obs,index_body) &
            / (obs_bodyElem_r(lobsSpaceData,OBS_OER,index_body)* &
               obs_bodyElem_r(lobsSpaceData,OBS_OER,index_body))
        zavgnrm(ichOBS_A,Isens)   = &
             zavgnrm(ichOBS_A,Isens) - &
             obs_bodyElem_r(lobsSpaceData,dest_obs,index_body)/ &
             obs_bodyElem_r(lobsSpaceData,OBS_OER,index_body)
     enddo BODY

  enddo HEADER

  !   2.  Close up, print summary
  !   .   -----------------------

  pjo = dlsum

  ! printout of mean jo and normalized average for each sensor.

  nchanperline = 18
  if ( llprint .and. inobsjo .gt. 0 ) then
     write(*,fmt=9000)
     do krtid = 1, nsensors
        do i = 1, jpchmax
           inobsch(0,krtid) = inobsch(0,krtid) + &
                              inobsch(i,krtid)
           zjoch(0,krtid)   = zjoch(0,krtid) + &
                              zjoch(i,krtid)
           zavgnrm(0,krtid) = zavgnrm(0,krtid) + &
                              zavgnrm(i,krtid)
        enddo
     enddo

     do jl = 1, nsensors
        incanjo = 0
        do i = 0, jpchmax
           if ( inobsch(i,jl) .ne. 0 ) then
              incanjo = incanjo + 1
              lcanjo(incanjo) = i
           endif
        enddo
        if ( incanjo .ne. 0 ) then
           write(*,'(/1x,"sensor #",i2,". platform: ",a, &
                          &   "instrument: ",a)') &
                          jl, csatid(jl), cinstrumentid(jl)
           do j = 1, incanjo, nchanperline
              indxs = j
              indxe = min(j+nchanperline-1,incanjo)
              if ( j .eq. 1 ) then
                 write(*,'(1x,"channel",t13,"   all",17i6)') &
                    (lcanjo(i),i=indxs+1,indxe)
              else
                 write(*,'(1x,"channel",t13,18i6)') &
                    (lcanjo(i),i=indxs,indxe)
              endif
              write(*,'(1x,"no. obs.",t13,18i6)') &
                 (inobsch(lcanjo(i),jl),i=indxs,indxe)
              write(*,'(1x,"mean jo",t13,18f6.2)') &
                 (zjoch(lcanjo(i),jl)/max(1,inobsch(lcanjo(i),jl)) &
                 ,i=indxs,indxe)
              write(*,'(1x,"norm. bias",t13,18f6.2,/)') &
                 (zavgnrm(lcanjo(i),jl)/max(1,inobsch(lcanjo(i),jl)) &
                 ,i=indxs,indxe)
           enddo
        endif
     enddo
  endif

 9000 format(//,10x,"-tovs_calc_jo: computing jo and residuals to tovs" &
        &  ," observations")

end subroutine tovs_calc_jo