<?php

class LdapUserImporter extends AbstractLdapImporter
{

    protected function loadLdapRelatedModels($ldapInterfaceId)
    {
        return User::model()->findAllByAttributes(array('ldapInterface' => $ldapInterfaceId));
    }

    protected function updateContact($attributes, $ldapInterface)
    {
        $model = $this->getModelInstance($attributes['ldapId'], $ldapInterface->id);
        $this->updateModelData($model, $attributes);
    }

    protected function getModelInstance($ldapId, $ldapInterfaceId)
    {
        $model = User::model()->findByAttributes(
                [
                    'ldapId' => $ldapId,
                    'ldapInterface' => $ldapInterfaceId
                ]
        );
        if (!isset($model)) {
            Log::d("Creating new contact for LDAP ID $ldapId.", 'LdapUserImporter');
            $model = new User();
            $model->ldapInterface = $ldapInterfaceId;
        }
        $model->scenario = 'LdapImport';

        return $model;
    }

    private function updateModelData($user, $attributes)
    {
        $seperatedAttributes = $this->seperateModelSpecificAttributes($attributes);
        if (!$user->isNewRecord()) {
            $this->updateSipAccount($user->id, $user->extension, $seperatedAttributes['User']['extension']);
        }
        $user->attributes = $seperatedAttributes['User'];
        if (!isset($user->group)) {
            $user->group = $this->GetAllUsersID();
        }
        if ($user->isNewRecord()) {
            $this->beforeImport($user);
        }
        //turned off validation on save because of passwordStrength class
        if ($user->validate()) {
            $user->save(false);
            $this->afterImport($user, $seperatedAttributes);
        } else {
            Log::e("User $user->ldapId can not be saved.", "LDAP Interface");
            Log::e(json_encode($user->errors), "LDAP Interface");
        }
    }

    private function seperateModelSpecificAttributes($attributes)
    {

        $userAttributes = array('name', 'extension', 'firstname', 'lastname', 'email', 'group', 'ldapId');

        foreach ($attributes as $key => $value) {
            if (in_array($key, $userAttributes)) {
                $attributes['User'][$key] = ($key != 'group') ? $value : $this->getGroupByName($value);
            } else {
                $attributes['Address'][$key] = $value;
            }
            unset($attributes[$key]);
        }

        return $attributes;
    }

    private function updateSipAccount($id, $oldExtension, $newExtension)
    {
        if ($newExtension !== $oldExtension) {
            $account = SipAccounts::model()->findByAttributes(
                    array(
                        'user_id' => $id,
                        'authname' => $oldExtension
                    )
            );
            if (isset($account)) {
                $account->authname = $newExtension;
                $account->save();
            }
        }
    }

    protected function beforeImport($newUser)
    {
        $newUser->isSystemAdmin = null;
        $newUser->password = $this->getDefaultPassword();
        $newUser->passwordPlainText = $newUser->password;
        if (!isset($newUser->pin)) {
            $newUser->pin = $this->getDefaultPIN();
        }
    }

    private function getGroupByName($group)
    {
        return empty($group) ? $this->GetAllUsersID() : $this->GetGroupIdByName($group);
    }

    private function getDefaultPassword()
    {
        $defaultPassword = cfg("DEFAULT_NEW_USER_PASSWORD");
        if (empty($defaultPassword)) {
            $defaultPassword = PasswordGenerator::generateUserPassword();
        }
        return $defaultPassword;
    }

    private function getDefaultPIN()
    {
        $defaultPIN = cfg("DEFAULT_NEW_USER_PIN");
        if (empty($defaultPIN)) {
            $defaultPIN = PasswordGenerator::generateUserPIN();
        }
        return $defaultPIN;
    }

    private function GetGroupIdByName($groupName)
    {
        if (strlen($groupName) > 40) {
            $names = explode(', ', $groupName);
            $groupName = (strlen($names[0]) > 40) ? substr($names[0], 0, 40) : $names[0];
        }
        $group = Groups::model()->findByAttributes(array('name' => $groupName));
        if (!isset($group)) {
            $group = new Groups();
            $group->name = $groupName;
            $group->parent = $this->GetAllUsersID();
            $group->save();
        }
        return $group->id;
    }

    protected function GetAllUsersID()
    {
        $group = Groups::model()->findByAttributes(array('type' => 'allUsers'));
        return $group->id;
    }

    protected function afterImport($user, $attributes)
    {
        if (isset($user->passwordPlainText)) {
            $user->unsetAttributes(array('password'));
            $user->zrtp = 0;
            $user->password = $user->passwordPlainText;
        }
        $this->upadteInternAddress($user, $attributes);

        //turned off validation on save because of passwordStrength class
        if ($user->validate()) {
            $user->save(false);
        } else {
            Log::e("User $user->ldapId can not be saved.", "LDAP Interface");
            Log::e(json_encode($user->errors), "LDAP Interface");
        }
    }

    protected function upadteInternAddress($user, $attributes)
    {
        $internAddressbook = Addressbook::model()->findByAttributes(array('type' => AddressbookType::intern));
        if ($internAddressbook) {
            $internAddress = $this->getInternAddress($user, $internAddressbook->id);
            if (isset($attributes['Address'])) {
                $internAddress->attributes = $attributes['Address'];
            }
            $this->setUserAddressAttributes($user->attributes, $internAddress);
            if ($internAddress->save()) {
                $user->addressReferece = $internAddress->id;
            } else {
                Log::e("Inernal Address $user->name can not be saved.", "LDAP Interface");
                Log::e(json_encode($internAddress->errors), "LDAP Interface");
            }
        }
    }

    protected function getInternAddress($newUser, $addressbookId)
    {
        if (isset($newUser->addressReferece)) {
            $internAddress = Addresses::model()->findByPk($newUser->addressReferece);
            if (isset($internAddress)) {
                return $internAddress;
            }
        }

        return $this->createNewAddress($addressbookId);
    }

    private function createNewAddress($addressbookId)
    {
        $internAddress = new Addresses();
        $internAddress->contact_owner = 'intern';
        $internAddress->source = AddressSourceType::LDAP;
        $internAddress->contact_tid = $addressbookId;

        return $internAddress;
    }

    protected function setUserAddressAttributes($newAttributes, $internAddress)
    {
        if ($newAttributes['firstname'] . $newAttributes['lastname'] === "") {
            $internAddress->n_given = $newAttributes['name'];
        } else {
            $internAddress->n_given = $newAttributes['firstname'];
            $internAddress->n_family = $newAttributes['lastname'];
        }

        $internAddress->contact_email = $newAttributes['email'];
        $internAddress->tel_work = $newAttributes['extension'];
    }
}
