package Zephyr;

use strict;
use Carp;
use vars qw($VERSION @ISA @EXPORT $AUTOLOAD);

require Exporter;
require DynaLoader;
require AutoLoader;

@ISA = qw(Exporter DynaLoader);

$VERSION = '0.05';

# Items to export into callers namespace by default.
# Note: do not export names by default without a very good reason. Use
# EXPORT_OK instead.  Do not simply export all your public
# functions/methods/constants.
@EXPORT = qw( CLIENT_CANCELSUB CLIENT_FLUSH CLIENT_GIMMEDEFS
	      CLIENT_GIMMESUBS CLIENT_NEW_SERVER CLIENT_SUBSCRIBE
	      CLIENT_SUBSCRIBE_NODEFS CLIENT_UNSUBSCRIBE EXPOSE_NETANN
	      EXPOSE_NETVIS EXPOSE_NONE EXPOSE_OPSTAFF EXPOSE_REALMANN
	      EXPOSE_REALMVIS HM_ATTACH HM_BOOT HM_CTL_CLASS
	      HM_CTL_CLIENT HM_CTL_SERVER HM_DETACH HM_FLUSH
	      HM_GIMMESTATS HM_SRV_SVCNAME HM_STAT_CLASS
	      HM_STAT_CLIENT HM_SVCNAME HM_TIMEOUT LOCATE_CLASS
	      LOCATE_HIDE LOCATE_LOCATE LOCATE_UNHIDE LOGIN_CLASS
	      LOGIN_USER_FLUSH LOGIN_USER_LOGIN LOGIN_USER_LOGOUT
	      SERVER_INSTANCE SERVER_PING SERVER_SERVICE
	      SERVER_SHUTDOWN SERVER_SVCNAME SRV_TIMEOUT USER_REREAD
	      USER_SHUTDOWN USER_STARTUP WG_CTL_CLASS WG_CTL_USER
	      ZAUTH ZAUTH_FAILED ZAUTH_NO ZAUTH_YES ZEPHYR_ADMIN_CLASS
	      ZEPHYR_CTL_CLASS ZEPHYR_CTL_CLIENT ZEPHYR_CTL_HM
	      ZEPHYR_USES_KERBEROS ZERR_NONE ZNOAUTH ZSRVACK_FAIL
	      ZSRVACK_NOTSENT ZSRVACK_SENT ZVERSIONHDR ZVERSIONMAJOR
	      ZVERSIONMINOR Z_MAXHEADERLEN Z_MAXOTHERFIELDS
	      Z_MAXPKTLEN Z_MAXQLEN Z_NUMFIELDS );

sub AUTOLOAD {
    # This AUTOLOAD is used to 'autoload' constants from the constant()
    # XS function.  If a constant is not found then control is passed
    # to the AUTOLOAD in AutoLoader.

    my $constname;
    ($constname = $AUTOLOAD) =~ s/.*:://;
    my $val = constant($constname);
    if ($! != 0) {
	if ($! =~ /Invalid/) {
	    $AutoLoader::AUTOLOAD = $AUTOLOAD;
	    goto &AutoLoader::AUTOLOAD;
	}
	else {
	  croak "Your Zephyr installation has not defined macro $constname";
	}
    }
    eval "sub $AUTOLOAD { '\Q$val\E' }";
    goto &$AUTOLOAD;
}

bootstrap Zephyr $VERSION;

### Preloaded methods go here.

package Zephyr::Notice;
use Carp;

my (%_field_map, @_fields, %_Fetch, %_Store);

{
  local($_);
  my @_field_map = qw( packet		packet
		       version		string
		       kind 		kind		
		       uid		id
		       time		time
		       port		uv
		       auth		iv
		       checked_auth	iv
		       ascii_authent	cblock
		       class		string
		       class_inst	string
		       opcode		string
		       sender		string
		       recipient	string
		       default_format	string
		       multinotice	string
		       multiuid		id
		       checksum		uv
		       other_fields	strlist
		       message		cblock
		     );
  %_field_map = @_field_map;
  @_fields = @_field_map[grep !($_%2), 0..$#_field_map];

  for (@_fields) {
    my $type = $_field_map{$_};
    my $fetch = "FETCH_$type";
    $_Fetch{$_} = \&$fetch if defined &$fetch;
    my $store = "STORE_$type";
    $_Store{$_} = \&$store if defined &$store;
  }
}

sub FETCH {
  if (exists $_Fetch{$_[1]}) { &{$_Fetch{$_[1]}}(@_); }
  else { carp "Cannot fetch field '$_[1]' from a Zephyr::Notice"; undef; }
}
sub STORE {
  if (exists $_Store{$_[1]}) { goto &{$_Store{$_[1]}}; }
  else { carp "Cannot store field '$_[1]' into a Zephyr::Notice"; undef; }
}

package Zephyr;

### Autoload methods go after =cut, and are processed by the autosplit program.

1;
__END__
# documentation for this module

=head1 NAME

Zephyr - Perl interface to the Zephyr library

=head1 SYNOPSIS

  use Zephyr;

=head1 DESCRIPTION

  Zephyr is an UDP-based notice transport and delivery system
  developed at MIT.  The Zephyr package provides a Perl interface to
  the C functions in the Zephyr library.

=head1 AUTHOR

Albert Dvornik, <bert@mit.edu>

=head1 SEE ALSO

zephyr(1), perl(1), "The Zephyr Programmer's Manual".

=head1 BUGS

  This documentation is still woefully incomplete.

  "The Zephyr Programmer's Manual" is also somewhat incomplete, which
  sometimes made writing this interface a pain in the behind.

=cut
