#!perl
use warnings; use strict;
use Test::More tests => 29;
use Test::Exception;
use Test::Builder;

use lib '.';
use t::Elive;

use Carp;

use Elive;
use Elive::Entity::Meeting;
use Elive::Entity::MeetingParameters;
use Elive::Entity::ServerParameters;

use XML::Simple;

our $t = Test::Builder->new;
our $class = 'Elive::Entity::Meeting' ;

our $connection;

SKIP: {

    my %result = t::Elive->test_connection();
    my $auth = $result{auth};

    my $connection_class = $result{class};
    $connection = $connection_class->connect(@$auth);
    Elive->connection($connection);

    my $meeting_start = time();
    my $meeting_end = $meeting_start + 900;

    $meeting_start .= '000';
    $meeting_end .= '000';

    my %meeting_data = (
	name => 'test meeting, generated by t/22-soap-meeting.t',
	facilitatorId => Elive->login->userId,
	password => 'test', # what else?
	start =>  $meeting_start,
	end => $meeting_end,
	privateMeeting => 1,
    );

    if (1) {
	$t->skip("can't modify restrictedMeeting property (known problem)");
    }
    else {
	$meeting_data{restrictedMeeting} = 1;
    }

    my ($meeting) = $class->insert(\%meeting_data);

    isa_ok($meeting, $class, 'meeting');

    foreach (keys %meeting_data) {
	next if $_ eq 'password';  # the password is not echoed by readback
	is($meeting->$_, $meeting_data{$_}, "meeting $_ as expected");
    }

    my %parameter_data = (
	costCenter => 'testing',
	moderatorNotes => 'test moderator notes. Here are some entities: & > <',
	userNotes => 'test user notes; some more entities: &gt;',
	recordingStatus => 'remote',
	raiseHandOnEnter => 1,
	maxTalkers => 3,
	);

    my $meeting_params = Elive::Entity::MeetingParameters->retrieve([$meeting->meetingId]);

    isa_ok($meeting_params, 'Elive::Entity::MeetingParameters', 'meeting_params');

    $meeting_params->update(\%parameter_data);

    foreach (keys %parameter_data) {
	#
	# returned record doesn't contain password
	is($meeting_params->$_, $parameter_data{$_}, "meeting parameter $_ as expected");
    }

    ########################################################################
    # This is a far as we can currently go with a mock connection
    ########################################################################

    skip ($result{reason} || 'skipping live tests', 15)
	if $connection_class->isa('t::Elive::MockConnection');

    my %meeting_server_data = (
	boundaryMinutes => 15,
	fullPermissions => 1,
	supervised => 1,
    );

    #
    # seats are updated via the updateMeeting command
    #
    ok($meeting->update({seats => 2}), 'can update number of seats in the meeting');

    my $server_params = Elive::Entity::ServerParameters->retrieve([$meeting->meetingId]);

    isa_ok($server_params, 'Elive::Entity::ServerParameters', 'server_params');

    $server_params->update(\%meeting_server_data);

    foreach (keys %meeting_server_data) {
	is($server_params->$_, $meeting_server_data{$_}, "server parameter $_ as expected");
    }

    ok($server_params->seats == 2, 'server_param - expected number of seats');

    do {
	#
	# some cursory checks on jnlp construction. Could be a lot
	# more detailed.
	#
	my $meetingJNLP;
	lives_ok(sub {$meetingJNLP = $meeting->buildJNLP(
			  version => '8.0',
			  displayName => 'Elive Test',
			  )},
		'$meeting->buildJNLP - lives');

	ok($meetingJNLP && !ref($meetingJNLP), 'got meeting JNLP');
	lives_ok(sub {XMLin($meetingJNLP)}, 'JNLP is valid XML (XHTML)');
    };

    #
    # check that we can access our meeting by user and date range.
    #

    my $user_meetings = Elive::Entity::Meeting->list_user_meetings_by_date(
	[$meeting_data{facilitatorId},
	 $meeting_data{start},
	 $meeting_data{end},
	 ]
	);

    isa_ok($user_meetings, 'ARRAY', 'user_meetings');

    my $meeting_id = $meeting->meetingId;

    ok(@$user_meetings, 'found user meetings by date');
    ok ((grep {$_->meetingId == $meeting_id} @$user_meetings),
	'meeting is in user_meetings_by_date');

    ok(my $web_url = $meeting->web_url, 'got meeting web_url()');
    #
    # start to tidy up
    #

    lives_ok(sub {$meeting->delete},'meeting deletion');
    #
    # This is an assertion of server behaviour. Just want to verify that
    # meeting deletion cascades. I.e. meeting & server parameters are deleted
    # when the meeting is deleted.
    #
    $meeting_params = undef;

    $meeting = undef;

    my $deleted_meeting;
    eval {$deleted_meeting = Elive::Entity::Meeting->retrieve([$meeting_id])};
    #
    # Change in policy with elluminate 9.5.1. Deleted meetings remain
    # retrievable, they just have the deleted flag set
    #
    ok($@ || ($deleted_meeting && $deleted_meeting->deleted),
       'cascaded delete of meeting parameters');
}

Elive->disconnect;

