#!/usr/bin/perl

use strict;
use warnings;
use perunServicesInit;
use perunServicesUtils;
use JSON::XS;

#forward declaration
sub processGroupData;
sub processMembersData;
sub processResourceData;

our $SERVICE_NAME = "feudal";
our $PROTOCOL_VERSION = "3.0.0";
my $SCRIPT_VERSION = "3.0.1";

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

#Constants
our $A_GROUP_NAME;                      *A_GROUP_NAME =                   \'urn:perun:group:attribute-def:core:name';
our $A_GROUP_VO_NAME;                   *A_GROUP_VO_NAME =                \'urn:perun:group:attribute-def:virt:voShortName';
our $A_U_F_LOGIN;                       *A_U_F_LOGIN =                    \'urn:perun:user_facility:attribute-def:virt:login';
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_MAIL;                       *A_USER_MAIL =                    \'urn:perun:user:attribute-def:def:preferredMail';
our $A_USER_DISPLAY_NAME;               *A_USER_DISPLAY_NAME =            \'urn:perun:user:attribute-def:core:displayName';
our $A_USER_SSHKEYS;                    *A_USER_SSHKEYS =                 \'urn:perun:user:attribute-def:def:sshPublicKey';
our $A_USER_AFFILIATIONS;               *A_USER_AFFILIATIONS =            \'urn:perun:user:attribute-def:virt:eduPersonScopedAffiliations';
our $A_F_FEUDAL_ISSUER;                 *A_F_FEUDAL_ISSUER =              \'urn:perun:facility:attribute-def:def:feudalIssuer';
our $A_F_FEUDAL_ENTITLEMENT_PREFIX;     *A_F_FEUDAL_ENTITLEMENT_PREFIX =  \'urn:perun:facility:attribute-def:def:feudalGroupEntitlementPrefix';
our $A_F_FEUDAL_ENTITLEMENT_SUFIX;      *A_F_FEUDAL_ENTITLEMENT_SUFIX =   \'urn:perun:facility:attribute-def:def:feudalGroupEntitlementSufix';

#main data structure
my $userInfo = {};

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

my $usersDirectory = "$DIRECTORY/users";
mkdir $usersDirectory or die "Can't mkdir $usersDirectory $!";


for my $user (keys %$userInfo) {
	my $outputStruc = { "userinfo" => $userInfo->{$user} };
	my $fileName = "$usersDirectory/$user";
	open FILE, ">$fileName" or die "Cannot open $fileName: $! \n";
	print FILE JSON::XS->new->utf8->pretty->canonical->encode($outputStruc);
	close FILE or die "Cannot close $fileName: $! \n";
}


perunServicesInit::finalize;

##############################################################################
#   Only subs definitions down there
##############################################################################

sub processGroupData {
	my $groupId = shift;
	my $resourceId = shift;
	my @membersIds = $data->getMemberIdsForResourceAndGroup(resource => $resourceId, group => $groupId);

	my $groupName = $data->getGroupAttributeValue(group => $groupId, attrName => $A_GROUP_NAME);
	my $voName = $data->getGroupAttributeValue(group => $groupId, attrName => $A_GROUP_VO_NAME);

	processMembersData \@membersIds, $groupName, $voName;
}

sub processMembersData {
	my ($membersIdsRef, $groupName, $voName) = @_;
	for my $memberId (@$membersIdsRef) {
		my $login = $data->getUserFacilityAttributeValue(member => $memberId, attrName => $A_U_F_LOGIN);
		my $displayName = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_DISPLAY_NAME);
		my $firstName = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_FIRST_NAME);
		my $lastName = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_LAST_NAME);
		my $mail = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_MAIL);
		my $sshKeys = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_SSHKEYS);
		my $affiliation = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_AFFILIATIONS);
		unless($userInfo->{$login}) {
			$userInfo->{$login}->{"sub"} = $login;
			$userInfo->{$login}->{"name"} = $displayName if defined $displayName;
			$userInfo->{$login}->{"given_name"} = $firstName if defined $firstName;
			$userInfo->{$login}->{"family_name"} = $lastName if defined $lastName;
			$userInfo->{$login}->{"email"} = $mail if defined $mail;
			$userInfo->{$login}->{"ssh_key"} = $sshKeys if defined $sshKeys;
			$userInfo->{$login}->{"eduperson_scoped_affiliation"} = $affiliation;
			$userInfo->{$login}->{"eduperson_entitlement"} = [];
			$userInfo->{$login}->{"iss"} = $data->getFacilityAttributeValue(attrName => $A_F_FEUDAL_ISSUER);
		}

		my $feudalEntitlementPrefix = $data->getFacilityAttributeValue(attrName => $A_F_FEUDAL_ENTITLEMENT_PREFIX);
		my $feudalEntitlementSufix = $data->getFacilityAttributeValue(attrName => $A_F_FEUDAL_ENTITLEMENT_SUFIX);
		push @{$userInfo->{$login}->{"eduperson_entitlement"}}, $feudalEntitlementPrefix . $voName . ':' . $groupName . $feudalEntitlementSufix;
		if($groupName eq 'members') {
			push @{$userInfo->{$login}->{"eduperson_entitlement"}}, $feudalEntitlementPrefix . $voName . $feudalEntitlementSufix;
		}

	}
}
