#!/usr/bin/perl
use strict;
use warnings;
use perunServicesInit;
use perunServicesUtils;
use File::Basename;
use utf8;

binmode STDOUT, ":utf8";

our $SERVICE_NAME = basename($0);
our $PROTOCOL_VERSION = "3.1.0";
my $SCRIPT_VERSION = "3.0.1";

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

#Constants
our $A_USER_ID;                 *A_USER_ID =                   \'urn:perun:user:attribute-def:core:id';
our $A_USER_PREFERRED_MAIL;     *A_USER_PREFERRED_MAIL =       \'urn:perun:user:attribute-def:def:preferredMail';
our $A_USER_RT_PREF_MAIL;       *A_USER_RT_PREF_MAIL =         \'urn:perun:user:attribute-def:def:rtPreferredMail';
our $A_USER_EPPN;               *A_USER_EPPN =                 \'urn:perun:user:attribute-def:virt:eduPersonPrincipalNames';
our $A_USER_FIRST_NAME;         *A_USER_FIRST_NAME =           \'urn:perun:user:attribute-def:core:firstName';
our $A_USER_LAST_NAME;          *A_USER_LAST_NAME =            \'urn:perun:user:attribute-def:core:lastName';
our $A_USER_ORGANIZATION;       *A_USER_ORGANIZATION =         \'urn:perun:user:attribute-def:def:organization';
our $A_MEMBER_STATUS;           *A_MEMBER_STATUS =             \'urn:perun:member:attribute-def:core:status';
our $A_RES_NAME;                *A_RES_NAME =                  \'urn:perun:resource:attribute-def:core:name';
our $A_RES_RT_GROUP_NAME;       *A_RES_RT_GROUP_NAME =         \'urn:perun:resource:attribute-def:def:rtGroupName';
our $A_FAC_OUTPUT_FILE_NAME;    *A_FAC_OUTPUT_FILE_NAME =      \'urn:perun:facility:attribute-def:def:rtOutputFileName';

our $STATUS_VALID;              *STATUS_VALID =                \'VALID';

#Headers
our $PREF_MAIL_HEADER = 'preferredMail';
our $EPPNS_HEADER = 'eppns';
our $DISPLAY_NAME_HEADER = 'displayName';
our $ORGANIZATION_HEADER = 'organization';
our $GROUPS_IN_RT_HEADER = 'groupsInRT';

#Other constants
our $EINFRA_DOMAIN = '@einfra.cesnet.cz';
our $META_DOMAIN   = '@meta.cesnet.cz';

my $service_file_name = "$DIRECTORY/$::SERVICE_NAME";
my $file_with_output_file_name = "$DIRECTORY/output_file_name";

my $usersStructureByUserId = {};

#####################################

my $output_file_name = $data->getFacilityAttributeValue(attrName => $A_FAC_OUTPUT_FILE_NAME) || 'rt-data';

foreach my $resourceId ($data->getResourceIds()) {

	my $rtGroupName = $data->getResourceAttributeValue(attrName => $A_RES_RT_GROUP_NAME, resource => $resourceId)
		|| $data->getResourceAttributeValue(attrName => $A_RES_NAME, resource => $resourceId);

	foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) {
		#skip non-valid members
		next if $data->getMemberAttributeValue(attrName => $A_MEMBER_STATUS, member => $memberId) ne $STATUS_VALID;

		my $userId = $data->getUserAttributeValue(attrName => $A_USER_ID, member => $memberId);
		unless(defined $usersStructureByUserId->{$userId}) {
			my $userPrefMail = $data->getUserAttributeValue(attrName => $A_USER_RT_PREF_MAIL, member => $memberId)
				|| $data->getUserAttributeValue(attrName => $A_USER_PREFERRED_MAIL, member => $memberId);
			my $userOrganization = $data->getUserAttributeValue(attrName => $A_USER_ORGANIZATION, member => $memberId);
			my $firstName = $data->getUserAttributeValue(attrName => $A_USER_FIRST_NAME, member => $memberId);
			my $lastName = $data->getUserAttributeValue(attrName => $A_USER_LAST_NAME, member => $memberId);
			my $userName;
			if($firstName && $lastName) {
				$userName = $firstName . ' ' . $lastName;
			} elsif ($firstName) {
				$userName = $firstName;
			} elsif ($lastName) {
				$userName = $lastName;
			} else {
				$userName = "";
			}

			#if user has meta eppn, he should have also einfra eppn
			my %userEPPNs = map { $_ => 1 } @{$data->getUserAttributeValue(attrName => $A_USER_EPPN, member => $memberId)};
			foreach my $eppn (keys %userEPPNs) {
				if($eppn =~ m/$META_DOMAIN/) {
					my $neweppn = $eppn;
					$neweppn =~ s/$META_DOMAIN/$EINFRA_DOMAIN/ge;
					$userEPPNs{$neweppn} = 1;
				}
			}
			#list of eppns must be unique
			

			$usersStructureByUserId->{$userId}->{$PREF_MAIL_HEADER} = $userPrefMail;
			$usersStructureByUserId->{$userId}->{$DISPLAY_NAME_HEADER} = $userName;
			$usersStructureByUserId->{$userId}->{$ORGANIZATION_HEADER} = $userOrganization;
			$usersStructureByUserId->{$userId}->{$EPPNS_HEADER} = \%userEPPNs;
		}

		$usersStructureByUserId->{$userId}->{$GROUPS_IN_RT_HEADER}->{$rtGroupName} = 1;
	}
}

####### FILE WITH NAME OF THE OUTPUT FILE ######
open NAME_FILE,">$file_with_output_file_name" or die "Cannot open $file_with_output_file_name: $! \n";
binmode NAME_FILE, ":utf8";
print NAME_FILE $output_file_name;
close(NAME_FILE);

####### FILE WITH DATA FOR OUTPUT FILE ######
open SERVICE_FILE,">$service_file_name" or die "Cannot open $service_file_name: $! \n";
binmode SERVICE_FILE, ":utf8";

#print header to the file
print SERVICE_FILE "user_id" . "\t" . $PREF_MAIL_HEADER . "\t" . $DISPLAY_NAME_HEADER . "\t" . $ORGANIZATION_HEADER . "\t" . $EPPNS_HEADER . "\t" . $GROUPS_IN_RT_HEADER . "\n";

foreach my $userId (sort { $a <=> $b } keys %$usersStructureByUserId) {
	print SERVICE_FILE $userId . "\t";
	print SERVICE_FILE $usersStructureByUserId->{$userId}->{$PREF_MAIL_HEADER} . "\t";
	print SERVICE_FILE $usersStructureByUserId->{$userId}->{$DISPLAY_NAME_HEADER} . "\t";
	print SERVICE_FILE $usersStructureByUserId->{$userId}->{$ORGANIZATION_HEADER} ? $usersStructureByUserId->{$userId}->{$ORGANIZATION_HEADER} . "\t" : "\t";
	print SERVICE_FILE join(',', sort keys %{$usersStructureByUserId->{$userId}->{$EPPNS_HEADER}}) . "\t";
	print SERVICE_FILE join(',', sort keys %{$usersStructureByUserId->{$userId}->{$GROUPS_IN_RT_HEADER}}) . "\n";
}

close(SERVICE_FILE);

perunServicesInit::finalize;
