# 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 Test::C2FIT::eg::music::Simulator;

use strict;
use Test::C2FIT::eg::music::MusicLibrary;
use Test::C2FIT::eg::music::MusicPlayer;
use Test::C2FIT::eg::music::Dialog;

use vars qw($system $time
            $nextSearchComplete $nextPlayStarted $nextPlayComplete);

$system = new Test::C2FIT::eg::music::Simulator();
$time = 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 and $event < $soon) ? $event : $soon;
}

sub perform
{
	my $self = shift;
	Test::C2FIT::eg::music::MusicLibrary::searchComplete() if $time == $nextSearchComplete;
	Test::C2FIT::eg::music::MusicPlayer::playStarted()     if $time == $nextPlayStarted;
	Test::C2FIT::eg::music::MusicPlayer::playComplete()    if $time == $nextPlayComplete;
}

sub advance
{
	my $self = shift;
	my($future) = @_;
	while ( $time < $future )
	{
		$time = $self->nextEvent($future);
		$self->perform();
    }
}

sub schedule
{
	my $self = shift;
	my($seconds) = @_;
	return $time + $seconds;
}

sub delay
{
	my $self = shift;
	my($seconds) = @_;
	$self->advance($self->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;
	$Test::C2FIT::ActionFixture::actor = new Test::C2FIT::eg::music::Dialog("load jamed", $Test::C2FIT::ActionFixture::actor);
}

sub _round
{
	my $self = shift;
	my $seconds = shift;

	my $roundDown = int($seconds);

	my $fractionalPart = $seconds - $roundDown;

	return ($fractionalPart >= .5 ? $seconds + 1 : $seconds);

}

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);
    }


}
