!     This program tests reading NF90_STRING & NF90_CHAR attributes from fortran.
!     The ref input data structure is shown in ref_att.cdl
!     The ref input data can be generated by running "ncgen -o ref_att.nc ref_att.cdl"
!     For the input of this program, rename ref input data as "att.nc"
!
!     Cheng Da   2025/08/30
!
program f90tst_att
  use netcdf, only: NF90_NOWRITE,NF90_GLOBAL,nf90_open,nf90_close,&
                    nf90_inq_ncid, nf90_inq_varid,nf90_get_att
  implicit none

  integer :: fid, gid, vid
  integer :: ierr
  character(len=256) :: fname, str
  
  fname = "att.nc"
  call check(NF90_Open(TRIM(fname), NF90_NOWRITE, fid))
! read global att
  str=""; call check(nf90_get_att(fid, NF90_GLOBAL, "agency", str)) !NF90_CHAR att
  call verify_results(trim(str), "fake_agency", "get wrong global attr: agency", 10)
  str=""; call check(nf90_get_att(fid, NF90_GLOBAL, "author", str)) !NF90_STRING att
  call verify_results(trim(str), "fake_author", "get wrong global attr: author", 11)

! read var att
  call check(nf90_inq_varid(fid, "obstype", vid))
  str=""; call check(nf90_get_att(fid, vid, "long_name", str)) !NF90_STRING att
  call verify_results(trim(str), "observation type", "get wrong obstype attr: long_name", 12)
  str=""; call check(nf90_get_att(fid, vid, "units", str)) !NF90_CHAR att
  call verify_results(trim(str), "N/A", "get wrong obstype attr: units", 13)

! read var atts under group MetaData
  call check(nf90_inq_ncid(fid, "MetaData", gid))
  call check(nf90_inq_varid(gid,"latitude", vid))
  str=""; call check(nf90_get_att(gid, vid, "units", str)) ! NF90_STRING att
  call verify_results(trim(str), "degrees_north", "get wrong MetaData/latitude attr: units", 14)

! read var atts group yobs
  call check(nf90_inq_ncid(fid, "yobs", gid))
  call check(nf90_inq_varid(gid,"sst", vid))
  str=""; call check(nf90_get_att(gid, vid, "units", str)) ! NF90_STRING att
  call verify_results(trim(str), "C", "get wrong yobs/sst attr: units", 15)

! read var atts group Hx
  call check(nf90_inq_ncid(fid, "Hx", gid))
  call check(nf90_inq_varid(gid,"sst", vid))
  str=""; call check(nf90_get_att(gid, vid, "units", str)) ! NF90_CHAR att
  call verify_results(trim(str), "C", "get wrong Hx/sst attr: units", 16)
  call check(nf90_close(fid))
  print *,"*** SUCCESS!"

contains
subroutine check(errcode)
  use netcdf, only: NF90_NOERR, nf90_strerror
  implicit none
  integer, intent(in) :: errcode
  if(errcode /= NF90_NOERR) then
     print*, "Error: ", trim(nf90_strerror(errcode))
     stop (1)
   endif
end subroutine check

subroutine verify_results(input, ref, errmsg, errcode)
  implicit none 
  character(*),intent(in) :: input, ref, errmsg
  integer,intent(in) :: errcode
  if (trim(input) .ne. trim(ref)) then
     print*, "Error: "//trim(errmsg)
     print*, "       expect to get:"//trim(ref)
     print*, "        actually get:"//trim(input)
     stop (errcode)
  end if
end subroutine verify_results

end program f90tst_att
