#!/usr/bin/perl

use strict;

use EBox;
use EBox::Global;
use EBox::Config;
use EBox::Sudo qw(:all);
use EBox::Exceptions::Internal;

EBox::init();

my $global = EBox::Global->getInstance(1);
my $users = $global->modInstance('users');

# Initialize the LDAP database
sub init
{
    root("cp " . EBox::Config::share() . "/ebox-usersandgroups/slapd.default /etc/default/slapd");
    root("invoke-rc.d slapd restart");

    populate();
    setupSyncProvider();
}

sub setupSyncProvider
{
	$users->ldap->ldapCon;
	my $ldap = $users->ldap->{ldap};
    my $dn;
    my $result;

    # enable the syncprov module
    $dn = 'cn=module{0},cn=config';
    my %args = (
        add => [ 'olcModuleLoad' => 'syncprov' ]
    );
    $ldap->modify($dn, %args);

    # add indexes for entryCNS and entryUUID
    $dn = 'olcDatabase={1}hdb,cn=config';
    my %args = (
        replace => [ 'olcDbIndex' => ['objectclass eq',
                                      'entryCSN eq',
                                      'entryUUID eq'] ],
    );
    $ldap->modify($dn, %args);

    %args = (
        base => 'olcDatabase={0}config,cn=config',
        filter => 'olcOverlay=syncprov'
    );
    $result = $ldap->search(%args);
    if ($result->count() == 0) {
        $dn = 'olcOverlay={0}syncprov,olcDatabase={0}config,cn=config';
        $result = $ldap->add($dn, attr => [
            'objectClass' => [ 'olcOverlayConfig', 'olcSyncProvConfig' ],
            'olcOverlay' => '{0}syncprov',
            'olcSpCheckpoint' => '10 60',
            'olcSpSessionlog' => '100',
        ]);
    }

    %args = (
        base => 'olcDatabase={1}hdb,cn=config',
        filter => 'olcOverlay=syncprov'
    );
    $result = $ldap->search(%args);
    if ($result->count() == 0) {
        $dn = 'olcOverlay={0}syncprov,olcDatabase={1}hdb,cn=config';
        $result = $ldap->add($dn, attr => [
            'objectClass' => [ 'olcOverlayConfig', 'olcSyncProvConfig' ],
            'olcOverlay' => '{0}syncprov',
            'olcSpCheckpoint' => '10 60',
            'olcSpSessionlog' => '100',
        ]);
    }
}

sub populate
{
	$users->ldap->ldapCon;
	my $ldap = $users->ldap->{ldap};
	my $dn = $users->usersDn;
	my $result = $ldap->add($dn, attr => [
                                        'ou' => 'Users',
                                        'objectClass' => 'organizationalUnit'
                                             ]);
	($result->is_error) and warn "Cant initialize Users";

	$dn = $users->groupsDn;
	$result = $ldap->add($dn, attr => [
                                        'ou' => 'Groups',
                                        'objectClass' => 'organizationalUnit'
                                          ]);

	($result->is_error) and warn "Cant initialize Groups";

	my $defaultGroup = $users->defaultGroup();
	$users->addGroup($defaultGroup, 'All users', 1);

    $dn = $users->slavesDn;
    my $result = $ldap->add($dn, attr => [
        'ou' => 'slaves',
        'objectClass' => 'organizationalUnit'
    ]);
    ($result->is_error) and EBox::debug("Cant initialize Slaves");
}

sub clean 
{
	# clean users
	foreach my $user ($users->users){
		my $username = $user->{'username'};
		$users->delUser($username);		
	}

	# clean groups
	foreach my $group ($users->groups){
		my $groupname = $group->{'account'};
		$users->delGroup($groupname);		
	}
}

sub addSysUser
{
	my $user = { 'user' => $_[1], 
		     'fullname' => $_[2],
		     'password' => "{crypt}" . $_[3], 
		     'comment' => $_[4] };

	$users->addUser($user, 1);
}

sub addSysGroup
{

	$users->addGroup($_[1], $_[2]);
}

sub usage
{
	print "Usage: $0 (init | populate | addSysUser name fullname pwd commet | addSysGroup name comment)\n";
}

#main 


if ($#ARGV == -1) {
	usage();
	exit(1);
}

if ($ARGV[0] eq 'populate') {
	populate();
} elsif ($ARGV[0] eq 'clean') {
	clean();
} elsif ($ARGV[0] eq 'addSysUser') {
	unless ($#ARGV == 4) {
	        usage();
	}
	addSysUser(@ARGV);
} elsif ($ARGV[0] eq 'addSysGroup') {
	unless ($#ARGV == 2) {
	        usage();
	}
	addSysGroup(@ARGV);
} elsif ($ARGV[0] eq 'init') {
    init();
} else {
	usage();
}
