#!/usr/bin/perl -w
# This script (sophomorix-exam-mode) is maintained by Rüdiger Beck
# It is Free Software (License GPLv3)
# If you find errors, contact the author
# jeffbeck@web.de  or  jeffbeck@linuxmuster.net

# modules
use strict;
#use Quota;
use Getopt::Long;
Getopt::Long::Configure ("bundling");
use Sophomorix::SophomorixConfig;
use List::MoreUtils qw(uniq);
use String::Approx 'amatch';
use String::Approx 'adist';
use Net::LDAP;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Terse = 1; 
use JSON;
use File::Basename qw( basename
                       dirname
                     ); 
use Text::Iconv;
use Sophomorix::SophomorixBase qw(
                                 print_line
                                 print_title
                                 create_schoollist
                                 unlock_sophomorix
                                 lock_sophomorix
                                 log_script_start
                                 log_script_end
                                 log_script_exit
                                 backup_auk_file
                                 get_passwd_charlist
                                 get_plain_password
                                 check_options
                                 config_sophomorix_read
                                 result_sophomorix_init
                                 result_sophomorix_add
                                 result_sophomorix_check_exit
                                 result_sophomorix_print
                                 filelist_fetch
                                 remove_whitespace
                                 json_dump
                                 recode_utf8_to_ascii
                                 remove_from_list
                                 call_sophomorix_command
                                 );
use Sophomorix::SophomorixSambaAD qw(
                                 AD_get_unicodepwd
                                 AD_set_unicodepwd
                                 AD_school_create
                                 AD_bind_admin
                                 AD_unbind_admin
                                 AD_session_manage
                                 AD_user_set_exam_mode
                                 AD_user_unset_exam_mode
                                 AD_user_create
                                 AD_user_kill
                                 AD_group_create
                                 AD_group_addmember
                                 AD_group_update
                                 AD_get_schoolname
                                 AD_get_name_tokened
                                 AD_dn_fetch_multivalue
                                 AD_get_sessions
                                 AD_get_user
                                 AD_get_examusers
                                 AD_dns_get
                                 AD_object_search
                                 AD_examuser_create
                                 AD_examuser_kill
                                 AD_get_passwd
                                    );

my @arguments = @ARGV;

# option vars
$Conf::log_level=1;
my $help=0;
my $info=0;
my $json=0;
my $school="";

my $supervisor="";
my $participants="";
my $set_exam_mode=0;
my $unset_exam_mode=0;
my $reset_all_exam_mode_users=0;

my $subdir; # for collecting into
my $subdir_examuser=""; # for creating examusers and OU

# Parsen der Optionen
my $testopt=GetOptions(
           "help|h" => \$help,
           "info|i" => \$info,
           "json|j+" => \$json,
           "verbose|v+" => \$Conf::log_level,
           "reset-all-exam-mode-users" => \$reset_all_exam_mode_users,
           "school=s" => \$school,
           "supervisor=s" => \$supervisor,
           "participants|m=s" => \$participants,
           "subdir=s" => \$subdir,
           "subdir-examuser=s" => \$subdir_examuser,
           "set-exam-mode|set" => \$set_exam_mode,
           "unset-exam-mode|unset" => \$unset_exam_mode,
          );

my %sophomorix_result=&result_sophomorix_init("sophomorix-exam-mode");
# Prüfen, ob Optionen erkannt wurden, sonst Abbruch
&check_options($testopt,\%sophomorix_result,$json);

# Reading Configuration
my ($ldap,$root_dse) = &AD_bind_admin(\@arguments,\%sophomorix_result,$json);
my $root_dns=&AD_dns_get($root_dse);
my %sophomorix_config=&config_sophomorix_read($ldap,$root_dse,\%sophomorix_result);
my ($smb_admin_pass)=&AD_get_passwd($DevelConf::sophomorix_file_admin,
                                     $DevelConf::secret_file_sophomorix_file_admin);

# --help
if ($help==1) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlsbeschreibung
   print('
sophomorix-exam-mode sets/unsets users in exam-mode

Options:
  -h  / --help
  -v  / --verbose
  -vv / --verbose --verbose
  -i  / --info

  sophomorix-exam-mode --set --supervisor <supi>  --participants <user1>,<user2>,...
  sophomorix-exam-mode --unset --subdir <subdir> <session> --participants <user1>,<user2>,...

  --reset-all-exam-mode-users --school <school>

Please see the sophomorix-exam-mode(8) man pages for full documentation
');
   print "\n";
   exit;
}


# --school <school1,school2, ...>
my @opt_schoollist=&create_schoollist($school,\%sophomorix_config);



# --info
if ($info==1) {
    my $ref_examusers=&AD_get_examusers({ldap=>$ldap,
                                         root_dse=>$root_dse,
                                         root_dns=>$root_dns,
                                         school=>$school,
                                         sophomorix_config=>\%sophomorix_config,
					});
    # print Dumper ($ref_examusers);
    my $jsoninfo="EXAMUSER";
    my $jsoncomment="All Exam Users";

    &json_dump({json => $json,
                jsoninfo => $jsoninfo,
                jsoncomment => $jsoncomment,
                object_name => $school,
                log_level => $Conf::log_level,
                hash_ref => $ref_examusers,
                sophomorix_config => \%sophomorix_config,
               });
    exit;
}



&result_sophomorix_check_exit(\%sophomorix_result,\%sophomorix_config,$json);
################################################################################
# Start
################################################################################
&log_script_start(\@arguments,\%sophomorix_result,\%sophomorix_config);



# --set-exam-mode
if ($set_exam_mode==1){
    if ($participants eq ""){
        print "\nERROR: you need to specify at least one participant\n\n";
        exit 88;
    }
    if ($supervisor eq ""){
        print "\nERROR: you need to specify the supervisor\n\n";
        exit 88;
    }

    my @participants=split(/,/,$participants);
    my $user_count=0;
    my $max_user_count=$#participants+1;
    foreach my $participant (@participants){
        $user_count++;
        my $ret=&AD_user_set_exam_mode({ldap=>$ldap,
                                root_dse=>$root_dse,
                                root_dns=>$root_dns,
                                supervisor=>$supervisor,
                                participant=>$participant,
                                user_count=>$user_count,
                                max_user_count=>$max_user_count,
                                json=>$json,
                                sophomorix_config=>\%sophomorix_config,
                                sophomorix_result=>\%sophomorix_result,
                            });

        if ($ret==0){
            # if <user> found and set in exammode, create <user>-exam
            &AD_examuser_create({ldap=>$ldap,
                                 root_dse=>$root_dse,
                                 root_dns=>$root_dns,
                                 participant=>$participant,
                                 subdir=>$subdir_examuser,
                                 user_count=>$user_count,
                                 max_user_count=>$max_user_count,
                                 smb_admin_pass=>$smb_admin_pass,
                                 json=>$json,
                                 sophomorix_config=>\%sophomorix_config,
                                 sophomorix_result=>\%sophomorix_result,
                               });

            if ($sophomorix_config{'INI'}{'EXAMMODE'}{'PASSWORDHASH_COPY'} eq "TRUE"){
                my $examuser=$participant.$sophomorix_config{'INI'}{'EXAMMODE'}{'USER_POSTFIX'};
                &print_title("Cloning password-hash of $participant to $examuser");
                my ($unicodepwd,$supplemental_credentials)= &AD_get_unicodepwd($participant,\%sophomorix_config);
                &AD_set_unicodepwd($examuser,$unicodepwd,$supplemental_credentials,\%sophomorix_config);
            }
        }
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --unset-exam-mode
if ($unset_exam_mode==1){
    if ($participants eq ""){
        print "\nERROR: you need to specify at least one participant\n\n";
        exit 88;
    }

    my @participants=split(/,/,$participants);
    my $user_count=0;
    my $max_user_count=$#participants+1;
    foreach my $participant (@participants){
        if ($participant=~m/-exam$/){
            $participant=~s/-exam$//; 
        }
        $user_count++;
        # collect data
        if ($sophomorix_config{'INI'}{'EXAMMODE'}{'COLLECT_BEFORE_KILL'} eq "TRUE"){
            my $examuser=$participant.$sophomorix_config{'INI'}{'EXAMMODE'}{'USER_POSTFIX'};
            my $command;
            if (defined $subdir){
                $command="/usr/sbin/sophomorix-transfer --copy-account-data --collect-copy-exam ".$examuser." --subdir ".$subdir;
            } else {
                $command="/usr/sbin/sophomorix-transfer --copy-account-data --collect-copy-exam ".$examuser;

            }
            &call_sophomorix_command($Conf::log_level,$json,$command);
        }
        my $ret=&AD_user_unset_exam_mode({ldap=>$ldap,
                                          root_dse=>$root_dse,
                                          root_dns=>$root_dns,
                                          participant=>$participant,
                                          user_count=>$user_count,
                                          max_user_count=>$max_user_count,
                                          json=>$json,
                                          sophomorix_config=>\%sophomorix_config,
                                          sophomorix_result=>\%sophomorix_result,
                                        });
        if ($ret==0){
            &AD_examuser_kill({ldap=>$ldap,
                               root_dse=>$root_dse,
                               root_dns=>$root_dns,
                               participant=>$participant,
                               user_count=>$user_count,
                               max_user_count=>$max_user_count,
                               smb_admin_pass=>$smb_admin_pass,
                               json=>$json,
                               sophomorix_config=>\%sophomorix_config,
                               sophomorix_result=>\%sophomorix_result,
                             });
        }
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --reset-all-exam-mode-users (--school <school> )
if ($reset_all_exam_mode_users==1){
    if ($school eq ""){
        $school=$DevelConf::name_default_school;
    }
    
    my $ref_examusers=&AD_get_examusers({ldap=>$ldap,
                                         root_dse=>$root_dse,
                                         root_dns=>$root_dns,
                                         school=>$school,
                                         sophomorix_config=>\%sophomorix_config,
					});
    #print Dumper ($ref_examusers);
    &print_title("Resetting examusers of school $school");

    if (not exists $ref_examusers->{'LISTS'}{'EXAMUSER_by_sophomorixSchoolname'}{$school}{'examuser'}){
        print "WARNING: No examusers found in school $school\n";
    } else {
        my $participants=join(",",@{ $ref_examusers->{'LISTS'}{'EXAMUSER_by_sophomorixSchoolname'}{$school}{'examuser'} } );
        my $command="/usr/sbin/sophomorix-exam-mode --unset --subdir transfer --participants ".$participants;
        #print $command."\n";
        &call_sophomorix_command($Conf::log_level,$json,$command);
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



################################################################################
# Sub
################################################################################
