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

local $::SERVICE_NAME = "ad_user_mu";
local $::PROTOCOL_VERSION = "3.0.1";
my $SCRIPT_VERSION = "3.0.2";

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

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_F_AZURE_DOMAIN;  *A_F_AZURE_DOMAIN = \'urn:perun:facility:attribute-def:def:adAzureDomain';
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_DISPLAY_NAME;  *A_DISPLAY_NAME = \'urn:perun:user:attribute-def:core:displayName';
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_WORKPLACE; *A_WORKPLACE = \'urn:perun:user:attribute-def:def:workplace';
our $A_WORKPLACE_ID; *A_WORKPLACE_ID = \'urn:perun:user:attribute-def:def:workplaceId';

# 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 );
my $azureDomain = $data->getFacilityAttributeValue( attrName => $A_F_AZURE_DOMAIN );

# 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);

#
# PRINT OPT_ATTRS FILE
#
open FILE,">:encoding(UTF-8)","$optAttrsFileName" or die "Cannot open $optAttrsFileName: $! \n";
print FILE ""; # always have an empty file
if (defined $azureDomain) { print FILE "msDS-cloudExtensionAttribute1"; }
# append newline in case of adding another attribute !
close(FILE);

#
# AGGREGATE DATA
#
# FOR EACH USER
foreach my $memberId ($data->getMemberIdsForFacility()) {

	my $login = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_LOGIN );

	$users->{$login}->{"DN"} = "CN=" . $login . "," . $baseDN;
	# 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_DISPLAY_NAME} = $data->getUserAttributeValue( member => $memberId, attrName => $A_DISPLAY_NAME );
	$users->{$login}->{$A_MAIL} = $data->getUserAttributeValue( member => $memberId, attrName => $A_MAIL );
	$users->{$login}->{$A_WORKPLACE} = $data->getUserAttributeValue( member => $memberId, attrName => $A_WORKPLACE );
	$users->{$login}->{$A_WORKPLACE_ID} = $data->getUserAttributeValue( member => $memberId, attrName => $A_WORKPLACE_ID );

}

#
# 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) {

	unless ($login =~ /^9[0-9]{1,6}$/ or $login =~ /^[0-9]{1,6}$/) {
		# We now always skip non-UČO users !!
		next;
	}

	# 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 = $users->{$login}->{$A_DISPLAY_NAME};
	my $mail = $users->{$login}->{$A_MAIL};
	my $workplace = $users->{$login}->{$A_WORKPLACE};
	my $workplaceId = $users->{$login}->{$A_WORKPLACE_ID};

	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";
	}
	if (defined $workplace and length $workplace) {
		if (length $workplace > 64) {
			# AD has internal limit to 64 chars for department attribute
			$workplace = substr($workplace, 0, 64);
		}
		print FILE "Department: " . $workplace . "\n";
	}
	if (defined $workplaceId and length $workplaceId) {
		print FILE "departmentNumber: " . $workplaceId . "\n";
	}

	# OPT ATTRIBUTES

	if (defined $azureDomain) {
		# manage mapping to Azure AD if present in AD config
		print FILE "msDS-cloudExtensionAttribute1:" . $login . "@" . $azureDomain . "\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;
