#!/usr/bin/perl

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

local $::SERVICE_NAME = basename($0);
local $::PROTOCOL_VERSION = "3.0.0";
my $SCRIPT_VERSION = "3.0.0";

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

our $A_USER_LOGIN;                      *A_USER_LOGIN =                       \'urn:perun:user_facility:attribute-def:virt:login';
our $A_O365_GROUP_ID;                   *A_O365_GROUP_ID =                    \'urn:perun:resource:attribute-def:def:o365GroupId';
our $A_KEEP_EXTERNAL_ACCOUNTS;          *A_KEEP_EXTERNAL_ACCOUNTS =           \'urn:perun:resource:attribute-def:def:o365KeepExternalAccounts';
our $A_FACILITY_LOGIN_SCOPE;            *A_FACILITY_LOGIN_SCOPE =             \'urn:perun:facility:attribute-def:def:o365DomainName';
our $A_MEMBER_STATUS;                   *A_MEMBER_STATUS =                    \'urn:perun:member:attribute-def:core:status';
our $STATUS_VALID;                      *STATUS_VALID =                       \'VALID';

my $PERUN_RESOURCE_PREFIX = 'https://perun.aai.muni.cz/facilities/facilityId/resources/resourceId';
my $struc = {};

my $loginDomain = $data->getFacilityAttributeValue(attrName => $A_FACILITY_LOGIN_SCOPE );
my $facilityId = $data->getFacilityId();
$PERUN_RESOURCE_PREFIX =~ s/facilityId/$facilityId/;

foreach my $resourceId ($data->getResourceIds()) {
	my $o365GroupId = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_O365_GROUP_ID );
	next unless $o365GroupId;
	my $keepExternalAccounts = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_KEEP_EXTERNAL_ACCOUNTS );
	if (exists $struc->{$o365GroupId}) {
		print 'Duplicate O365 group ID detected: ' . $o365GroupId;
		exit(1)
	}
	my $perunResourceUrl = $PERUN_RESOURCE_PREFIX;
	$perunResourceUrl =~ s/resourceId/$resourceId/;
	$struc->{$o365GroupId}->{'perunResourceUrl'} = $perunResourceUrl;
	$struc->{$o365GroupId}->{'keepExternalAccounts'} = $keepExternalAccounts ? defined $keepExternalAccounts : 0;

	foreach my $memberId ($data->getMemberIdsForResource( resource => $resourceId )) {
		my $memberStatus = $data->getMemberAttributeValue(member => $memberId, attrName => $A_MEMBER_STATUS);
		next unless $memberStatus eq $STATUS_VALID;
		my $login = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_USER_LOGIN );
		my $userPrincipalName = $login . '@' . $loginDomain;
		$struc->{$o365GroupId}->{'members'}->{$userPrincipalName} = 1;
	}
}

###Prepare struc for printing to JSON
my $printingStruc = {};
my @groupData = ();
foreach my $o365GroupId (sort keys %$struc) {
	my $record = {};
	$record->{'groupId'} = $o365GroupId;
	my @members = ();
	foreach my $login (sort keys %{$struc->{$o365GroupId}->{'members'}}) {
		push @members, $login;
	}
	$record->{'members'} = \@members;
	$record->{'keepExternalAccounts'} = $struc->{$o365GroupId}->{'keepExternalAccounts'};
	$record->{'perunResourceUrl'} = $struc->{$o365GroupId}->{'perunResourceUrl'};
	push @groupData, $record;
}
#sort the struc to get comparable output
@groupData = sort { $a->{'groupId'} cmp $b->{'groupId'} } @groupData;
$printingStruc->{'scope'} = $loginDomain;
$printingStruc->{'groups'} = \@groupData;

my $file_name = "$DIRECTORY/$::SERVICE_NAME";
####### output file ######################
open FILE,">$file_name" or die "Cannot open $file_name: $! \n";
print FILE JSON::XS->new->utf8->pretty->canonical->encode($printingStruc);
close(FILE);

perunServicesInit::finalize;
