program horiz
  use oznmon_read_diag

  implicit none
  integer ntype, mls2_levs,mls3_levs
  parameter (ntype=4)
  parameter (mls2_levs=37)
  parameter (mls3_levs=55)

  logical first

  character(6),dimension(ntype):: var_list
  character(6),dimension(ntype):: ges_vars
  character(6),dimension(ntype):: anl_vars
  character(8) stid
  character(20) satname,stringd,satsis
  character(10) dum,satype,dplat
  character(40) string,grad_file,ctl_file
  character(500) diag_oz

  integer luname,lungrd,lunctl,lndiag,isave
  integer iyy,imm,idd,ihh,idhh,incr,iread,irite,iflag
  integer n_levs,j,nlev,nflag,i,nlevs,nobs,iobs,m_levs,k,lev_nobs
  integer,allocatable,dimension(:):: iuse

  real weight,rlat,rlon,rtim,rmiss,obs,ges,obsges,sza,fovn,toqf
  real,allocatable,dimension(:):: error,dlat,dlon
  real,allocatable,dimension(:):: prs_nlev
  real,allocatable,dimension(:,:):: var,var1

  integer :: klev
  real,allocatable,dimension(:)::  maxval,minobs
  integer,allocatable,dimension(:):: jmax,jmin

  real :: tmp_ozmp
  integer :: nobs_mls_oncpu,istatus
  real,allocatable,dimension(:,:) :: ozmp,ozmr

! Variables for reading satellite data
  type(diag_header_fix_list )         :: header_fix
  type(diag_header_nlev_list),pointer :: header_nlev(:)
  type(diag_data_fix_list   ),pointer :: data_fix(:)
  type(diag_data_nlev_list  ),pointer :: data_nlev(:,:)
  type(diag_data_extra_list) ,pointer :: data_extra(:,:)


! Namelist with defaults
  logical               :: new_hdr            = .true.
  character(10)         :: ptype              = 'ges'
  logical               :: netcdf             = .false.
  namelist /input/ satname,iyy,imm,idd,ihh,idhh,incr,new_hdr,ptype,netcdf

  data luname,lungrd,lunctl,lndiag / 5, 100, 51, 21 /
  data rmiss /-999./

  !***************************************************
  ! anl_vars and ges_vars are the lists of variables
  ! used in the output GrADS control (.ctl) files
  !
  data anl_vars / 'obs', 'anl', 'obsanl', 'ozmp' /
  data ges_vars / 'obs', 'ges', 'obsges', 'ozmp' /

  data first / .true. /
  data stringd / '.%y4%m2%d2%h2' /
  
  

!************************************************************************
!
! Initialize variables
  nobs=0; irite=0
  rtim=0.0; nlev=1; nflag=1

! Read namelist input
  read(luname,input)
  write(6,input)
  write(6,*)' '

  print*, 'netcdf  = ', netcdf
  print*, 'satname = ', satname

!**********************************************
! Create filenames for diagnostic input, 
!   GrADS output, and GrADS control files    
!
  write(stringd,100) iyy,imm,idd,ihh
100 format('.',i4.4,3i2.2)

  diag_oz   = trim(satname) // '.' // trim(ptype)
  grad_file = trim(satname) // '.' // trim(ptype) // trim(stringd) // '.ieee_d'
  ctl_file  = trim(satname) // '.' // trim(ptype) // '.ctl'

  write(6,*)'diag_oz =',diag_oz
  write(6,*)'grad_file=',grad_file
  write(6,*)'ctl_file =',ctl_file

!************************
! Open diagnostic file.  
!
  call set_netcdf_read( netcdf )
  call open_ozndiag( diag_oz, lndiag, istatus )
  write(6,*) 'istatus from open_ozndiag = ', istatus

  
  call read_ozndiag_header( lndiag, header_fix, header_nlev, new_hdr, istatus )


!****************************************************
! Extract observation type, satellite id, num levels
!
  satype = header_fix%obstype
  satsis = header_fix%isis
  dplat  = header_fix%id
  n_levs = header_fix%nlevs

  if(index(satype,'mls2')/=0 ) then
    n_levs = mls2_levs
  end if
  if(index(satype,'mls3')/=0 ) then
    n_levs = mls3_levs
  end if

  write(6,*)'satype,satsis,dplat,n_levs = ', satype, satsis, dplat, n_levs

  string = trim(satype)//'_'//trim(dplat)
  if ( trim(string) /= trim(satname) ) then
     write(6,*)'***ERROR*** inconsistent instrument types'
     write(6,*)'  satname,string  =',satname,' ',string
     call errexit(91)
  endif


!******************************************************
! Allocate arrays to hold observational information
!
  allocate ( prs_nlev(n_levs))
  allocate (var(n_levs,ntype), iuse(n_levs), error(n_levs))
  allocate(maxval(n_levs))
  allocate(minobs(n_levs))
  allocate(jmax(n_levs))
  allocate(jmin(n_levs))


!**********************************************
! Extract ozinfo relative index
!
  do j=1,n_levs
     error(j)     = real( header_nlev(j)%err, 4)
     prs_nlev(j)  = real( header_nlev(j)%pob, 4)
     iuse(j)      = real( header_nlev(j)%iouse, 4 )
  end do


!**********************************************
! Create GrADS control file
!
  if( trim(ptype) == 'ges' )then
     var_list = ges_vars
  else
     var_list = anl_vars
  end if

  call create_ctl_horiz(ntype,ptype,var_list, &
       n_levs,iyy,imm,idd,ihh,idhh,incr,&
       ctl_file,lunctl,rmiss,satname,prs_nlev,&
       error,iuse,satype,dplat)


!**********************************************
! Loop to read entries in diagnostic file
!
  iflag = 0
  m_levs=n_levs
  if(index(satype,'mls')/=0 ) then
     print*, 'deal with MLS data, reset n_levs=1'
     m_levs=1
  end if

  maxval=0.0
  minobs=500.0
  if(index(satype,'mls')/=0 ) then
    lev_nobs=0
  end if


  !**********************************************
  ! Read a record.  If read flag, iflag does not 
  !   equal zero, exit loopd
  !
  loopd:  do while (iflag == 0)

     call read_ozndiag_data( lndiag, header_fix, data_fix, data_nlev, data_extra, iread, iflag )

     if( iflag /= 0 ) exit loopd
     nobs=nobs+iread

     if(index(satype,'mls')/=0 ) then
        print*, 'nobs, iread for case MLS data= ', nobs, iread
        allocate(dlat(iread))
        allocate(dlon(iread))
        allocate(var1(iread,ntype))
     end if

     !**********************************************
     ! Extract obervation location

     do iobs=1,iread

        rlat   = data_fix(iobs)%lat
        rlon   = data_fix(iobs)%lon
        if(index(satype,'mls')/=0) then
           dlat(iobs)=rlat
           dlon(iobs)=rlon
        end if
     
        !**********************************************
        ! Level loop
        !
        isave=0
        do j = 1, m_levs

           isave = 1
           obs   = data_nlev(j,iobs)%ozobs
           ges   = data_nlev(j,iobs)%ozobs - data_nlev(j,iobs)%ozone_inv
           obsges = data_nlev(j,iobs)%ozone_inv
           tmp_ozmp = data_nlev(j,iobs)%toqf


           !*****************************************************
           !  MLS v2 obs between levels 8 and 23 should be good
           !
           if( index( satype,'mls' ) /=0 .and. j<24 .and. j>7 &
                 .and. ( obs<1.0e-8 .or. ges<1.0e-8 ) ) then 
              print*, 'obs,ges,omg=',obs,ges,obsges, m_levs,rlat,rlon,iobs
           end if


           !*****************************************************
           !  Load into output array
           !
           var(j,1) = obs
           var(j,2) = ges
           var(j,3) = obsges
           var(j,4) = tmp_ozmp

           if(index(satype,'mls')/=0) then
              do i=1,ntype
                 var1(iobs,i)=var(1,i)  !MLS is set to 1 level
              end do

              !*****************************************************
              !  MLS obs between levels 8 and 23 should be good
              !
              klev=mod(iobs,n_levs)
              if(klev==0) klev=n_levs

                 if( klev<24 .and. klev>7 ) then
                    if( (var1(iobs,1)<=0. .or. var1(iobs,1)>100.0) &
                          .and. (var1(iobs,1) /= rmiss) ) then          !  if obs<0. or obs>100
                       print*, 'iobs= ', iobs, ' obs is unreasonable', &
                           klev, iobs, var(1,1), var1(iobs,1),var1(iobs,3)
                    end if

                    if( (var1(iobs,2)<=0. .or. var1(iobs,2)>100.0) &
                          .and. (var1(iobs,1) /= rmiss) ) then          !  if ges<0. or ges>100
                       print*, 'iobs= ', iobs, ' ges is unreasonable', &
                           klev, iobs, var(1,2), var1(iobs,2),var1(iobs,3)
                 end if

              end if
           end if

        enddo ! level loop
 
        !*****************************************************
        ! Write GrADS record
        !
        if (isave==1) then
           if (first) then
              first=.false.
              open(lungrd,file=grad_file,form='unformatted')
           endif

           irite=irite+1
           if(index(satype,'mls')==0 ) then  !non-MLS case
              write(stid,'(i8)') irite
              write(lungrd) stid,rlat,rlon,rtim,nlev,nflag
              write(lungrd) ((var(j,i),j=1,m_levs),i=1,ntype)
           end if
        end if

     enddo ! do iobs=1,iread

     if(index(satype,'mls')/=0 ) then

        allocate(ozmp(n_levs,1000))
        allocate(ozmr(n_levs,1000))
        ozmp=rmiss
        ozmr=rmiss
        nobs_mls_oncpu=0
        print*, 'total # of MLS obs is: ', iobs-1

        do i=1,iread,n_levs
           lev_nobs=lev_nobs+1   !lev_nobs represents the profile ID
           nobs_mls_oncpu=nobs_mls_oncpu+1
           write(stid,'(i8)') lev_nobs
           write(lungrd) stid,dlat(i),dlon(i),rtim,nlev,nflag
           write(lungrd) ((var1(k,j),k=i,i+n_levs-1),j=1,ntype)

           do k=i,i+n_levs-1
              klev=mod(k,n_levs)
              if(klev==0) klev=n_levs

              if(var1(k,4)>0.) then
                 ozmp(klev,nobs_mls_oncpu)=var1(k,4)
                 ozmr(klev,nobs_mls_oncpu)=var1(k,1)
              end if

              if(var1(k,1)>maxval(klev) .and. var1(k,1)/=rmiss ) then
                 maxval(klev)=var1(k,1)
                 jmax(klev)=lev_nobs
              end if

              if(var1(k,1)<minobs(klev) .and. var1(k,1)/=rmiss ) then
                 minobs(klev)=var1(k,1)
                 jmin(klev)=lev_nobs
              end if

           end do
        end do

        deallocate(dlat)
        deallocate(dlon)
        deallocate(var1)

        open(10,file='ozmp.dat',form='unformatted')
        do k=1,n_levs
           write(10) (ozmr(k,i),i=1,nobs_mls_oncpu)
        end do

        do k=1,n_levs
           write(10) (ozmp(k,i),i=1,nobs_mls_oncpu)
        end do

        close(10)
        write(20,*) nobs_mls_oncpu,header_fix%iint

        do i=1,nobs_mls_oncpu
           write(30,*) i,ozmp(:,i)
        end do

        deallocate(ozmp)
        deallocate(ozmr)

     end if

  enddo loopd           ! End of loop over diagnostic file
!-------------------------------------

  write(6,*)'read in ',nobs,' obs & write out ',irite,' obs'
  write(6,*)'write output to lungrd=',lungrd,', file=',trim(grad_file)


  deallocate(var,iuse,error)


!-----------------------------------
!   Close unit to diagnostic file
  close(lndiag)

!----------------------------------------------------------------------
!   If data was written to GrADS file, write terminator and close file

  if (irite>0) then
     stid ='ozone'
     rlat =0.0
     rlon =0.0
     rtim =0.0
     nlev =0
     nflag=0
     write(lungrd) stid,rlat,rlon,rtim,nlev,nflag
     close(lungrd)
  endif

  if(index(satype,'mls')/=0 ) then
     do i=1,n_levs
        print*, 'max,min=',i,maxval(i),minobs(i),jmax(i),jmin(i)
     end do
  end if

  print*, 'Exiting horiz'
!-----------------
! End of program
  stop
end program horiz