!-------------------------------------- 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 rebldnotag 1,12

#if defined (DOC)
*
***s/r rebldnotag   
*
*Author  : Bin He  *ARMA/MRB   FEB., 2009
*
*Revision:
*         Bin He   *ARMA/MRB  Feb. 2009 
*                   . MPI version 
*        Bin He   - ARMA/MRB   - Oct. 2011,
*                 - 4Dvar optimization.

*Arguments: none
*
#endif
      use modfgat
      use mod4dv, only: l4dvar 
      USE procs_topo  
      IMPLICIT NONE
*implicits
#include "comdim.cdk"
#include "comdimo.cdk"
#include "comlun.cdk"
#include "comcst.cdk"
#include "comoabdy.cdk"
#include "comoahdr.cdk"
#include "comoba.cdk"
#include "comgdpar.cdk"
#include "cvcord.cdk"
#include "comfilt.cdk"
#include "comct0.cdk"
#include "comvfiles.cdk"
#include "comsv.cdk"
#include "comcva.cdk"
#include "cparamgoes.cdk"
#include "comgoes.cdk"
*
      integer jobs, iobs,ig1obs, ig2obs, ig3obs, ig4obs, newdate
      integer vezgdef, ierr,istepstamp,jstep,istat,ihdl,ihdl01
      integer :: icode,jvar,getprofcode, ireslun
      integer :: idate, itime, idata,idatend, jdata,itimeout,fnom
      integer :: jo,istart,ifle,jj,istep,ifamid,ifile 
      character(len=2) :: cljx, cljy,cistep
      integer :: istep1  

      integer :: maxnobs 

      real*8 zig1,zig2,zig3,zig4
*
      real*8, allocatable, dimension(:,:) ::  dlatfld, dlonfld
      integer :: i,nobtotmax 
      integer,allocatable,dimension(:) :: allnobtot 
      logical :: llflag,lltimein
      logical,dimension(nstepobs) :: lfirst
      integer :: omp_get_max_threads

      write(nulout,*) 'ReBldNobtag: Step obs : ',dstepobs,' hours'
      nstepobs = 2*nint((3.d0 - dstepobs/2.d0)/dstepobs) + 1
      write(nulout,*) 'ReBldNobtag: Number of step obs : ',nstepobs

      allocate(nobs(nstepobs))
      nobs=0
      allocate(nobsgid(nstepobs))
      nobsgid=0
      allocate(nstart(nstepobs,nfiles),stat=ierr)
      nstart=0
      allocate(nend(nstepobs,nfiles),stat=ierr)
      nend=0

      allocate(notag(nobtot,nstepobs))
      notag=0
      allocate(dlatfld(nobtot,nstepobs))
      dlatfld=0.0d0
      allocate(dlonfld(nobtot,nstepobs))
      dlonfld=0.0d0
!
      allocate(nobs_to(nstepobs),stat=ierr)
       nobs_to=0
      allocate(nobs_go(nstepobs),stat=ierr)
       nobs_go=0
  
      allocate(nobs_ro(nstepobs),stat=ierr)
       nobs_ro=0
      allocate(nobs_gp(nstepobs),stat=ierr)
       nobs_gp=0

      allocate(astepobs(nstepobs),stat=ierr) 
       do jj=1,nstepobs
         astepobs(jj)=jj
       enddo 
!-----------
      id_nonzero=0
!--------------------------------------------------------
!     allocate mem to robdata8_loc
      allocate(robdata8_loc(ndata),stat=ierr)  
       robdata8_loc=0.0D0 
!-------------
       numthreads=omp_get_max_threads()
!
      call getstamplist(NSTAMPLIST,nstepobs,nbrpstamp,dstepobs)

      do jstep = 1, jpfiles
        ntimeout(jstep) = 0
      enddo

      do jstep = 1, nstepobs
        nobs(jstep) = 0
      enddo
  
      write(*,*) 'NOBTOT= ',nobtot 

      !!IF(nobtot==0) RETURN 
      do jobs=1, nobtot
! return the step stamp associated whit date and time of the observation

c spe : for normal use uncomment the call to stepobs and comment the
C following line (istepstamp = nstamplist(1))
 
        call stepobs(ISTEPSTAMP,nbrpstamp,mobhdr(ncmdat,jobs)
     &       ,mobhdr(ncmetm,jobs),dstepobs)

c        ISTEPSTAMP = nstamplist(1)
! building the list of step stamp and counting number of obs in each step
        lltimein = .false.
        step : do jstep = 1,nstepobs
          if (nstamplist(jstep) == istepstamp) then
            nobs(jstep) = nobs(jstep) + 1
            lltimein = .true.
            exit step
          endif
        enddo step

        if (.not. lltimein) then
          ntimeout(mobhdr(ncmotp,jobs))=ntimeout(mobhdr(ncmotp,jobs))+1
          write(nulout,*) 'Report time for obs no. ',jobs
     &         ,' out of range : ', mobhdr(ncmdat,jobs),
     &         mobhdr(ncmetm,jobs)

! Put put the wrong data in the central bin
          jstep = (nstepobs + 1) / 2
          nobs(jstep) = nobs(jstep) + 1

! .. flag it as out of (time) domain (bit #5 of header flag
! .. and turn off its assimilation flag

          idata = mobhdr(ncmrln,jobs)
          idatend = mobhdr(ncmnlv,jobs) + idata -1
          do jdata = idata, idatend
            MOBDATA(NCMASS,JDATA) = 0
          enddo
          mobhdr(ncmst1,jobs)= ibset( mobhdr(ncmst1,jobs) , 05)
        endif
! building the lat, long and tag vectors for each step

        dlatfld(nobs(jstep),jstep) = robhdr(ncmlat,jobs)
        dlonfld(nobs(jstep),jstep) = robhdr(ncmlon,jobs)
        notag(nobs(jstep),jstep) = jobs

! Converting lat long to radian units

        if(dlonfld(nobs(jstep),jstep).lt.0)
     &       dlonfld(nobs(jstep),jstep) = dlonfld(nobs(jstep),jstep) +
     &       2*rpi
        if(dlonfld(nobs(jstep),jstep).ge.2.*rpi)
     &       dlonfld(nobs(jstep),jstep) =dlonfld(nobs(jstep),jstep) -
     &       2*rpi
        dlatfld(nobs(jstep),jstep)=dlatfld(nobs(jstep),jstep)*180./rpi
        dlonfld(nobs(jstep),jstep)=dlonfld(nobs(jstep),jstep)*180./rpi

      enddo

      itimeout = 0
      do jstep = 1,nfiles
        itimeout = ntimeout(jstep) + itimeout
      enddo
!! calculate the start and end index for each time step of a family 
       jj=0
       nstart=0
       nend=0
!!     for O-P or O-A , skipping this block ...
       if(nconf == 141) then  
       do ifile=1,Nfiles
         do istep=1,nstepobs
           lfirst(istep)=.true.
           !!!bhe **      jj=0
           do iobs=1,nobs(istep)  
             jobs=notag(iobs,istep)
             ifamId = MOBHDR(NCMOEC,jobs)
             istart=MOBHDR(NCMRLN,jobs)
             idata=MOBHDR(NCMNLV,jobs)   
             CALL stepobs(ISTEPSTAMP,nbrpstamp,mobhdr(NCMDAT,jobs)
     &       ,mobhdr(NCMETM,jobs),dstepobs)

              if(ifamId == ifile) then
                 if(nstamplist(istep) == ISTEPSTAMP ) then
                   IF(LFIRST(istep)) THEN
                      nstart(istep,ifile)=istart 
                      jj=istart
                      Lfirst(istep)=.false.
                   ENDIF 
                   jj=jj+idata  
                 endif  
              endif
           enddo 

           nend(istep,ifile)=jj-1
           if(nstart(istep,ifile) == 0) nend(istep,ifile)=0

           print*,'nstart(istep,ifile) nend(istep,ifile)= ',ifile,nstart(istep,ifile),nend(istep,ifile) 
           
        enddo 
      enddo 
      endif !! end of skipping for O-A or O-P .... 
      if(itimeout > 0) then
        write(nulout,*) 'Number of reports with time out of range :',
     &       itimeout
        write(nulout,*) '  FAMILY       No. of reports'
        do jstep = 1,nfiles
          write(nulout,'(4x,a2,11x,i5)') CFAMTYP(jstep),ntimeout(jstep)
        enddo
      endif

      zig1 = 0.0D0
      zig2 = 0.0D0
      zig3 = 1.0D0
      zig4 = 1.0D0

      call vcxgaig('L',ig1obs, ig2obs, ig3obs, ig4obs,
     .             zig1, zig2, zig3, zig4)
c
      maxnobs=maxval(nobs) 

      write(nulout,*) 'STEP OBS NO. -  DATE -  TIME -  Nbr. of obs.'
      do jstep = 1,nstepobs
        if (jstep == (nstepobs+1)/2) then
          iobs = nobs(jstep) - itimeout
        else
          iobs = nobs(jstep)
        endif

        ierr = newdate(nstamplist(jstep),idate,itime,-3)
        write(nulout,'(6x,i2,5x,i10,2x,i4.4,5x,i5)') jstep,idate,itime
     &       /10000,iobs
        if (nobs(jstep) .gt. 0) then
          nobsgid(jstep) = vezgdef(nobs(jstep),1,'Y','L',ig1obs,ig2obs,
     &         ig3obs,ig4obs,dlonfld(1:nobs(jstep),jstep)
     &         ,dlatfld(1:nobs(jstep),jstep))
        else
          nobsgid(jstep) = -999
        endif
      enddo

      deallocate(dlatfld)
      deallocate(dlonfld)
!! bhe.. for O-P or O-A skipping following block..
      if(NCONF == 141 ) THEN 
c
c     Looking for the last step file containing observations 
c     ------------------------------------------------------
      istepobs_first=1
       do jstep = 1,nstepobs
        if (nobs(jstep) .gt. 0) then
          istepobs_first=jstep
          exit  
        endif 
      enddo

      !istepobs_last=0
      do jstep = nstepobs,1,-1
        if (nobs(jstep) .gt. 0) goto 999
      enddo
  999 continue
      istepobs_last=jstep
c     If no obs in any jstep, set istepobs_last = nstepobs 
      if (istepobs_last.eq.0) istepobs_last = nstepobs
      write(nulout,*) 'ISTEPOBS_LAST containing observations = ',istepobs_last
      istep1=istepobs_last-1
      write(cljx,'(i2.2)') myidx
      write(cljy,'(i2.2)') myidy
      write(cistep,'(i2.2)') istep1
      IF(l4dvar) TL_prof_file = trim(CEXC4DV) // '/' // cljx//'_'// cljy //'_'// cistep // '/dwyf_'//cljx//'_'//cljy//'_'//cistep//'.prof'
c
      do ifile=1,NFILES 
        if(cfamtyp(ifile) == 'TO' .and. nbegintyp(ifile) >0 )then
          allocate(nobtag_to(maxnobs,nstepobs),stat=ierr)
          nobtag_to=0
          CALL getFamilyTag('TO',nobtag_to,nobs_to)
        else if(cfamtyp(ifile) == 'GO' .and. nbegintyp(ifile) >0 )then
          allocate(nobtag_go(maxnobs,nstepobs),stat=ierr)
          nobtag_go=0
          CALL getFamilyTag('GO',nobtag_go,nobs_go)
        else if(cfamtyp(ifile) == 'RO' .and. nbegintyp(ifile) >0 )then
          allocate(nobtag_ro(maxnobs,nstepobs),stat=ierr)
          nobtag_ro=0
          CALL getFamilyTag('RO',nobtag_ro,nobs_ro)
        else if(cfamtyp(ifile) == 'GP' .and. nbegintyp(ifile) >0 )then
          allocate(nobtag_gp(maxnobs,nstepobs),stat=ierr)
          nobtag_gp=0
          CALL getFamilyTag('GP',nobtag_gp,nobs_gp)
       endif 

      enddo 

! find the processor id (id_nonzero) which has maximum number of observations. 
      allocate(allnobtot(nprocs)) 
      allnobtot=0
      !bhecall rpn_comm_allgather(nobtot,1,"MPI_INTEGER",allnobtot,1,"MPI_INTEGER","GRID",ierr) 
      call rpn_comm_gather(nobtot,1,"MPI_INTEGER",allnobtot,1,"MPI_INTEGER",0,"GRID",ierr) 
      call rpn_comm_bcast(allnobtot,nprocs,"MPI_INTEGER",0,"GRID",ierr) 

      nobtotmax=allnobtot(1)
      id_nonzero=0
      do i=1,nprocs-1
       if(nobtotmax<allnobtot(i+1) ) then
         nobtotmax=allnobtot(i+1)
         id_nonzero=i
       endif 

      enddo   
      write(nulout,*) 'Maximum number of obs. at the processor: ',id_nonzero 
      deallocate(allnobtot) 
      ENDIF  !! End of skipping... for O-P and O-A...   
      write(nulout,*) ' '
      write(nulout,*) '-------- END OF ReBldNobtag ---------'
      write(nulout,*) ' '
c
      contains


      subroutine getFamilyTag(cfam,iobtag,sobs) 4
         CHARACTER*2,intent(IN) :: cfam
         integer,dimension(:,:),intent(INOUT) :: iobtag
         integer,dimension(:),intent(INOUT) :: sobs

         integer :: jf ,iobs ,istep 
         integer :: jj,jbegin,jlast,ibeginob,ilastob  
         integer :: idatyp, idata,idatend,  isat ,ksat 
         logical :: assim 

         jj=0
         DO jf=1,NFILES
          IF(cfam .EQ. cfamtyp(jf))THEN
             DO istep=1,nstepobs
                jj=0
                jbegin=nstart(istep,jf) 
                jlast=nend(istep,jf)
                if(jbegin == 0 .and. jlast == 0) goto 88 
                ibeginob=MOBDATA(NCMOBS,jbegin)
                ilastob=MOBDATA(NCMOBS,jlast)
                do jo=ibeginob,ilastob
                  IDATYP = MOD(MOBHDR(NCMITY,JO),1000)
                  if(cfam == 'TO') then
                    IF ( IDATYP .EQ. 164 .OR. 
     +                 IDATYP .EQ. 168 .OR. 
     +                 IDATYP .EQ. 180 .OR. 
     +                 IDATYP .EQ. 181 .OR. 
     +                 IDATYP .EQ. 182 .OR. 
     +                 IDATYP .EQ. 183 .OR.      
     +                 IDATYP .EQ. 185 .OR.      
     +                 IDATYP .EQ. 186) THEN
                    jj=jj+1
                    iobtag(jj,istep)=jo 
                   endif
                 else if(cfam == 'GO') Then
                   DO ksat=1,NSATGO
                   IF ( IDATYP .EQ. 180  ) THEN
                     IDATA   = MOBHDR(NCMRLN,JO)
                     IDATEND = MOBHDR(NCMNLV,JO) + IDATA - 1
                     ASSIM = .FALSE.
                     DO JDATA= IDATA, IDATEND
                     IF ( MOBDATA(NCMASS,JDATA).EQ.1 ) THEN
                        ASSIM = .TRUE.
                     ENDIF
                     ENDDO
                     ISAT = MOD(MOBHDR(NCMITY,JO)/1000,1000)
 
                     ISAT  = ISAT - 244
                     IF ( ASSIM .AND. (ISAT .EQ. NIDSATGO(KSAT)) ) THEN
                     jj=jj+1
                     iobtag(jj,istep)=jo
                     ENDIF
                    ENDIF
                   ENDDO
                 else 
                    jj=jj+1
                    iobtag(jj,istep)=jo
                 endif
                enddo  !! JO 
88              sobs(istep)=jj
             ENDDO ! istep 
          ENDIF
         ENDDO 
         print*,'size of sobs(istep) =',sobs(1:nstepobs) 
         print*,'return getFamilyTag: ',cfam 
 
      end subroutine getFamilyTag  

      end subroutine rebldnotag