Source: managers/session.js

define('application/managers/session', [
    'application/managers/api',
    'antie/storageprovider',
    'antie/runtimecontext',
    'antie/class',
    'rofl/lib/promise',
    'rofl/lib/utils',
    'application/managers/recording',
    'application/managers/feature',
    'application/managers/channel',
    'application/events/parentalcontrol',
    'application/models/configuration',
    'application/events/lockedevent'
], function (
    ApiManager,
    StorageProvider,
    RuntimeContext,
    Class,
    Promise,
    Utils,
    RecordingManager,
    FeatureManager,
    ChannelManager,
    ParentalControlEvent,
    KPNConfig,
    LockedEvent
) {
    'use strict';

    var REFRESH_TIMEOUT_TIME = 25 * 60 * 1000, // 25 minutes
        WARM_WELCOME_DISPLAYS = 1,
        HEADERS = {
            default: 'http://www.itvonline.nl',
            smarttv: 'http://smarttv.itvonline.nl'
        },
        userPin,
        application,
        recordingManager,
        featureManager,
        api,
        device,
        storage,
        sessionStorage,
        instance,
        SessionManager,
        kpnStorage;

    SessionManager = Class.extend({

        /**
         * Initialises the session manager.
         */
        init: function () {
            api = ApiManager.getKPNAPI();
            device = RuntimeContext.getDevice();
            storage = device.getStorage(StorageProvider.STORAGE_TYPE_PERSISTENT, 'storage');
            sessionStorage = device.getStorage(StorageProvider.STORAGE_TYPE_SESSION, 'storage');
            recordingManager = RecordingManager.getInstance();
            featureManager = FeatureManager.getInstance();
            application = RuntimeContext.getCurrentApplication();
            kpnStorage = device.getStorage(StorageProvider.STORAGE_TYPE_PERSISTENT, 'kpn-channel');

            this._parentalOn = storage.getItem('parental');

            document.addEventListener('visibilitychange', Utils.bind(this._onVisibilityChange, this));
        },

        /**
         * Visibility change event.
         *
         * @param {Object} e - The event data.
         * @private
         */
        _onVisibilityChange: function (e) {
            if (document.visibilityState === 'visible' || e === 'visible') {
                storage.setItem('parental', true);
                this._parentalOn = true;
                this.setUserPin(null);

                setTimeout(function () {
                    application.broadcastEvent(new LockedEvent());
                }, 2000);
            }
        },

        /**
         * Returns true if the user is logged in.
         *
         * @returns {boolean} - Returns true if the user is logged in.
         */
        isLoggedIn: function () {
            return storage.getItem('login');
        },

        /**
         * Sets the user login.
         *
         * @param {Object} user - The user data.
         */
        setUserLogin: function (user) {
            storage.setItem('login', user);
        },

        /**
         * Sets the user pin.
         *
         * @param {string|null} pin - The user pin.
         */
        setUserPin: function (pin) {
            userPin = pin;
            application.broadcastEvent(new ParentalControlEvent(pin === null));

            this._parentalOn = pin === null;
        },

        /**
         * Returns the user pin.
         *
         * @returns {string} - The user pin.
         */
        getUserPin: function () {
            return userPin;
        },

        /**
         * Returns parental controls user settings.
         *
         * @returns {Object} ParentalSettings - Parental control settings.
         */
        getUserPCParams: function () {
            return storage.getItem('userParentalControlSettings');
        },

        /**
         * Sets the user PC parameters.
         *
         * @param {Object} parentalControlParams - Parental control params.
         */
        setUserPCParams: function (parentalControlParams) {
            storage.setItem('userParentalControlSettings', parentalControlParams);
        },

        /**
         * Sets local parental switch.
         *
         * @param {boolean} parentalControlSwitch - Parental control params.
         */
        setLocalPC: function (parentalControlSwitch) {
            sessionStorage.setItem('parental', parentalControlSwitch);
            this._parentalOn = parentalControlSwitch;
        },

        /**
         * Saves username.
         *
         * @param {Object} accountnumber - Account number.
         */
        setAccountNumber: function (accountnumber) {
            storage.setItem('username', accountnumber);
        },

        /**
         * Saves amount of displayed welcome screen.
         */
        increaseWarmWelcomeDisplayCount: function () {
            var index = storage.getItem('warm-welcome-displayed') || 0;

            index++;

            storage.setItem('warm-welcome-displayed', index);
        },

        /**
         * Resets the warm welcome display.
         */
        resetWarmWelcome: function () {

            storage.setItem('warm-welcome-displayed', 0);
        },

        /**
         * Resets channel to play.
         */
        resetChannel: function () {

            kpnStorage.setItem('last-watched-channelid', '');
        },

        /**
         * Returns true if should show warm welcome screen.
         *
         * @returns {boolean} - True if should show warm welcome.
         */
        shouldShowWarmWelcome: function () {
            var current = storage.getItem('warm-welcome-displayed') || 0;

            return current < WARM_WELCOME_DISPLAYS;
        },

        /**
         * Get username.
         *
         * @returns {string} Username.
         */
        getAccountNumber: function () {
            return storage.getItem('username');
        },

        /**
         * Clears the user login.
         */
        clearUserLogin: function () {
            storage.removeItem('login');
            storage.removeItem('last-watched-channelid');
            this.setUserPin(null);

            recordingManager.reset();
        },

        /**
         * Sets the entry confirmed state.
         */
        setEntryConfirmed: function () {
            storage.setItem('entry', true);
        },

        /**
         * Resets the entry.
         */
        resetEntry: function () {
            storage.removeItem('entry');
        },

        /**
         * Returns true if the entry is confirmed.
         *
         * @returns {boolean} - True if the entry is confirmed.
         */
        isEntryConfirmed: function () {
            return storage.getItem('entry');
        },

        /**
         * Returns true if parental is on.
         *
         * @returns {boolean} - True if parental is on.
         */
        isParentalOn: function () {

            return this._parentalOn;
        },

        /**
         * Logs the user in.
         *
         * @param {string} username - The username.
         * @param {string} password - The password.
         * @returns {Promise} - Promise resolving after logging in.
         */
        login: function (username, password) {

            // User is already logged in.
            if (this.isLoggedIn()) {
                return Promise.resolve(true);
            }

            // Log the user in for the given username and password.
            return api.create('session', {
                data: {
                    credentialsStdAuth: {
                        username: username,
                        password: password,
                        remember: 'Y',
                        deviceRegistrationData: {
                            deviceId: device.getUdid().toString(),
                            accountDeviceIdType: 'DEVICEID',
                            deviceType: 'SMARTTV',
                            vendor: device.getBrand(),
                            appVersion: application.getConfiguration().version
                        }
                    }
                },
                headers: {
                    AVSSite: this.getAVSSiteHeader()
                },
                withCredentials: true
            }).then(Utils.bind(function (user) {

                return ChannelManager.getInstance().load()
                    .then(Utils.bind(function () {

                        application.route('menu');

                        if (featureManager.isRecordingEnabled() && user.canRecord()) {
                            return recordingManager.getRecordings({
                                forceReload: true
                            })
                                .then(Utils.bind(function () {
                                    this.startRefreshSessionTimeout();
                                }, this));
                        }

                        this.startRefreshSessionTimeout();
                    }, this));
            }, this));
        },

        /**
         * Prepares the user.
         *
         * @returns {Promise} - Promise resolving after logging in.
         */
        prepareUser: function () {
            return api.create('session', {
                data: {
                    credentialsStdAuth: {
                        deviceRegistrationData: {
                            deviceId: device.getUdid().toString(),
                            accountDeviceIdType: 'DEVICEID'
                        }
                    }
                },
                headers: {
                    AVSSite: this.getAVSSiteHeader()
                },
                withCredentials: true
            }).then(Utils.bind(function (user) {

                return ChannelManager.getInstance().load()
                    .then(Utils.bind(function () {

                        application.route('menu');

                        if (featureManager.isRecordingEnabled() && user.canRecord()) {
                            return recordingManager.getRecordings({
                                forceReload: true
                            })
                                .then(Utils.bind(function () {
                                    this.startRefreshSessionTimeout();
                                }, this));
                        }

                        this.startRefreshSessionTimeout();
                    }, this));
            }, this));
        },

        /**
         * Manually refresh users token.
         *
         * @returns {Promise} - Refresh token promise.
         */
        refreshToken: function () {
            return api.create('session', {
                data: {
                    credentialsStdAuth: {
                        deviceRegistrationData: {
                            deviceId: device.getUdid().toString(),
                            accountDeviceIdType: 'DEVICEID'
                        }
                    }
                },
                headers: {
                    AVSSite: this.getAVSSiteHeader()
                },
                withCredentials: true
            });
        },

        /**
         * Logs the user out.
         *
         * @returns {Promise} - Promise resolving after logging out.
         */
        logout: function () {
            var self = this;

            this.clearRefreshSessionTimeout();

            return api.destroy('session', {
                headers: {
                    AVSSite: this.getAVSSiteHeader()
                },
                withCredentials: true
            }).then(function () {
                self.resetWarmWelcome();
                self.clearUserLogin();
                self.resetChannel();
            })
            ['catch'](function () {
                self.resetWarmWelcome();
                self.clearUserLogin();
            });
        },

        /**
         * Starts the refresh session timeout.
         */
        startRefreshSessionTimeout: function () {
            var now = application.getDate(),
                deltaRefreshTime = (now - this.lastRefreshTime),
                refreshPromise;

            this.lastRefreshTime = now;
            this.clearRefreshSessionTimeout();

            refreshPromise = (deltaRefreshTime >= REFRESH_TIMEOUT_TIME)
                ? this.refreshToken()
                : this.getProfile();

            refreshPromise
                .then(Utils.bind(function () {
                    this._refreshSessionTimeout = setTimeout(
                        Utils.bind(this.startRefreshSessionTimeout, this),
                        REFRESH_TIMEOUT_TIME);
                }, this));
        },

        /**
         * Reads the profile model.
         *
         * @returns {Promise} Read profile.
         */
        getProfile: function () {
            return api.read('profile', {
                withCredentials: true
            });
        },

        /**
         * Clears the refresh session timeout.
         */
        clearRefreshSessionTimeout: function () {
            clearTimeout(this._refreshSessionTimeout);
        },

        /**
         * Returns the last service message number.
         *
         * @returns {Date} - The last service message.
         */
        getLastServiceMessageShown: function () {
            return this._lastServiceMessage;
        },

        /**
         * Sets the last service message date.
         */
        setLastServiceMessageShown: function () {
            this._lastServiceMessage = new Date();
        },

        /**
         * Returns the AVSSite header.
         *
         * @returns {string} - The AVSSite header value.
         */
        getAVSSiteHeader: function () {
            var apiSetting = RuntimeContext.getCurrentApplication().getAPISetting();

            if (apiSetting === KPNConfig.APIS.BETA) {
                return HEADERS.smarttv;
            }

            return HEADERS.default;
        }
    });

    return {

        /**
         * Returns the instance.
         *
         * @returns {Object} - The instance.
         */
        getInstance: function () {

            if (!instance) {
                instance = new SessionManager();
            }

            return instance;
        }
    };
});