#!/usr/bin/perl

#
# Script for ceitec_protemics service used at IDM MU.
#
# Generates 3 files:
# - groups.csv contains list of all groups assigned to resource
# - users.csv contains list of all users from assigned groups
# - memberships.csv contains list of pairs user-group and member status of the user in the group

use strict;
use warnings;
use Text::Unidecode;
use perunServicesInit;
use perunServicesUtils;
use Data::Dumper;
local $::SERVICE_NAME = "ceitec_proteomics";
local $::PROTOCOL_VERSION = "3.0.0";
my $SCRIPT_VERSION = "3.0.1";

perunServicesInit::init;
my $DIRECTORY = perunServicesInit::getDirectory;
my $data = perunServicesInit::getHashedDataWithGroups;

#forward declaration
sub processUsers;
sub processGroups;
sub processMemberships;

#Constants
our $A_USER_ID;                   *A_USER_ID =               \'urn:perun:user:attribute-def:core:id';
our $A_MEMBER_STATUS;             *A_MEMBER_STATUS =         \'urn:perun:member:attribute-def:core:status';
our $A_USER_NAME;                 *A_USER_NAME =             \'urn:perun:user:attribute-def:core:firstName';
our $A_USER_SURNAME;              *A_USER_SURNAME =          \'urn:perun:user:attribute-def:core:lastName';
our $A_USER_EMAIL;                *A_USER_EMAIL =            \'urn:perun:user:attribute-def:def:preferredMail';
our $A_USER_EPPN;                 *A_USER_EPPN =             \'urn:perun:user:attribute-def:virt:eduPersonPrincipalNames';

our $A_GROUP_ID;                  *A_GROUP_ID =              \'urn:perun:group:attribute-def:core:id';
our $A_GROUP_NAME;                *A_GROUP_NAME =            \'urn:perun:group:attribute-def:core:name';

our $userStruc = {};
our $u_name = {};
our $u_surname = {};
our $u_status = {};
our $u_email = {};
our $u_eppns = {};

our $groupStruc = {};
our $g_name = {};

our $membershipStruc = {};

my $fileUsers = $DIRECTORY . "users.csv";
my $fileGroups = $DIRECTORY . "groups.csv";
my $fileMemberships = $DIRECTORY . "memberships.csv";

foreach my $resourceId ( $data->getResourceIds() ) {
	foreach my $groupId ( $data->getGroupIdsForResource( resource => $resourceId ) ) {
		processGroups($groupId, $resourceId);
	}
}

# USERS: user_id name surname e-mail eppns
open FILE_USERS,">$fileUsers" or die "Cannot open $fileUsers: $! \n";
binmode FILE_USERS, ":utf8";

foreach my $uid (sort keys %$userStruc) {
	print FILE_USERS "\"$uid\",\"$userStruc->{$uid}->{$u_name}\",\"$userStruc->{$uid}->{$u_surname}\",\"$userStruc->{$uid}->{$u_email}\",\"", join(",", @{$userStruc->{$uid}->{$u_eppns}}), "\"\n";
}
close (FILE_USERS) or die "Cannot close $fileUsers: $! \n";

# GROUPS: group_id group_name
open FILE_GROUPS,">$fileGroups" or die "Cannot open $fileGroups: $! \n";
binmode FILE_GROUPS, ":utf8";

foreach my $gid (sort keys %$groupStruc) {
	print FILE_GROUPS "\"$gid\",\"$groupStruc->{$gid}->{$g_name}\"", "\n";
}
close (FILE_GROUPS) or die "Cannot close $fileGroups: $! \n";

# MEMBERSHIPS: user_id group_id status
open FILE_MEMBERSHIPS,">$fileMemberships" or die "Cannot open $fileMemberships: $! \n";
foreach my $uid (sort keys %$membershipStruc) {
	foreach my $gid (sort keys %{$membershipStruc->{$uid}}){
		foreach my $membershipStatus (sort keys %{$membershipStruc->{$uid}->{$gid}}){
			print FILE_MEMBERSHIPS "\"$uid\",\"$gid\",\"$membershipStatus\"", "\n";
		}
	}
}
close (FILE_MEMBERSHIPS) or die "Cannot close $fileMemberships: $! \n";

perunServicesInit::finalize;


##############################################################################
#   Only subs definitions down there
##############################################################################
## creates structure for users.csv file
sub processUsers {
	my ($gid, $memberId) = @_;

	my $uid = $data->getUserAttributeValue( member => $memberId, attrName => $A_USER_ID );

	unless(exists $userStruc->{$uid}) {
		$userStruc->{$uid}->{$u_name} = $data->getUserAttributeValue( member => $memberId, attrName => $A_USER_NAME ) || "";
		$userStruc->{$uid}->{$u_surname} = $data->getUserAttributeValue( member => $memberId, attrName => $A_USER_SURNAME ) || "";
		$userStruc->{$uid}->{$u_email} = $data->getUserAttributeValue( member => $memberId, attrName => $A_USER_EMAIL );
		$userStruc->{$uid}->{$u_eppns} = $data->getUserAttributeValue( member => $memberId, attrName => $A_USER_EPPN );
	}

	my $memberStatus = $data->getMemberAttributeValue( member => $memberId, attrName => $A_MEMBER_STATUS );

	processMemberships $gid, $uid, $memberStatus;
}

## creates structure for groups.csv file
sub processGroups {
	my $gid = shift;
	my $resourceId = shift;

	my $groupName = $data->getGroupAttributeValue( group => $gid, attrName => $A_GROUP_NAME );

	if($groupName) {

		unless(exists $groupStruc->{$gid}) {
			$groupStruc->{$gid}->{$g_name} = $groupName;
		}

		for my $memberId ( $data->getMemberIdsForResourceAndGroup( resource => $resourceId, group => $gid )) {
			processUsers $gid, $memberId;
		}
	}
}

## creates structure for memberships.csv file
sub processMemberships {
	my ($gid, $uid, $status) = @_;

	unless(exists $membershipStruc->{$uid}->{$gid}->{$status}) {
		$membershipStruc->{$uid}->{$gid}->{$status} = {};
	}
}
