/**
 * Created by andrei on 08.04.16.
 */
define([
        "dojo/_base/declare",
        "dojo/_base/lang",
        "dojo/when",
        "implab/safe",
        "../ForbiddenException"],
    function (declare, lang, when, safe, ForbiddenException) {
        return declare(null, {
            _container: null,
            _sessionData: null,
            /**
             * Создавать анонимную сессию. Если прозрачная аутентификация не
             * проводилась, и текущей сессии нет, то может быть создана сессия
             * для анонимного пользователя. Это сделано опцией, поскольку не во
             * всех системах требуется, отслеживать активность анонимных
             * пользователей (это не бесплатно).
             */
            _createAnonymousSession: false,

            /**
             * Регистрировать пользователей, полученных из внешнего источника
             * аутентификации.
             */
            _autoRegisterUsers: false,

            constructor: function (options) {
                safe.argumentNotNull(options, "options");
                safe.argumentNotNull(options.container, "options.container");

                this._container = options.container;

                this._createAnonymousSession = options.createAnonymousSession || this._createAnonymousSession;
                this._autoRegisterUsers = options.autoRegisterUsers || this._autoRegisterUsers;

                this._sessionData = this._initSession();
            },
            getSessionData: function () {
                return this._sessionData;
            },

            /**
             * @remarks Сосздание/восстановление сессии происходит в несколько
             *          этапов 1. Получаем текущую сессию. 2. Если упешно, то
             *          выходим. 3. Получаем идентификатор пользователя,
             *          используя identityProvider 4. Если успешно 5. Создаем
             *          новую сессию для полученного пользователя, выходим 6.
             *          Иначе если установлен параметр _createAnonymousSession 7.
             *          Создаем новую анонимную сессию. 8. Иначе, выходим
             */
            _initSession: function () {
                let me = this;

                let securityAuthority = me._container.getService("securityAuthority");
                let securityProvider = me._container.getService("securityProvider");
                let identityProvider = me._container.getService("identityProvider");

                if (!securityAuthority)
                    throw new Error("Sessions are not supported, no security authority is supplied");


                // пытаемся получить текущую сессию
                return when(securityAuthority.getSession(), function (session) {
                    if (session)
                        return session;

                    // пытаемся создать сессию с использованием
                    // пользователя из внешнего
                    // источника аутентификации
                    if (identityProvider) {
                        return when(identityProvider.getUserLogin(), function (login) {
                            if (login) {
                                return when(securityProvider.createUserIdentity(login, false, {
                                    createUser: me._autoRegisterUsers
                                }), function (uid) {
                                    return securityAuthority.initSession(uid);
                                }, function (err) {
                                    console.log("Failed to create session for '" + login + "' ", err);
                                    throw new ForbiddenException();
                                });
                            } else if (me._createAnonymousSession) {
                                return when(securityProvider.getAnonymousIdentity(), function (uid) {
                                    return securityAuthority.initSession(uid);
                                });
                            } else {
                                throw new ForbiddenException();
                            }
                        });
                    } else if (me._createAnonymousSession) {
                        return when(securityProvider.getAnonymousIdentity(), function (uid) {
                            return securityAuthority.initSession(uid);
                        });
                    }

                    throw new ForbiddenException();
                });
            }
        });
    });