#!/usr/bin/perl
use warnings;
use strict;

use Getopt::Long;
use Elive::Util;
use Elive::Entity;
use DateTime::Format::ISO8601;
use Pod::Usage;

use Carp;

=head1 NAME

elive_raise_meeting

=head1 SYNOPSIS

% elive_raise_meeting   http://myserver.com/my-site[:port] userid[=role] [userid[=role]...]

    -user someuser              # server login user
    -pass somepass              # server login password

    -facilitator userId
    -name 'my meeting name'
    -meeting_pass otherpass     # meeting password
    -preload file               # local file to upload as a preload
    -start  'YYYY-MM-DD HH:MM'  # start time
    -end '[YYYY-MM-DD] HH::MM'  # end time
    -max_talkers                # max no. of simultaneous talkers
    -help

=head1 DESCRIPTION

Creates a meeting on an Elluminate Live (c) server

=head1 SEE ALSO

    perldoc Elive
    http://search.cpan/org?Elive

=cut

my $username = 'serversupport';
my $password;
my $debug;
my $facilitator;
my $start_str;
my $end_str;
my $meeting_name = 'elive test meeting';
my $meeting_password;
my $max_talkers = 1;
my $raise_hands;
my $preload;
my $url;
my $help;

main(@ARGV) unless caller;

sub main {

    local(@ARGV) = @_;

    GetOptions(
	'name|meeting_name=s' => \$meeting_name,
	'username|user=s' => \$username,
	'password|pass=s' => \$password,
	'facilitator|moderator=s' => \$facilitator,
	'start=s' => \$start_str,
	'end=s' => \$end_str,
	'meeting_password|meeting_pass=s' => \$meeting_password,
	'max_talkers=i' => \$max_talkers,
	'raise_hands' => \$raise_hands,
##	   'private' => \$private,
	'debug=i' => \$debug,
	'help|?' => \$help,
	'preload' => \$preload,
    )
	&& (($help && pod2usage(2)) || ($url = shift @ARGV))
	or die pod2usage(1);

    Elive->debug($debug);

    if ($debug) {
	$SIG{__WARN__} = \&Carp::cluck;
	$SIG{__DIE__} = \&Carp::confess;
    }

    our $connection = Elive->connect(
	$url      ||= Elive::Util::prompt('Elluminate Server: '),
	$username ||= Elive::Util::prompt('Username: '),
	$password ||= Elive::Util::prompt('Password: ', password => 1),
	);

    my $start = $start_str
	? DateTime::Format::ISO8601->parse_datetime($start_str)
	: DateTime->now->clone->add(minutes => 15);

    my $end = $end_str
	? DateTime::Format::ISO8601->parse_datetime($end_str,
						    base_datetime => $start)
	: $start->clone->add(minutes => 45);

    die "end time must be later than start time"
	unless ($end->epoch > $start->epoch);

    my $facilitator_obj = $facilitator
	? _get_user($facilitator)
	: Elive->_login;

    my @participants;

    foreach my $spec (@ARGV) {

	#
	# parse a participant spec: user[=roleId]
	#
	my $user_spec;
	my $role;

	if (($user_spec,$role) = ($spec =~ m{^([^=]+)=([^=]+)$}x)) {
	    die "non-numeric role: $spec"
		unless $role =~ m{^\d+$};
	}
	else {
	    $user_spec = $spec;
	}

	$role = 3 if (!defined $role);

	die "role ($role) not in range 0-3: $spec"
	    unless ($role >= 0 && $role <= 3);

	die "null username: $spec"
	    if ($user_spec eq '');

	my $user_obj = _resolve_user($user_spec);

	if (grep {$_->{user} eq $user_obj} @participants) {
	    warn "duplicate user: $user_spec"
	}
	else {
	    push (@participants, 
		  Elive::Entity::Participant->new({
		      user => $user_obj,
		      role => {roleId => $role},
		      }),
		);
	}
    }

    my $meeting = Elive::Entity::Meeting->insert
	({
	    name => $meeting_name,
	    password => $meeting_password,
	    facilitatorId => $facilitator_obj->stringify,
##	    privateMeeting => $private,
	    start => $start->epoch * 1000,
	    end => $end->epoch * 1000,
	 });
    
    print "created meeting: ".$meeting->name." with id ".$meeting->meetingId."\n";

    if (defined $max_talkers || defined $raise_hands) {
	
	my $meeting_parameters
	    = Elive::Entity::MeetingParameters->retrieve([$meeting->meetingId])
	    or die "Unable to retrieve meeting parameters for this meeting";
	
	$meeting_parameters->maxTalkers($max_talkers)
	    if (defined $max_talkers);

	$meeting_parameters->raiseHandOnEnter($raise_hands)
	    if (defined $raise_hands);

	$meeting_parameters->update;
    }

    if (@participants) {

	setup_participants($meeting->meetingId, @participants);

    }
    else {
	print "no participants\n";
    }

    if ($preload) {
	_upload_preload('/tmp/onechar.tmp',
			$meeting->meetingId,
			$meeting->facilitatorID || $connection->login->userId);
    }

    Elive->disconnect;

    return $meeting;
}

########################################################################

sub _upload_preload {
    my $file_name = shift;
    my $meeting_id = shift;
    my $facilitator_id = shift;

    my $preload = Elive::Entity::Preload->insert(
	{
	    type => 'whiteboard',
	    mimeType => 'application/octet-stream',
	    name => 'introduction.wbd',
	    ownerId => $facilitator_id,
	},
	param => {size => 1},

	);

    

}

########################################################################

sub _setup_participants {
    my $meeting_id = shift;
    my @participants = @_;
	#
	# Create participant list
	#
	my $participant_list = Elive::Entity::ParticipantList
	    ->insert({meetingId => $meeting_id,
		      participants => \@participants,
		     });

	my @participants_echo;
	my $participant_objs = $participant_list->participants;

	foreach (@$participant_objs) {
	    my $user_obj = $_->user;
	    my $loginName = $user_obj->loginName;
	    my $email = $user_obj->email;

	    my $participant_str = ($loginName || $user_obj->userId);
	    $participant_str .= ' <'.$email.'>'
		if $email;
	    push (@participants_echo, $participant_str);
	}

	print "participants: ".join(', ', @participants_echo)."\n";
}

########################################################################

sub _resolve_user {
    my $user_spec = shift;

    die 'usage: _get_user($user_name_or_id)'
	unless (defined $user_spec && $user_spec ne '');
    #
    # Try by username
    #
    my $user;

    if ($user_spec =~ m{^\d+$}) {
	#
	# Numeric id. Assume it's a user id
	#
	$user = {userId => $user_spec};
    }
    else {
	#
	# Treat non-numeric as a loginName
	#
	$user = Elive::Entity::User->get_by_loginName($user_spec);
    }

    die "unkown user: $user_spec"
	unless ($user);

    return $user;
}
