# Simulator.pm
#
# Copyright (c) 2002 Cunningham & Cunningham, Inc.
# Released under the terms of the GNU General Public License version 2 or later.
#
# Perl translation by Dave W. Smith <dws@postcognitive.com>

package Simulator;

use strict;
use MusicLibrary;
use MusicPlayer;
use Dialog;

use vars qw($system $time
            $nextSearchComplete $nextPlayStarted $nextPlayComplete);

$system = new Simulator();
$time = 10000;		#HACK start with a fixed time()

$nextSearchComplete = 0;
$nextPlayStarted = 0;
$nextPlayComplete = 0;

sub new {
    my $pkg = shift;

    return bless { @_ }, $pkg;
}

sub nextEvent {
    my $self = shift;
    my($bound) = shift;

    my $result = $bound;
    $result = sooner($result, $nextSearchComplete);
    $result = sooner($result, $nextPlayStarted);
    $result = sooner($result, $nextPlayComplete);
    return $result;
}

sub sooner {
    my($soon, $event) = @_;

    return ($event > $time && $event < $soon) ? $event : $soon;
}

sub perform {
    my $self = shift;

    MusicLibrary::searchComplete() if $time == $nextSearchComplete;
    MusicPlayer::playStarted()     if $time == $nextPlayStarted;
    MusicPlayer::playComplete()    if $time == $nextPlayComplete;
}

sub advance {
    my $self = shift;
    my($future) = @_;

    #DEBUG print "advancing: $future ", (caller(1))[3], "\n";

    while ( $time < $future ) {
	$time = $self->nextEvent($future);
	$self->perform();
    }
}

sub schedule {
    my($seconds) = @_;

    return $time + int($seconds + 0.5);
}

sub delay {
    my $self = shift;
    my($seconds) = @_;

    $seconds = int($seconds + 0.5);

    $self->advance(schedule($seconds));
}

sub waitSearchComplete {
    my $self = shift;

    $self->advance($nextSearchComplete);
}

sub waitPlayStarted {
    my $self = shift;

    $self->advance($nextPlayStarted);
}

sub waitPlayComplete {
    my $self = shift;

    $self->advance($nextPlayComplete);
}

sub failLoadJam {
    my $self = shift;

    $ActionFixture::actor = new Dialog("load jamed", $ActionFixture::actor);
}


1;

__END__

// Copyright (c) 2002 Cunningham & Cunningham, Inc.
// Released under the terms of the GNU General Public License version 2 or later.

package eg.music;

import fit.*;
import java.util.Date;

public class Simulator {

    // This discrete event simulator supports three events
    // each of which is open coded in the body of the simulator.

    static Simulator system = new Simulator();
    static long time = new Date().getTime();

    public static long nextSearchComplete = 0;
    public static long nextPlayStarted = 0;
    public static long nextPlayComplete = 0;

    long nextEvent(long bound) {
        long result = bound;
        result = sooner(result, nextSearchComplete);
        result = sooner(result, nextPlayStarted);
        result = sooner(result, nextPlayComplete);
        return result;
    }

    long sooner (long soon, long event) {
        return event > time && event < soon ? event : soon;
    }

    void perform() {
        if (time == nextSearchComplete)     {MusicLibrary.searchComplete();}
        if (time == nextPlayStarted)        {MusicPlayer.playStarted();}
        if (time == nextPlayComplete)       {MusicPlayer.playComplete();}
    }

    void advance (long future) {
        while (time < future) {
            time = nextEvent(future);
            perform();
        }
    }

    static long schedule(double seconds){
        return time + (long)(1000 * seconds);
    }

    void delay (double seconds) {
        advance(schedule(seconds));
    }

    public void waitSearchComplete() {
        advance(nextSearchComplete);
    }

    public void waitPlayStarted() {
        advance(nextPlayStarted);
    }

    public void waitPlayComplete() {
        advance(nextPlayComplete);
    }

    public void failLoadJam() {
        ActionFixture.actor = new Dialog("load jamed", ActionFixture.actor);
    }


}
