#!/usr/bin/perl
use feature "switch";
use strict;
use warnings;
use perunServicesInit;
use perunServicesUtils;
use utf8;

local $::SERVICE_NAME = "ad_user_mu_ucn";
local $::PROTOCOL_VERSION = "3.0.0";
my $SCRIPT_VERSION = "3.0.2";

perunServicesInit::init;
my $DIRECTORY = perunServicesInit::getDirectory;
my $fileName = "$DIRECTORY/$::SERVICE_NAME".".ldif";
my $baseDnFileName = "$DIRECTORY/baseDN";

my $data = perunServicesInit::getHashedHierarchicalData;

#Constants
our $A_F_BASE_DN;  *A_F_BASE_DN = \'urn:perun:facility:attribute-def:def:adBaseDN';
our $A_F_DOMAIN;  *A_F_DOMAIN = \'urn:perun:facility:attribute-def:def:adDomain';
our $A_F_UAC;  *A_F_UAC = \'urn:perun:facility:attribute-def:def:adUAC';
our $A_FIRST_NAME;  *A_FIRST_NAME = \'urn:perun:user:attribute-def:core:firstName';
our $A_LAST_NAME;  *A_LAST_NAME = \'urn:perun:user:attribute-def:core:lastName';
our $A_MAIL;  *A_MAIL = \'urn:perun:user:attribute-def:def:preferredMail';
our $A_LOGIN; *A_LOGIN = \'urn:perun:user_facility:attribute-def:virt:login';
our $A_CHIPNUMBERS; *A_CHIPNUMBERS = \'urn:perun:user:attribute-def:def:chipNumbers';
our $A_MEMBER_STATUS; *A_MEMBER_STATUS = \'urn:perun:member:attribute-def:core:status';
our $A_ALLOW_INACTIVE; *A_ALLOW_INACTIVE = \'urn:perun:resource:attribute-def:def:allowInactiveMembers';

our $A_R_NAME; *A_R_NAME = \'urn:perun:resource:attribute-def:core:name';

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

# CHECK ON FACILITY ATTRIBUTES
if (!defined($data->getFacilityAttributeValue( attrName => $A_F_BASE_DN ))) {
	exit 1;
}
if (!defined($data->getFacilityAttributeValue( attrName => $A_F_DOMAIN ))) {
	exit 1;
}
if (!defined($data->getFacilityAttributeValue( attrName => $A_F_UAC ))) {
	exit 1;
}

my $baseDN = $data->getFacilityAttributeValue( attrName => $A_F_BASE_DN );
my $domain = $data->getFacilityAttributeValue( attrName => $A_F_DOMAIN );
my $uac = $data->getFacilityAttributeValue( attrName => $A_F_UAC );

# GATHER USERS
my $users;  # $users->{$login}->{ATTR} = $attrValue;

#
# PRINT BASE_DN FILE
#
open FILE,">:encoding(UTF-8)","$baseDnFileName" or die "Cannot open $baseDnFileName: $! \n";
print FILE $baseDN;
close(FILE);

my $serviceAccountsDN = "OU=Services,OU=Perun,OU=MU,DC=ucn,DC=muni,DC=cz";

#
# AGGREGATE DATA
#
# FOR EACH RESOURCE
foreach my $resourceId ( $data->getResourceIds() ){

	my $allowInactiveMembers = $data->getResourceAttributeValue( resource => $resourceId, attrName => $A_ALLOW_INACTIVE);
	# EACH USER ON RESOURCE
	foreach my $memberId ($data->getMemberIdsForResource( resource => $resourceId )) {

		my $login = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_LOGIN );
		my $memberStatus = $data->getMemberAttributeValue( member => $memberId, attrName => $A_MEMBER_STATUS );
		#next unless ( $uAttributes{$A_MEMBER_STATUS} eq $STATUS_VALID || ( $uAttributes{$A_MEMBER_STATUS} eq $STATUS_EXPIRED && $rAttributes{$ALLOW_NOT_VALID_MEMBERS}));
		next unless ( ($memberStatus eq $STATUS_VALID) || ( ($memberStatus eq $STATUS_EXPIRED) && $allowInactiveMembers));

		unless ($login =~ /^s-/){
			$users->{$login}->{"DN"} = "CN=" . $login . "," . $baseDN;
		} else {
			$users->{$login}->{"DN"} = "CN=" . $login . "," . $serviceAccountsDN;
		}
		# store standard attrs
		$users->{$login}->{$A_FIRST_NAME} = $data->getUserAttributeValue(member => $memberId, attrName => $A_FIRST_NAME);
		$users->{$login}->{$A_LAST_NAME} = $data->getUserAttributeValue(member => $memberId, attrName => $A_LAST_NAME);
		$users->{$login}->{$A_MAIL} = $data->getUserAttributeValue(member => $memberId, attrName => $A_MAIL);
		$users->{$login}->{$A_CHIPNUMBERS} = $data->getUserAttributeValue(member => $memberId, attrName => $A_CHIPNUMBERS);
	}
}

#
# PRINT user data LDIF
#
open FILE,">$fileName" or die "Cannot open $fileName: $! \n";
binmode FILE, ":utf8";

# FOR EACH USER ON FACILITY
my @logins = sort keys %{$users};
for my $login (@logins) {

	# print attributes, which are never empty
	print FILE "dn: " . $users->{$login}->{"DN"} . "\n";

	print FILE "cn: " . $login . "\n";
	print FILE "samAccountName: " . $login . "\n";
	print FILE "userPrincipalName: " . $login . "\@" . $domain . "\n";
	# enable accounts (if not) using service propagation
	print FILE "userAccountControl: " . $uac . "\n";

	# skip attributes which are empty and LDAP can't handle it (FIRST_NAME, EMAIL)
	my $sn = $users->{$login}->{$A_LAST_NAME};
	my $givenName = $users->{$login}->{$A_FIRST_NAME};
	my $displayName = "";
	if (defined $givenName and length $givenName){
		$displayName = $displayName . $givenName;
	}
	if (defined $sn and length $sn){
		$displayName = $displayName . (length $displayName ? " " : "") . $sn;
	}
	# Use login as displayname if it's empty.
	if (!defined $displayName and !length $displayName){
		$displayName = $login;
	}

	my $mail = $users->{$login}->{$A_MAIL};

	if (defined $displayName and length $displayName) {
		print FILE "displayName: " . $displayName . "\n";
	}
	if (defined $sn and length $sn) {
		print FILE "sn: " . $sn . "\n";
	}
	if (defined $givenName and length $givenName) {
		print FILE "givenName: " . $givenName . "\n";
	}
	if (defined $mail and length $mail) {
		print FILE "mail: " . $mail . "\n";
	}
	foreach (@{$users->{$login}->{$A_CHIPNUMBERS}}){
		next if ($_ eq "");
		print FILE "houseIdentifier: " . $_ . "\n";
	}

	# print classes
	print FILE "objectclass: top\n";
	print FILE "objectclass: person\n";
	print FILE "objectclass: user\n";
	print FILE "objectclass: organizationalPerson\n";

	# There MUST be an empty line after each entry, so entry sorting and diff works on slave part
	print FILE "\n";

}

close(FILE);

perunServicesInit::finalize;