package MHelp;
use strict;

use vars qw(@ISA %Categories %Keywords);
use MInitializable;
@ISA = qw(MInitializable);

use MCoreTools;
use DirHandle ();

# FIXME: help system ought to be in modules

sub _initialize {
  my ($class) = @_;
  $class->load_help;
}

sub load_help {
  my ($class) = @_;
  
  mudlog "Loading help...";
  %Categories = %Keywords = ();
  
  my $root = $::Config{help_path};
  my $hdir = DirHandle->new(rdir($root)) or do {mudlog "ERROR: Failed to open help file directory: $!"; return};
  foreach my $cname ($hdir->read) {
    next unless $cname !~ /\W/ and -d rdir($root.'/'.$cname);
    #mudlog "Scanning help category $cname";

    my $cat = ($Categories{$cname} ||= {items => {}});
    my $cdir = DirHandle->new(rdir($root.'/'.$cname)) or do {mudlog "ERROR: Failed to open help file category '$cname': $!"; return};

    foreach my $fname ($cdir->read) {
      next unless (my $hname = $fname) =~ s/\.help$//;
      #mudlog "Reading help file $cname/$fname";
      
      my $fh = IO::File->new(rfile($root.'/'.$cname.'/'.$fname)) or do {mudlog "ERROR: Failed to open help file '$cname/$fname': $!"; return};
      my @keywords = split /\s*,\s*/, <$fh>;
      my $text = do {local $/; <$fh>};
      $fh->close;
      
      $cat->{items}->{$hname} = {
        text => $text,
        keywords => [@keywords],
      };
      foreach (@keywords, $hname) {
        $cat->{keywords}->{$_} = $hname;
        $Keywords{$_} = [$cname, $hname];
      }
      
    } # end category dir
  } # end help dir
} # end load_help

sub search {
  my ($class, $keyword, $caller) = @_;
  
  my (%hseen, %cseen, %sseen);
  return (
    (grep !$hseen{$$_[0]}++, map $Keywords{$_}, grep !$keyword || /\Q$keyword/, keys %Keywords), 
    map(['cmd', $_], grep !$keyword || /\Q$keyword/ && !$cseen{$_}++, map {$_, $caller->cmdi_aliases($_)} $caller->commands_for_display),
    #FIXME map(['soc', $_], grep !$keyword || /\Q$keyword/ && !$sseen{$_}++, MSocials->all),
  );
}

sub hf_text {
  my ($class, $cat, $name, $caller) = @_;
  
  $cat = lc $cat;
  if ($cat eq 'cmd' and $name = $caller->cmd_match(undef, $name)) {
    my $buf = "&:title;Help on command '$name':&:n;\n";
    my $aka = join ', ', $caller->cmdi_aliases($name);
    $buf .= "&:c;Also known as: $aka&:n;\n" if $aka;
    if ($caller->priv_watcher) {
      $buf .= "&:c;Requires privileges: " . (join ', ', $caller->cmdi_requires($name)) . "&:n;\n";
    }      
    $buf .= $caller->cmdi_help($name) || 'No help is available for this command.';
    return $buf;
  } else {
    return $Categories{$cat}{items}{$name}{text};
  }
}

1;


__END__


Old help command:

oldhelp => {
  code => sub {
    my ($self, $args) = @_;

    if ($args eq '-r') {
      MHelp->load_help;
      $self->send("Done.");
      return;

    } elsif ($args =~ /:/) {
      my ($cat, $key) = split /\s*:\s*/, $args, 2;
      my $help = MHelp->hf_text($cat, $key, $self) or return [report=>{}, [error=>{}, "There is no such help file."]];
      return [report=>{},
        [title=>{},"help $cat:$key"],
        [pre=>{}, $help],
      ];

    } elsif ($args eq '') {
      $self->send([report=>{}, MHelp->hf_text('info', 'basic', $self) || 'Error: missing root help file']);
      
    } elsif (my @r = MHelp->search(($args =~ /^topics$/i ? '' : $args), $self)) {
      if (@r > 1) {
        return [report=>{},
          [line=>{}, "More than one help entry matched your keyword. Please choose one."],
          [title=>{}, "Help Search '$args'"],
          [list=>{mark=>'bullet',cols=>'yes'},
            map [li=>{}, [help=>{}, $_]], sort map "$$_[0]:$$_[1]", @r
          ],
        ];
       } else {
        return [report=>{},
          [title=>{},"help $r[0][0]:$r[0][1]"],
          [pre=>{},MHelp->hf_text(@{$r[0]}, $self)],
        ];
      }
      
    } else {
      mudlog "KEYWORD: help '$args'";
      return [report=>{}, [error=>{}, "No help entry for '$args'.\nYour keyword has been logged."]];
    }
  },
  junk_prefixes => ['for', 'on', 'me with', 'do i', 'do', 'did'],
  help => <<"EOHELP",
help &:meta;<keyword>&:n;
help &:meta;<category>&:n;:&:meta;<name>&:n;
help topics

Accesses $::Config{name}'s help system. If a keyword is provided, displays a matching help topic or a list of them; if a &:y;category:name&:n is provided, displays the specific help topic. The special keyword 'topics' lists all help topics.
EOHELP
},
#---------------------------------------------------------------------------------------------------
