#!/usr/bin/env perl

=head1 NAME

addcourse - add a course

=head1 SYNOPSIS

 addcourse [options] COURSEID

=head1 DESCRIPTION

Add a course to the courses directory. The required directories will be created.
Optionally, a database can be populated with users. Also, one or more users can
be granted professor privileges.

=head1 OPTIONS

=over

=item B<--users>=I<FILE>

The users listed in the comma-separated text file I<FILE> will be added to the
user list of the new course. The format of this file is the same as user lists
exported from WeBWorK.

=item B<--professors>=I<USERID>[,I<USERID>]...

Each I<USERID>, if it is present in the new course's user list, will be granted
professor privileges (i.e. a permission level of 10). Requires B<--users>.

=item B<--templates-from>=I<COURSEID>

If specified, the contents of the specified course's templates directory are
used to populate the new course's templates directory.

=item I<COURSEID>

The name of the course to create.

=back

=cut

use strict;
use warnings;

use Getopt::Long;

BEGIN {
	use Mojo::File qw(curfile);
	use Env qw(WEBWORK_ROOT);

	$WEBWORK_ROOT = curfile->dirname->dirname;
}

# link to WeBWorK and pg code libraries
use lib "$ENV{WEBWORK_ROOT}/lib";

use WeBWorK::CourseEnvironment;
use WeBWorK::File::Classlist;
use WeBWorK::Utils qw(runtime_use cryptPassword);
use WeBWorK::Utils::CourseManagement qw(addCourse);
use WeBWorK::File::Classlist qw(parse_classlist);
use WeBWorK::DB::Record::User;
use WeBWorK::DB::Record::Password;
use WeBWorK::DB::Record::PermissionLevel;

sub usage_error {
	warn "@_\n";
	warn "usage: $0 [options] COURSEID\n";
	warn "Options:\n";
	warn "  [--users=FILE [--professors=USERID[,USERID]...] ]\n";
	exit;
}

my ($users, $templates_from) = ('', '');
my @professors;

GetOptions(
	"users=s"          => \$users,
	"professors=s"     => \@professors,
	"templates-from=s" => \$templates_from,
);
my %professors = map { $_ => 1 } map { split /,/ } @professors;
my $courseID   = shift;

usage_error('The COURSEID must be provided.') unless $courseID;

my $ce = WeBWorK::CourseEnvironment->new({ courseName => $courseID });

die "Aborting addcourse: Course ID cannot exceed $ce->{maxCourseIdLength} characters."
	if length($courseID) > $ce->{maxCourseIdLength};

usage_error("Can't specify --professors without also specifying --users.")
	if @professors && !$users;

my @users;
if ($users) {
	my @classlist = parse_classlist($users);
	for my $record (@classlist) {
		my %record  = %$record;
		my $user_id = $record{user_id};

		# Set the default status if the status field is not set.
		$record{status} = $ce->{statuses}{Enrolled}{abbrevs}[0] unless $record{status};

		# Determine what to use for the password (if anything).
		if (!$record{password}) {
			if (defined $record{unencrypted_password} && $record{unencrypted_password} =~ /\S/) {
				$record{password} = cryptPassword($record{unencrypted_password});
			} elsif ($ce->{fallback_password_source}
				&& { user_id => 1, first_name => 1, last_name => 1, student_id => 1 }
				->{ $ce->{fallback_password_source} }
				&& $record{ $ce->{fallback_password_source} }
				&& $record{ $ce->{fallback_password_source} } =~ /\S/)
			{
				$record{password} = cryptPassword($record{ $ce->{fallback_password_source} });
			}
		}

		# Set permission
		if (!$record{status} && defined $professors{$user_id}) {
			$record{permission} = $ce->{userRoles}{professor};
		}

		delete $professors{$user_id};

		push @users,
			[
				WeBWorK::DB::Record::User->new(%record),
				WeBWorK::DB::Record::Password->new(user_id => $user_id, password => $record{password}),
				WeBWorK::DB::Record::PermissionLevel->new(
					user_id    => $user_id,
					permission => defined $professors{$user_id}
					? $ce->{userRoles}{professor}
					: ($record{permission} // $ce->{default_permission_level})
				)
			];
	}

	if (my @ids = keys %professors) {
		warn "Warning: The following users were not in the imported list:\n" . join("\n", @ids) . "\n";
	}
}

my %optional_arguments;
if ($templates_from) {
	$optional_arguments{copyFrom}          = $templates_from;
	$optional_arguments{copyTemplatesHtml} = 1;
}

eval { addCourse(courseID => $courseID, ce => $ce, users => \@users, %optional_arguments,); };

die "$@\n" if $@;

print qq{Successfully added "$courseID" course.\n};
