#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;
use Date::Format;
use HTTP::Cookies;
use HTTP::Request;
use LWP;
use LWP::UserAgent;
use URI::Escape;
use XML::LibXML;

my $today=time2str("%m/%d/%Y",time);
my $home_dir=$ENV{'HOME'};
my $koha_host='http://wotan.liu.edu';
my $koha_url="$koha_host/cgi-bin/koha";
my $branch_url="$koha_url/admin/branches.pl";
my $users_url="$koha_url/members/memberentry.pl";
my $login_url="$koha_url/mainpage.pl";
my $permissions_url="$koha_url/members/member-flags.pl";
my $branch_set_url="$koha_url/circ/selectbranchprinter.pl";
my $koha_userid='koha';
my $get_borrower_numbers_command="ssh koha\@wotan.liu.edu \". .bash_profile ; perl/list_borrowernumbers\"";
my $dom=XML::LibXML->new();

## course code argument
my $course_code=$ARGV[0];
if(not defined($course_code)) {
  print "fatal: no course code argument\n";
  exit;
}

## course code argument
my $koha_password=$ARGV[1];
if(not defined($koha_password)) {
  print "fatal: no koha password\n";
  exit;
}

## find out about the students
my $students=&parse_course_file($course_code);

## create user agent
my $ua=&create_ua();

## login to koha 
&koha_login();

## do work 
&add_all_students($students);
&fix_permissions_for_all_users();

## logout of koha
&koha_logout();

## adds branches 
sub add_all_students {
  my $students=shift;
  my $count=1;
  foreach my $secret (keys %{$students}) {
    print "$secret\n";
    ## add a branch for the student
    add_branch($students->{$secret}->{'username'},$students->{$secret}->{'name'});
    ## make a user for the student
    &add_staff_user($students->{$secret},$count++);
  }
}

## 
sub fix_permissions_for_all_users {
  my $base_options='';
  ## parameters to pass for all users
  $base_options.="newflags=1&flag=catalogue&flag=editcatalogue:edit_catalogue&";
  $base_options.="flag=editcatalogue:edit_items&flag=editcatalogue:fast_cataloging&";
  $base_options.="cardnumber=$borrower_number&";
  $base_options.="flag=editauthorities&flag=editcatalogue:edit_catalogue";
  foreach my $borrower_number (`$get_borrower_numbers_command`) {
    chomp $borrower_number;
    print "borrower $borrower_number...\n";
    print "going to $permissions_url\n";
    my $req = HTTP::Request->new(POST => $permissions_url);
    $req->content_type('application/x-www-form-urlencoded');
    my $options="member=$borrower_number&".$base_options;
    $req->content($options);
    &get_with_redirect($req);
  }
}

## get a page, follow redirect if given
sub get_with_redirect {
  my $req=shift;
  my $res = $ua->request($req);
  if($res->status_line=~m|302|) {
    my $headers=$res->headers;
    my $redirect_url=$koha_host.$headers->{'location'};
    my $req = HTTP::Request->new(POST => $redirect_url);
    $res = $ua->request($req);
  }
  if($res->is_success) {
    print $res->content;
  }
  else {
    print $res->status_line, "\n";
  }
}

## adds staff user
sub add_staff_user {
  my $student=shift;
  my $count=shift;
  my $options='';
  $options.="BorrowerMandatoryField=zipcode|surname|cardnumber&category_type=S&";
  $options.="destination=&categorycode=S&updtype=I&op=insert&";
  $options.="surname=".$student->{'last_name'}.'&';
  $options.="firstname=".$student->{'first_name'}.'&';
  $options.="branchcode=".$student->{'username'}.'&';
  $options.="userid=".$student->{'username'}.'&';
  if($student->{'initials'}) {
    $options.="initials=".$student->{'initials'}.'&';
  }
  $options.="password=".$student->{'secret'}.'&';
  $options.="zipcode=11548&";
  $options.="dateenrolled=".$today;
  my $req = HTTP::Request->new(POST => $users_url);
  $req->content_type('application/x-www-form-urlencoded');
  $req->content($options);
  &get_with_redirect($req);
}

## adds a branch
sub add_branch {
  my $branch_id=shift;
  my $branch_name=shift;
  my $req = HTTP::Request->new(POST => $branch_url);
  $req->content_type('application/x-www-form-urlencoded');
  $req->content("add=1&op=add_validate&branchcode=$branch_id&branchname=$branch_name&submit=Submit");
  my $res = $ua->request($req);  
  if ($res->is_success) {
    print $res->content;
  }
  else {
    print $res->status_line, "\n";
  }
}

## create a user agent object
sub create_ua {
  my $ua = LWP::UserAgent->new;
  $ua->agent("koha_robot/0.1");
  $ua->cookie_jar(HTTP::Cookies->new(file => "/tmp/koha_cookies.txt",
                                     autosave => 1));
  return $ua;
}

## login to koha 
sub koha_login {
  ## login to koha
  my $req = HTTP::Request->new(POST => $login_url);
  $req->content_type('application/x-www-form-urlencoded');
  $req->content("userid=$koha_userid&password=$koha_password");
  ## pass request to the user agent and get a response back
  my $res = $ua->request($req);
  ## check the outcome of the response
  if ($res->is_success) {
    ##print $res->content;
  }
  else {
    print $res->status_line, "\n";
  }
}

## parses the course file to return student structure
sub parse_course_file {
  my $course_code=shift;
  my $file="$home_dir/doc/grades/$course_code"."_grades.xml";
  my $students;
  if(not -f $file) {
    print "no such file: $file\n";
    exit;
  }
  my $doc=$dom->parse_file($file) or die;
  my $gradesheet_element=$doc->documentElement();
  foreach my $student_element ($gradesheet_element->getElementsByTagName('student')) {
    my $secret=$student_element->getElementsByTagName('code')->[0]->textContent;
    if(not $secret) {
      print "fatal: no secret in", $student_element->toString;
      exit;
    }
    my $username=$student_element->getElementsByTagName('username')->[0]->textContent;
    if(not $username) {
      print "fatal: no username in", $student_element->toString;
      exit;
    }
    ## names are held as inverted names
    my $inverted_name=$student_element->getElementsByTagName('name')->[0]->textContent;
    if(not $inverted_name) {
      print "fatal: no inverted name in", $student_element->toString;
      exit;
    }
    if(not $inverted_name=~m|, +|) {
      print "fatal: inverted name has no comma in", $student_element->toString;
      exit;      
    }
    my $initials='';
    while($inverted_name=~s| ([A-Z])$||) {
      my $initial=$1;
      print "found initial: $initial\n";
      $initials.="$initial.";
    }
    if(not $inverted_name=~m|, +|) {
      print "fatal: inverted name has no comma in", $student_element->toString;
      exit;      
    }
    ## split into first and last name
    $inverted_name=~m|([^,]+), +([^,]+)|;
    my $last_name=$1;
    my $first_name=$2;
    my $name="$first_name $last_name";
    $students->{$secret}->{'inverted_name'}=$inverted_name;
    $students->{$secret}->{'first_name'}=$first_name;
    $students->{$secret}->{'last_name'}=$last_name;
    if($initials) {
      $students->{$secret}->{'initials'}=$initials;
    }
    $students->{$secret}->{'name'}=$name;
    $students->{$secret}->{'username'}=$username;
    $students->{$secret}->{'secret'}=$secret;
  }
  return $students;
}

## logout of koha 
sub koha_logout {
  ## login to koha
  my $req = HTTP::Request->new(GET => "$login_url?logout.x=1");
  ## pass request to the user agent and get a response back
  my $res = $ua->request($req);
  ## check the outcome of the response
  if ($res->is_success) {
    ##print $res->content;
  }
  else {
    print $res->status_line, "\n";
  }
}
