package include::config;

use strict;
use warnings;

# Load the configuration and return an object encapsulating all the options.
sub configurate {
  my $class = shift;
  # TODO: no hardcoding
  require "/home/dabreegster/adv/config";
  return bless loadconf(), $class;
}

our $AUTOLOAD;

# The config singleton (known as StdMech) encapsulates configuration and
# gameplay mechanics. Its data is accessed through methods.
sub AUTOLOAD {
  my $self = shift;
  my $do = $AUTOLOAD;
  $do =~ s/^.*:://;
  return if $do eq "DESTROY";
  if ($self->{$do}) {
    return $self->{$do}->(@_) if ref $self->{$do} eq "CODE";
    return $self->{$do};
  } else {
    die "No config for $do!\n";
  }
}

# Returns a random number within a range.
sub random {
  my $me = shift if ref $_[0];
  #my $me = shift unless (caller)[1] =~ "config";  # no CONFIG yet
  $me ||= bless({Rnds => [], SaveRnds => []}, "include::config");
  if (@_ == 1) {
    my $max = shift;
    die "WARNING: rnd not saved/loaded" unless $me;
    return int $me->rander(1 + $max);
  } else {
    my ($min, $max) = @_;
    return $min if $min == $max;
    ($min, $max) = ($max, $min) if $min > $max;
    die "WARNING: rnd not saved/loaded" unless $me;
    return $min + int $me->rander(1 + $max - $min);
  }
}

# Allow resimulation.
sub rander {
  my ($self, $arg) = @_;
  my $rnd;
  if (@{ $self->{Rnds} }) {
    $rnd = shift @{ $self->{Rnds} };
  } else {
    $rnd = rand($arg);
  }
  push @{ $self->{SaveRnds} }, $rnd;
  return $rnd;
}

# Returns a random element of the set.
sub chooserand {
  my $self = shift;
  #shift unless (caller)[1] =~ "config";  # no CONFIG yet
  return $_[ $self->random(0, $#_) ];
}

# Returns true a percentage of the time.
sub percent {
  my $self = shift unless (caller)[1] =~ "config";  # no CONFIG yet
  $self ||= bless({Rnds => [], SaveRnds => []}, "include::config");
  return 1 if $self->random(1, 100) <= shift;
}

sub rndload {
  my ($self, $fname) = @_;
  open my $file, "<$fname" or die "can't open '$fname'!\n";
  while (<$file>) {
    chomp $_;
    push @{ $self->{Rnds} }, $_;
  }
  close $file;
}

sub rndsave {
  my $self = shift;
  open my $file, ">rnds" or die "can't open rnds!\n";
  print $file "$_\n" foreach @{ $self->{SaveRnds} };
  close $file;
}

sub rndmize {
  my $self = shift;
  # ripped right from List::Util. i need my rand so i can save the #s.
  my @a=\(@_);
  my $n;
  my $i=@_;
  map {
    $n = $self->random(0, -1 + $i--);
    (${$a[$n]}, $a[$n] = $a[$i])[0];
  } @_;
}

42;
