/**
 * the top level controller
 */
angular.module("sn.$sp").controller("spPageCtrl", function($scope, $http, $location, $window, spAriaUtil, spUtil, spMetatagService, spAnnouncement,
    snRecordWatcher, $rootScope, spPage, spAriaFocusManager, $timeout, spAtf, spGtd, spContextManager, tinymceService, snAnalyticsUtil, snAnalytics) {
    'use strict';

    var _ = $window._;

    var c = this;
	
    var hasDynamicHeaderFooter = true;

    c.doAnimate = false; // Used to prevent animation on the first page load
    c.firstPage = true; // @todo: Instead of having a global flag, we should fire an event once.
    $scope.theme = {};
    $scope.page = {
        title: "Loading..."
    }; //@todo: This string needs to allow translation.

    $scope.sessions = {}; //@todo: that needs to be in a Factory. Check 'sessions' widget.

    if ($window.NOW.sp_show_console_error) {
        spPage.showBrowserErrors();
    }

    // Fetch tinymce script asynchronously
    tinymceService.loadTinymceAsync();

    // This is used for the ng-style on containers
    c.parseJSON = function(str) {
        return JSON.parse(str);
    };

    c.getContainerClasses = function(container) {
        var classes = [];

        if (!container.bootstrap_alt) {
            classes[classes.length] = container.width;
        }

        if (container.container_class_name) {
            classes[classes.length] = container.container_class_name;
        }

        return classes;
    };

    /***
     * first page load and subsequent location changes
     */

    var oid = $location.search().id;
    var oldPath = $location.path();
    var locationChanged = false;

    function isNavigateOutPortal(newUrl, oldUrl) {
        var newUrlParser = document.createElement('a'),
            oldUrlParser = document.createElement('a');

        newUrlParser.href = newUrl;
        oldUrlParser.href = oldUrl;

        //navigate to external url
        if (newUrlParser.hostname !== oldUrlParser.hostname)
            return true;

        //navigate inside same portal
        if (newUrlParser.pathname === oldUrlParser.pathname)
            return false;


        //navigate to out from current portal
        return true;
    }

    $rootScope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
        if (newUrl !== oldUrl && isNavigateOutPortal(newUrl, oldUrl)) {
            event.preventDefault();
            $window.location = newUrl;
        }
    });

    $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {
        locationChanged = (oldUrl != newUrl);
        var s = $location.search();
        var p = $location.path();

        // Has portal changed?
        if (oldPath != p) {
            $window.location.href = $location.absUrl();
            return;
        }

        // page is handling?
        if (angular.isDefined($scope.containers) && oid == s.id && s.spa) {
            return;
        }

        if (spPage.isHashChange(newUrl, oldUrl)) {
            return;
        }

        if (!g_persist_msgs_through_page_nav)
            $scope.$broadcast('$$uiNotification.dismiss');
        if (newUrl = spPage.containsSystemPage(p)) {
            $window.location.href = newUrl;
            return;
        }

        // Redirect if the current page is the login page
        if (!$window.NOW.has_access && locationChanged) {
            $window.location.href = $location.absUrl();
            return;
        }

        oid = s.id;

        getPage();
    });

    function loadPage(r) {
        var response = r.data.result;

        spMetatagService.setTags(response.metatags);
        spMetatagService.setSeoTags(response.seotags);

        c.firstPage = false;

        $scope.containers = _.filter(response.containers, {
            'subheader': false
        });

        $scope.subheaders = _.filter(response.containers, {
            'subheader': true
        });

        // promote to root
        var p = response.page;
        var u = response.user;

        /*
         * All initial page loads already handle authentication (showing login page)
         * so if $location has changed and page is not public, reload to show the login page.
         * That way, the URL stays the same, and user will see correct page after login.
         */
        if (!spPage.isPublicOrUserLoggedIn(p, u)) {
            if (locationChanged) {
                $window.location.href = $location.absUrl();
                return;
            }
        }

		if(r.config && r.config.url){
			response.page.url = $window.location.origin.concat(r.config.url);
		}
		
        $rootScope.page = $scope.page = p;

        $(spPage.getElement(p)).remove(); // Removes Page CSS
        $(spPage.getStyle(p)).appendTo('head'); // Adds Page CSS

        response.portal = $rootScope.portal;
        //$window.document.title = spPage.getTitle(response);

        $scope.$broadcast('$sp.scroll', {
            position: 0
        }); // Scroll to the Top of the page

        //@todo: Cleanup variable trains
        //STRY50668467: By avoiding header/footer server script calls, empty theme will be returned from server response from second page load request onwards. Handling the same with this condition.
        if (response.theme) {
            var theme = response.theme;
            $rootScope.theme = $scope.theme = theme;
            var isHeaderDynamic = theme.header && (theme.header['static'] === false);
            var isFooterDynamic = theme.footer && (theme.footer['static'] === false);
            hasDynamicHeaderFooter = !!(isHeaderDynamic || isFooterDynamic);
        }

        c.style = spPage.getClasses($scope);

        if (!$scope.user) {
            $rootScope.user = $scope.user = {};
        }

        $scope.g_accessibility = spAriaUtil.g_accessibility;

        angular.extend($scope.user, response.user);
        $scope.user.logged_in = spPage.userLoggedIn($scope.user);
        $scope.$broadcast('$$uiNotification', response.$$uiNotification);
        if ($scope.user.logged_in && !p.omit_watcher)
            snRecordWatcher.init();

        $timeout(function() {
            c.doAnimate = true;
        }, 500);

        //gtd specific code

        //PRB1402276: Guided Tours on Service Portal will auto-launch even when the device screen size is within the mobile range
        if (spUtil.isMobile()) {
            NOW.sp.enableTours = false;
        }

        if (NOW && NOW.sp && NOW.sp.enableTours && $scope.user.logged_in) {
            spGtd.getToursForPage({
                    portal: $rootScope.portal,
                    page: $rootScope.page,
                    user: $rootScope.user
                })
                .then(function(data) {
                    $rootScope.$broadcast('sp-menu-update-tours', data);
                    //for cases when the sp-header has not yet loaded
                    $scope.$on('sp-header-loaded', function() {
                        $rootScope.$broadcast('sp-menu-update-tours', data);
                    });
                });
        }

        spContextManager.init();

        var recordInfo = {};
        var queryParams = $location.search();
        Object.keys(queryParams).forEach(function(key) {
            if (key === 'table' || key === 'sys_id')
                recordInfo[key] = queryParams[key];
        });

        if (recordInfo.table || recordInfo.sys_id)
            spContextManager.updateContextForKey('record', recordInfo);

        sendAnalytics(response.page);
        return r;
    }

    function sendAnalytics(page) {
        snAnalytics.startPage(page.id, page.static_title);
    }

    $rootScope.$on('sn.ucm.finished', function() {
        // just after login when page loads we do call startPage but it will fail because of analytic checks (ucm has to be finished to pass analytic checks)
        // so we need to listen to 'sn.ucm.finished' event so that we can send the initial page payload to appsee :)
        sendAnalytics($scope.page);

        if (NOW.ucm_invocations != 1)
            return;
        // send successful login event
        // Make sure event is sent after page is set so no empty pages will be marked on login
        var payload = {};
        payload.name = "Successful Login";
        payload.data = {};
        payload.data["Login"] = "true";
        snAnalytics.addEvent(payload);
    });

    function setupAtf() {
        spAtf.init().then(function(atf) {
            atf.triggerPageLoaded();
        });
    }

    function signalPageLoaded() {
        $rootScope.$emit('sp.page.loaded', $rootScope);
        displayAnalyticsConsentModal();
    }

    function displayAnalyticsConsentModal() {
        // return if sp_config portal
        if ($rootScope.portal && $rootScope.portal.sys_id == 'db57a91047001200ba13a5554ee49050')
            return;

        // once page is loaded invoke UCM egnine which decides whether to display consent modal to user or not
        snAnalyticsUtil.invokeUCMEngine();
    }

    function getSPPageResponse() {
        if (NOW.spPageResponse) {
            return NOW.spPageResponse.then(function(response) {
                return {
                    data: response
                }
            });
        } else {
            var data = {};
            data.session = 'new';
            return spUtil.get('set_session_params', data).then(function() {
                return $http({
                    method: 'GET',
                    url: spPage.getUrl($scope.portal_id, !hasDynamicHeaderFooter),
                    headers: spUtil.getHeaders()
                })
            }, function() {
                return $http({
                    method: 'GET',
                    url: spPage.getUrl($scope.portal_id, !hasDynamicHeaderFooter),
                    headers: spUtil.getHeaders()
                })
            });

        }
    }

    function getPage() {
        return getSPPageResponse()
            .then(loadPage, handlePageLoadErrors)
            .then(function(res) {
                // Forcing announcements to load with the page
                spAnnouncement.init(res.data.result.announcements).then(function() {
                    spAriaFocusManager.pageLoadComplete($location.url());
                    setupAtf();
                });
            })
            .then(signalPageLoaded)
            .then(function() {
                NOW.spPageResponse = null;
            });
    }

    function handlePageLoadErrors(error) {
        var absUrl = $location.absUrl();
        var url = $location.url();
        var path = $location.path();
        // PRB1389764 : For unauthorized exceptions refreshing url with redirect URL as portal page
        if ('Unauthorized' == error.statusText || '401' == error.status) {
            absUrl = absUrl.replace(url, path + '?sysparm_goto_url=' + $rootScope.portal.url_suffix);
            $window.location.href = absUrl;
        }
        //For other than unauthorized errors, intimating js error in the console.
        console.error(error);
        return Promise.reject(error);
    }

    $scope.$on('sp.page.reload', getPage);

    // keyboard shortcut to save form - broadcasts out $sp.save
    $($window).keydown(spPage.saveOnCtrlS);

    $scope.$on('$destroy', function() {
        $($window).off('keydown', spPage.saveOnCtrlS);
    });

    c.focusOnPageTitle = function() {
        spAriaFocusManager.focusOnPageTitle();
    }
	
	function deferScripts(wait) {
        var delay = wait || 0;
        $timeout(function() {
            var element = document.createElement('script');
            element.src = 'scripts/js_includes_sp_defer.js?v=' + g_builddate;
            element.onload = function() {
                $rootScope.$broadcast("sp.defer_scripts.loaded");
            };
            document.body.appendChild(element);
            tinymceService.loadTinymceAsync();
        }, delay);
    }
	
	
   deferScripts();
});