#!/usr/bin/perl

use strict;
use CGI;

use Opals::Context;
use Opals::Template qw(
    tmpl_read
    tmpl_write
    tmpl_rangedPageList
);
use Opals::Search qw(
    srch_zDatabase
);
use Opals::WebServiceClient qw(
    wsc_getLibInfo
    wsc_requestILL
);

my $dbh = Opals::Context->dbh();
END { $dbh->disconnect(); }

my $cgi = CGI->new;
# $cgi->param('aaa') returns an array of aaa
my $input = $cgi->Vars();
#my $op = $input->{'op'};
my ($permission, $cookieList, $template) = tmpl_read(
    {
        dbh             => $dbh,
        cgi             => $cgi,
        tmplFile        => 'ill/list.tmpl',
        reqPermission   => 'required_login',
#        reqPermission   => 'circ_ill_req|circ_ill_filter',
#        op              => $op,
    }
);


# See User.pm for the list of permissions
#if ($permission && ($permission->{'circ_ill_filter'} ||
#                    $permission->{'circ_ill_req'})) {
my $uid = $template->param('curUserId');
my $pageNumber = $input->{'pNum'};
my $pageSize = 10;
my $pageRange = 10;
($pageNumber && $pageNumber > 0) || ($pageNumber = 1);

my $zid = $input->{'zid'};
($zid) || ($zid = $cgi->cookie('ill_zid'));
my ($zdbList, $locationId) = getZdbList($dbh, $zid);
if (!$zid && scalar(@$zdbList) > 0) {
    $zid = $zdbList->[0]->{'zid'};
    $locationId = $zdbList->[0]->{'locationId'};
}

my $zdb = srch_zDatabase($dbh, $zid);

if ($uid && $zdb->{'studentILL'}) {
    my ($reqList, $reqCount);
    my $ill_filter = $input->{'ill_filter'};
    ($ill_filter) || ($ill_filter = $cgi->cookie('ill_filter'));

    if ($permission->{'circ_ill_filter'}) {
        my @reqID;
        if ($input->{'username'}) {
            @reqID= split(/�/, $input->{'reqID'});
        }
        else {
            @reqID = $cgi->param('reqID');
        }

        if ($input->{'op'} =~ m/(approve|reject)/i) {
            updateRequests($dbh, $zdb->{'host'}, 
                    $locationId, \@reqID, $uid, $input->{'op'});
        }

        ($reqList, $reqCount) = 
                listRequest($dbh, $zid, $pageNumber, $pageSize, $ill_filter);
        $template->param(
            circ_ill_filter => 1,
            );
    }
    else {
        ($reqList, $reqCount) = 
                listRequest($dbh, $zid, $pageNumber, $pageSize, $ill_filter, $uid);
    }

    $reqList = addLibInfo($zdb->{'host'}, $reqList, $locationId);
    $reqList = addSiteURL($reqList);

    my @rangedPageList = 
            tmpl_rangedPageList($reqCount, $pageNumber, $pageSize, $pageRange);

    if ($reqList && scalar(@{$reqList}) > 0) {
        $template->param(
            requestList     => $reqList,
        );
    }

    $template->param(
        rangedPageList  => \@rangedPageList,
        zdbList         => $zdbList,
        zid             => $zid,
        pNum            => $pageNumber,
    );
}
else { # input for login form
    my @form_input;
    foreach my $param (keys %{$input}) {
        push @form_input, {name => "$param", value => "$input->{$param}"};
    }
    $template->param(
        input=>\@form_input,
    );
}

tmpl_write($dbh, $cgi, $cookieList, $template);
################################################################################

sub listRequest {
    my ($dbh, $zid, $pageNumber, $pageSize, $ill_filter, $uid) = @_;

    my $sql = <<_SQL_;
select  *
from    opl_studentILL
where   zid = ?
_SQL_

    my @param = ($zid);
    if ($uid) {
        $sql .= ' && uid = ?';
        push @param, $uid;
    }

    my $filter = 
        ($ill_filter eq 'pending') ? 'dApproval is null && dRejection is null' :
        ($ill_filter eq 'approved') ? 'dApproval is not null' :
        ($ill_filter eq 'rejected') ? 'dRejection is not null' : undef;
    if ($filter) {
        $sql .= " && $filter";
    }

    my $requestList = $dbh->selectall_arrayref($sql, undef, @param);
    my $reqCount = scalar(@{$requestList});

    my $offset = ($pageNumber - 1) * $pageSize;

    $sql .= " order by id desc limit $pageSize offset $offset";

    $requestList = $dbh->selectall_arrayref($sql, {Slice => {}}, @param);
    my ($ill_admin, $ill_user);
    foreach my $req (@{$requestList}) {
        $req->{'active'} = !($req->{'dApproval'} || $req->{'dRejection'});
        $ill_admin->{$req->{'illAdmin'}} = 1;
        $ill_user->{$req->{'uid'}} = 1;
    }

    my $admins = getUserData($dbh, join(',', sort keys %{$ill_admin}));
    my $users = getUserData($dbh, join(',', sort keys %{$ill_user}));
    foreach my $req (@{$requestList}) {
        $req->{'admin_firstname'} = 
                $admins->{$req->{'illAdmin'}}->{'firstname'};
        $req->{'admin_lastname'} = 
                $admins->{$req->{'illAdmin'}}->{'lastname'};
        
        $req->{'user_firstname'} = 
                $users->{$req->{'uid'}}->{'firstname'};
        $req->{'user_lastname'} = 
                $users->{$req->{'uid'}}->{'lastname'};
        $req->{'user_sid'} = 
                $users->{$req->{'uid'}}->{'sid'};
        $req->{'user_userbarcode'} = 
                $users->{$req->{'uid'}}->{'userbarcode'};
    }

    return ($requestList, $reqCount);
}
############################################################

sub getUserData {
    my ($dbh, $ids) = @_;

    my $sql = <<_SQL_;
select  *
from    opl_user
where   uid in ($ids)
_SQL_
    my $key = 'uid';
    my $users = $dbh->selectall_hashref($sql, $key);

    return $users;
}
############################################################

sub listRequestByIDs {
    my ($dbh, $reqIDs) = @_;

    my $reqList = join(',', @{$reqIDs});
    my $sql = <<_SQL_;
select  *
from    opl_studentILL
where   id in ($reqList)
_SQL_

    my $key = 'id';
    my $requestList = $dbh->selectall_hashref($sql, $key);

    return $requestList;
}
############################################################

sub addSiteURL {
    my ($requestList) = @_;

    if (!$requestList || scalar(@$requestList) == 0) {
        return;
    }

    # get list of distinct ZID's
    my $zids;
    foreach my $req (@{$requestList}) {
        $zids->{$req->{'zid'}} = 1;
    }

    # get z-databse info
    my $zidList = join(',', sort keys %{$zids});
    my $sql = <<_SQL_;
select  *
from    opl_zDatabase
where   zid in ($zidList)
_SQL_

    my $key = 'zid';
    my $zdb = $dbh->selectall_hashref($sql, $key);

    # add library info to each request
    foreach my $req (@{$requestList}) {
        $req->{'host'} = $zdb->{$req->{'zid'}}->{'host'};
    }

    return $requestList;
}
############################################################

sub addLibInfo {
    my ($host, $requestList, $locationId) = @_;

    if (!$requestList || scalar(@$requestList) == 0) {
        return;
    }

    # get list of distinct LID's
    my $lids;
    foreach my $req (@{$requestList}) {
        foreach my $lid (split(/,/, $req->{'responderList'})) {
            $lids->{$lid} = 1;
        }
    }

    # get library info
    my $lidList = join(',', sort keys %{$lids});
    my $libInfo = wsc_getLibInfo(
        host        => $host, 
        lidList     => $lidList, 
        locationId  => $locationId
    );

    # add library info to each request
    foreach my $req (@{$requestList}) {
        foreach my $lid (keys %{$libInfo}) {
            if ($libInfo->{$lid}->{'unionId'} eq $locationId) {
                push @{$req->{'req_lib'}}, $libInfo->{$lid};
                last;
            }
        }

        foreach my $lid (split(/,/, $req->{'responderList'})) {
            push @{$req->{'responders'}}, $libInfo->{$lid};
        }
    }

    return $requestList;
}
############################################################

sub getZdbList {
    my ($dbh, $selectedZid) = @_;

    my $sql = <<_SQL_;
select  *
from    opl_zDatabase
where   studentILL = 1
_SQL_

    my $zdbList = $dbh->selectall_arrayref($sql, {Slice => {}});

    my $locationId;
    if (!$selectedZid) {
        $zdbList->[0]->{'selected'} = 1;
        $locationId = $zdbList->[0]->{'locationId'};
    }
    else {
        foreach my $zdb (@{$zdbList}) {
            if ($zdb->{'zid'} == $selectedZid) {
                $zdb->{'selected'} = 1;
                $locationId = $zdb->{'locationId'};
                last;
            }
        }
    }

    return ($zdbList, $locationId);
}
############################################################

sub updateRequests {
    my ($dbh, $host, $locationId, $reqIDs, $uid, $op) = @_;

    if ($op eq 'approve') {
        approveRequests($dbh, $host, $locationId, $reqIDs, $uid);
    }
    else {
        rejectRequests($dbh, $reqIDs, $uid);
    }
}
############################################################

sub approveRequests {
    my ($dbh, $host, $locationId, $reqIDs, $uid) = @_;

    my $xml = requestToXML($dbh, $locationId, $reqIDs);
    my $ill = wsc_requestILL($host, $xml);

    if (!$ill) {
        return;
    }

    my $sth = $dbh->prepare(<<_SQL_);
update  opl_studentILL
set     dApproval = now(),
        illAdmin = ?,
        illId = ?
where   id = ?
_SQL_

    foreach my $reqID (sort keys %{$ill}) {
        $sth->execute($uid, $ill->{$reqID}->{'ILLID'}, $reqID);
    }

    $sth->finish;
}
############################################################

sub requestToXML {
    my ($dbh, $locationId, $reqIDs) = @_;

    my $requestList = listRequestByIDs($dbh, $reqIDs);

    my $xml = <<_STR_;
<?xml version="1.0" encoding="UTF-8"?>
<requests locationId="$locationId">
_STR_
    foreach my $reqID (sort keys %{$requestList}) {
        $requestList->{$reqID}->{'description'}
            =~ s/"/\&quot;/g;

        $xml .= <<_STR_;
    <request 
        id="$reqID"
        rid="$requestList->{$reqID}->{'rid'}"
        description="$requestList->{$reqID}->{'description'}"
        dRequest="$requestList->{$reqID}->{'dRequest'}"
        dExpiry="$requestList->{$reqID}->{'dExpiry'}"
        responderList="$requestList->{$reqID}->{'responderList'}"
    />
_STR_
    }

    $xml .= <<_STR_;
</requests>
_STR_

    return $xml;
}
############################################################

sub rejectRequests {
    my ($dbh, $reqIDs, $uid) = @_;

    my $sth = $dbh->prepare(<<_SQL_);
update  opl_studentILL
set     dRejection = now(),
        illAdmin = ?
where   id = ?
_SQL_

    foreach my $reqID (@{$reqIDs}) {
        $sth->execute($uid, $reqID);
    }

    $sth->finish;
}
