!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubehelp_check
  use sic_def
  use sic_types
  use cubetools_parameters
  use cubetools_structure
  use cube_messaging
  !
  public :: cubehelp_check_register
  private
  !
  type :: check_comm_t
    type(option_t), pointer :: check
  end type check_comm_t
  type(check_comm_t) :: comm
  !
  type :: check_user_t
    character(len=argu_l) :: topic
  contains
    procedure, private :: toprog => cubehelp_check_user_toprog
  end type check_user_t
  !
  type :: check_prog_t
    integer(kind=lang_k)   :: ilang
    integer(kind=comm_k)   :: icomm
    character(len=name_l)  :: lang
    character(len=name_l)  :: command
  contains
    procedure, private :: run => cubehelp_check_prog_run
  end type check_prog_t
  !
contains
  !
  subroutine cubehelp_check_register(error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    logical, intent(inout) :: error
    !
    type(standard_arg_t) :: stdarg
    character(len=*), parameter :: rname='CHECK>REGISTER'
    !
    call cube_message(seve%t,rname,'Welcome')
    !
    call cubetools_register_command( &
         'CHECK','[LANG\]COMMAND',&
         'Print all online-help surfaces of one command',&
         'Display-only audit helper: CHECK prints command, option, and option-argument help surfaces for one target command.'&
         //strg_bl//&
         'Automation output contract:'//strg_cr//&
         '- emits one marker per rendered surface: Help surface: <surface-query>.'//strg_cr//&
         '- emits one final summary line: Help surfaces total: N.'//strg_cr//&
         '- invariant: N equals marker count and N >= 1 for successful runs.'//strg_bl//&
         'Associated commands: HELP\HELP, HELP\COLLECT.'//strg_bl//&
         'Typical workflow:'//strg_cr//&
         '  CUBE> HELP\CHECK SET\SPECTRAL',&
         cubehelp_check_command,&
         comm%check,error,&
         allowopt=.false.)
    if (error) return
    !
    call stdarg%register( &
         'COMMAND',&
         'Command name',&
         'Target command in COMMAND or LANG\COMMAND syntax (for example: SPECTRAL or SET\SPECTRAL).'//strg_cr//&
         'For audit automation, prefer fully-qualified LANG\COMMAND.',&
         code_arg_mandatory,&
         error)
    if (error) return
  end subroutine cubehelp_check_register
  !
  subroutine cubehelp_check_command(line,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(check_user_t) :: user
    type(check_prog_t) :: prog
    !
    call cubehelp_check_parse(line,user,error)
    if (error) return
    call user%toprog(prog,error)
    if (error) return
    call prog%run(error)
    if (error) return
  end subroutine cubehelp_check_command
  !
  subroutine cubehelp_check_parse(line,user,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    character(len=*),  intent(in)    :: line
    type(check_user_t),intent(out)   :: user
    logical,           intent(inout) :: error
    !
    user%topic = strg_emp
    call cubetools_getarg(line,comm%check,1,user%topic,mandatory,error)
    if (error) return
  end subroutine cubehelp_check_parse
  !
  subroutine cubehelp_check_user_toprog(user,prog,error)
    use cubetools_disambiguate
    use cubetools_language
    use cubetools_standard_comm
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(check_user_t), intent(in)    :: user
    type(check_prog_t),  intent(out)   :: prog
    logical,             intent(inout) :: error
    !
    integer(kind=inte_k) :: iquiet,isiccomm,ocode,ibsl,ier
    integer(kind=lang_k) :: ilang
    integer(kind=comm_k) :: icomm
    type(language_t), pointer :: language
    type(command_t),  pointer :: command
    character(len=name_l) :: lang
    character(len=argu_l) :: topic
    character(len=name_l) :: token_command,solved
    character(len=name_l), allocatable :: cnames(:)
    character(len=*), parameter :: rname='CHECK>USER>TOPROG'
    !
    call cubetools_disambiguate_toupper(user%topic,topic,error)
    if (error) return
    !
    iquiet = 1
    call sic_parse_command(topic,len_trim(topic),iquiet,.true.,ilang,isiccomm,ocode,error)
    if (error) then
      call cube_message(seve%e,rname,'Unable to resolve target '//trim(topic)//'. Use LANG\COMMAND when ambiguous.')
      return
    endif
    if (isiccomm.lt.1) then
      call cube_message(seve%e,rname,'Failed to resolve command target '//trim(topic))
      error = .true.
      return
    endif
    !
    ibsl = index(topic,backslash)
    if (ibsl.eq.0) then
      token_command = topic
    else if (ibsl.ge.len_trim(topic)) then
      call cube_message(seve%e,rname,'Missing command name in target '//trim(topic))
      error = .true.
      return
    else
      token_command = adjustl(topic(ibsl+1:len_trim(topic)))
    endif
    if (len_trim(token_command).le.0) then
      call cube_message(seve%e,rname,'Missing command name in target '//trim(topic))
      error = .true.
      return
    endif
    !
    call sic_ilang(ilang,lang)
    if (.not.cubetools_pack_has_language(lang)) then
      call cube_message(seve%e,rname,'Unknown package language '//trim(lang))
      error = .true.
      return
    endif
    !
    call pack%get_language_id(lang,prog%ilang,error)
    if (error) return
    language => cubetools_language_ptr(pack%lang%list(prog%ilang)%p,error)
    if (error) return
    !
    allocate(cnames(language%comm%n),stat=ier)
    if (ier.ne.0) then
      call cube_message(seve%e,rname,'Failed to allocate command list for disambiguation')
      error = .true.
      return
    endif
    do icomm=1,language%comm%n
      command => cubetools_command_ptr(language%comm%list(icomm)%p,error)
      if (error) return
      cnames(icomm) = command%name
    enddo
    !
    call cubetools_disambiguate_strict(token_command,cnames,prog%icomm,solved,error)
    if (error) return
    command => cubetools_command_ptr(language%comm%list(prog%icomm)%p,error)
    if (error) return
    prog%lang    = language%name
    prog%command = command%name
  end subroutine cubehelp_check_user_toprog
  !
  subroutine cubehelp_check_prog_run(prog,error)
    use cubetools_language
    use cubetools_standard_comm
    use cubetools_primitive_opt
    use cubetools_primitive_arg
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(check_prog_t), intent(in)    :: prog
    logical,             intent(inout) :: error
    !
    integer(kind=opti_k) :: iopt
    integer(kind=narg_k) :: iarg
    integer(kind=inte_k) :: nsurface
    type(language_t), pointer :: language
    type(command_t),  pointer :: command
    class(primitive_opt_t), pointer :: option
    class(primitive_arg_t), pointer :: argument
    character(len=mess_l) :: surface
    character(len=*), parameter :: rname='CHECK>PROG>RUN'
    !
    language => cubetools_language_ptr(pack%lang%list(prog%ilang)%p,error)
    if (error) return
    command => cubetools_command_ptr(language%comm%list(prog%icomm)%p,error)
    if (error) return
    !
    nsurface = 0
    !
    surface = trim(prog%lang)//backslash//trim(prog%command)//' ?'
    nsurface = nsurface+1
    call cubehelp_check_show_surface(surface)
    call cubehelp_check_prog_command_surface(prog,command,error)
    if (error) return
    !
    do iopt=1,command%opt%n
      option => cubetools_primitive_opt_ptr(command%opt%list(iopt)%p,error)
      if (error) return
      surface = trim(prog%lang)//backslash//trim(prog%command)//' /'//trim(option%name)//' ?'
      nsurface = nsurface+1
      call cubehelp_check_show_surface(surface)
      call option%summary(error)
      if (error) return
      !
      do iarg=1,option%arg%n
        argument => cubetools_primitive_arg_ptr(option%arg%list(iarg)%p,error)
        if (error) return
        surface = trim(prog%lang)//backslash//trim(prog%command)//' /'//trim(option%name) &
             //' '//trim(argument%name)//' ?'
        nsurface = nsurface+1
        call cubehelp_check_show_surface(surface)
        call argument%summary(error)
        if (error) return
      enddo
    enddo
    !
    if (nsurface.le.0) then
      call cube_message(seve%e,rname,'Internal error: HELP\\CHECK produced no help surface marker')
      error = .true.
      return
    endif
    !
    call cubehelp_check_show_count(nsurface)
  end subroutine cubehelp_check_prog_run
  !
  subroutine cubehelp_check_prog_command_surface(prog,command,error)
    use cubetools_terminal_tool
    use cubetools_primitive_opt
    use cubetools_primitive_prod
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(check_prog_t), intent(in)    :: prog
    type(command_t),      intent(in)    :: command
    logical,             intent(inout) :: error
    !
    integer(kind=opti_k) :: iopt
    integer(kind=prod_k) :: iprod
    class(primitive_opt_t), pointer :: option
    class(primitive_prod_t), pointer :: product
    character(len=*), parameter :: rname='CHECK>COMMAND>SURFACE'
    !
    call command%show_minimum(prog%lang,error)
    if (error) return
    !
    option => cubetools_primitive_opt_ptr(command%opt%list(0)%p,error)
    if (error) return
    call option%list(error)
    if (error) return
    !
    if (command%opt%n.gt.0) then
      call cube_message(seve%r,rname,terminal%dash_strg())
      do iopt=1,command%opt%n
        option => cubetools_primitive_opt_ptr(command%opt%list(iopt)%p,error)
        if (error) return
        call option%print_abstract(error)
        if (error) return
      enddo
    endif
    !
    if (command%prod%n.gt.0) then
      call cube_message(seve%r,rname,terminal%dash_strg())
      call cube_message(seve%r,rname,'  Products')
      do iprod=1,command%prod%n
        product => cubetools_primitive_prod_ptr(command%prod%list(iprod)%p,error)
        if (error) return
        call product%print_abstract(iprod,error)
        if (error) return
      enddo
    endif
    !
    call cube_message(seve%r,rname,blankstr)
  end subroutine cubehelp_check_prog_command_surface
  !
  subroutine cubehelp_check_show_surface(surface)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    character(len=*), intent(in) :: surface
    !
    character(len=*), parameter :: rname='CHECK>SURFACE'
    !
    ! Stable marker token for audit automation; keep literal prefix unchanged
    call cube_message(seve%r,rname,blankstr)
    call cube_message(seve%r,rname,'Help surface: '//trim(surface))
  end subroutine cubehelp_check_show_surface
  !
  subroutine cubehelp_check_show_count(nsurface)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    integer(kind=inte_k), intent(in) :: nsurface
    !
    character(len=argu_l) :: nstr
    character(len=*), parameter :: rname='CHECK>SUMMARY'
    !
    ! Contract: count must equal the number of emitted "Help surface:" markers
    write(nstr,'(i0)') nsurface
    call cube_message(seve%r,rname,'Help surfaces total: '//trim(nstr))
  end subroutine cubehelp_check_show_count
end module cubehelp_check
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
