(function() {
            
            // Localize jQuery variable
            var jQuery;
            //alert('framework');
            //if (window.jQuery !== undefined) { console.log('Version of jQuery which is already loaded in local: ' + window.jQuery.fn.jquery); }
                
            /******** Load jQuery if not present (1.7 Minimum) *********/
            var needtoLoad = false;
            if (window.jQuery === undefined) {
                needtoLoad = true;
            } else { 
                version = window.jQuery.fn.jquery.split('.');
                if (parseInt(version[0]) < 2) {
                    if (parseInt(version[0]) < 1) needtoLoad = true;
                    if (parseInt(version[0]) == 1 && parseInt(version[1]) < 7) needtoLoad = true;
                }
            }
            
            //console.log(needtoLoad);
            if (needtoLoad) {
                //console.log('Dynamically loading jQuery in framework scope');
                var script_tag = document.createElement('script');
                script_tag.setAttribute('type','text/javascript');
                script_tag.setAttribute('src',
                    'https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js');
                if (script_tag.readyState) {
                  script_tag.onreadystatechange = function () { // For old versions of IE
                      if (this.readyState == 'complete' || this.readyState == 'loaded') {
                          scriptLoadHandler();
                      }
                  };
                } else { // Other browsers
                  script_tag.onload = scriptLoadHandler;
                }
                // Try to find the head, otherwise default to the documentElement
                (document.getElementsByTagName('head')[0] || document.documentElement).appendChild(script_tag);
                //console.log('jQuery script tag created');
            } else {
                //console.log('Using existing jQuery from local');
                // The jQuery version on the window is the one we want to use
                //Load OmniWindow
                jQuery = window.jQuery;
                // Call our main function
                main();
                
                
            }

            /******** Called once jQuery has loaded ******/
            function scriptLoadHandler() {
                //console.log('framework loaded with jQuery version ' + window.jQuery.fn.jquery);
                // Restore $ and window.jQuery to their previous values and store the
                // new jQuery in our local jQuery variable
                //Load OmniWindow
                jQuery = window.jQuery.noConflict(true);
                //if (window.jQuery !== undefined) { console.log('After framework load local jQuery version is back to ' + window.jQuery.fn.jquery); }
                // Call our main function
                main();
                
            }
        
        /******** Our main function/JQuery loaded or exists ********/
        function main() {
            
            //alert('main');
            jQuery(document).ready(function($) {
            //alert('doc ready');
            if (typeof console === 'undefined') console = { log: function() { } };
            /*!
 * jQuery-ajaxTransport-XDomainRequest - v1.0.4 - 2015-03-05
 * https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest
 * Copyright (c) 2015 Jason Moon (@JSONMOON)
 * Licensed MIT (/blob/master/LICENSE.txt)
 */

// Only continue if we're on IE8/IE9 with jQuery 1.5+ (contains the ajaxTransport function)

var div = document.createElement("div");
div.innerHTML = "<!--[if lt IE 10]><i></i><![endif]-->";
var isIeLessThan10 = (div.getElementsByTagName("i").length == 1);
if (isIeLessThan10) {
  
var httpRegEx = /^(https?:)?\/\//i;
var getOrPostRegEx = /^get|post$/i;
var sameSchemeRegEx = new RegExp('^(\/\/|' + location.protocol + ')', 'i');

// ajaxTransport exists in jQuery 1.5+
$.ajaxTransport('* text html xml json', function(options, userOptions, jqXHR) {

  // Only continue if the request is: asynchronous, uses GET or POST method, has HTTP or HTTPS protocol, and has the same scheme as the calling page
  if (!options.crossDomain || !options.async || !getOrPostRegEx.test(options.type) || !httpRegEx.test(options.url) || !sameSchemeRegEx.test(options.url)) {
    return;
  }

  var xdr = null;

  return {
    send: function(headers, complete) {
      var postData = '';
      var userType = (userOptions.dataType || '').toLowerCase();

      xdr = new XDomainRequest();
      if (/^\d+$/.test(userOptions.timeout)) {
        xdr.timeout = userOptions.timeout;
      }

      xdr.ontimeout = function() {
        complete(500, 'timeout');
      };

      xdr.onload = function() {
        var allResponseHeaders = 'Content-Length: ' + xdr.responseText.length + '\r\nContent-Type: ' + xdr.contentType;
        var status = {
          code: 200,
          message: 'success'
        };
        var responses = {
          text: xdr.responseText
        };
        try {
          if (userType === 'html' || /text\/html/i.test(xdr.contentType)) {
            responses.html = xdr.responseText;
          } else if (userType === 'json' || (userType !== 'text' && /\/json/i.test(xdr.contentType))) {
            try {
              responses.json = $.parseJSON(xdr.responseText);
            } catch(e) {
              status.code = 500;
              status.message = 'parseerror';
              //throw 'Invalid JSON: ' + xdr.responseText;
            }
          } else if (userType === 'xml' || (userType !== 'text' && /\/xml/i.test(xdr.contentType))) {
            var doc = new ActiveXObject('Microsoft.XMLDOM');
            doc.async = false;
            try {
              doc.loadXML(xdr.responseText);
            } catch(e) {
              doc = undefined;
            }
            if (!doc || !doc.documentElement || doc.getElementsByTagName('parsererror').length) {
              status.code = 500;
              status.message = 'parseerror';
              throw 'Invalid XML: ' + xdr.responseText;
            }
            responses.xml = doc;
          }
        } catch(parseMessage) {
          throw parseMessage;
        } finally {
          complete(status.code, status.message, responses, allResponseHeaders);
        }
      };

      // set an empty handler for 'onprogress' so requests don't get aborted
      xdr.onprogress = function(){};
      xdr.onerror = function() {
        complete(500, 'error', {
          text: xdr.responseText
        });
      };

      if (userOptions.data) {
        postData = ($.type(userOptions.data) === 'string') ? userOptions.data : $.param(userOptions.data);
      }
      xdr.open(options.type, options.url);
      xdr.send(postData);
    },
    abort: function() {
      if (xdr) {
        xdr.abort();
      }
    }
  };
});

}
            // jQuery OmniWindow plugin
// @version:  1.0.0
// @author:   Rudenka Alexander (mur.mailbox@gmail.com)
// @license:  MIT

  $.fn.extend({
    omniWindow: function(options) {
      options = $.extend(true, {
        animationsPriority: {
          show: ['overlay', 'modal'],
          hide: ['modal', 'overlay']
        },
        overlay: {
          selector: '.ow-overlay',
          hideClass: 'ow-closed',
          animations: {
            show: function(subjects, internalCallback) { return internalCallback(subjects); },
            hide: function(subjects, internalCallback) { return internalCallback(subjects); },
            internal: {
              show: function(subjects){ subjects.overlay.removeClass(options.overlay.hideClass); },
              hide: function(subjects){ subjects.overlay.addClass(options.overlay.hideClass); }
            }
          }
        },
        modal:   {
          hideClass: 'ow-closed',
          animations: {
            show: function(subjects, internalCallback) { return internalCallback(subjects); },
            hide: function(subjects, internalCallback) { return internalCallback(subjects); },
            internal: {
              show: function(subjects){ subjects.modal.removeClass(options.modal.hideClass); },
              hide: function(subjects){ subjects.modal.addClass(options.modal.hideClass); }
            }
          },
          internal: {
            stateAttribute: 'ow-active'
          }
        },
        eventsNames: {
          show: 'show.ow',
          hide: 'hide.ow',
          internal: {
            overlayClick:  'click.ow',
            keyboardKeyUp: 'keyup.ow'
          }
        },
        callbacks: {                                                                                  // Callbacks execution chain
          beforeShow:  function(subjects, internalCallback) { return internalCallback(subjects); },   // 1 (stop if returns false)
          positioning: function(subjects, internalCallback) { return internalCallback(subjects); },   // 2
          afterShow:   function(subjects, internalCallback) { return internalCallback(subjects); },   // 3
          beforeHide:  function(subjects, internalCallback) { return internalCallback(subjects); },   // 4 (stop if returns false)
          afterHide:   function(subjects, internalCallback) { return internalCallback(subjects); },   // 5
          internal: {
            beforeShow: function(subjects) {
              if (subjects.modal.data(options.modal.internal.stateAttribute)) {
                return false;
              } else {
                subjects.modal.data(options.modal.internal.stateAttribute, true);
                return true;
              }
            },
            afterShow: function(subjects) {
              $(document).on(options.eventsNames.internal.keyboardKeyUp, function(e) {
                if (e.keyCode === 27) {                                              // if the key pressed is the ESC key
                  subjects.modal.trigger(options.eventsNames.hide);
                  subjects.overlay.css('display', '');  // clear inline styles after jQ animations
                  subjects.modal.css('display', '');
                }
              });

              subjects.overlay.on(options.eventsNames.internal.overlayClick, function(){
                subjects.modal.trigger(options.eventsNames.hide);
                subjects.overlay.css('display', '');  // clear inline styles after jQ animations
                subjects.modal.css('display', '');
              });
            },
            positioning: function(subjects) {
              subjects.modal.css('margin-left', Math.round(subjects.modal.outerWidth(false) / -2));
            },
            beforeHide: function(subjects) {
              if (subjects.modal.data(options.modal.internal.stateAttribute)) {
                subjects.modal.data(options.modal.internal.stateAttribute, false);
                return true;
              } else {
                return false;
              }
            },
            afterHide: function(subjects) {
              subjects.overlay.off(options.eventsNames.internal.overlayClick);
              $(document).off(options.eventsNames.internal.keyboardKeyUp);
              subjects.overlay.css('display', '');  // clear inline styles after jQ animations
              subjects.modal.css('display', '');
            }
          }
        }
      }, options);

      var animate = function(process, subjects, callbackName) {
        var first  = options.animationsPriority[process][0],
            second = options.animationsPriority[process][1];

        options[first].animations[process](subjects, function(subjs) {        // call USER's    FIRST animation (depends on priority)
          options[first].animations.internal[process](subjs);                 // call internal  FIRST animation

          options[second].animations[process](subjects, function(subjs) {     // call USER's    SECOND animation
            options[second].animations.internal[process](subjs);              // call internal  SECOND animation

                                                                              // then we need to call USER's
                                                                              // afterShow of afterHide callback
            options.callbacks[callbackName](subjects, options.callbacks.internal[callbackName]);
          });
        });
      };

      var showModal = function(subjects) {
        if (!options.callbacks.beforeShow(subjects, options.callbacks.internal.beforeShow)) { return; } // cancel showing if beforeShow callback return false

        options.callbacks.positioning(subjects, options.callbacks.internal.positioning);

        animate('show', subjects, 'afterShow');
      };

      var hideModal = function(subjects) {
        if (!options.callbacks.beforeHide(subjects, options.callbacks.internal.beforeHide)) { return; } // cancel hiding if beforeHide callback return false

        animate('hide', subjects, 'afterHide');
      };

      var $overlay = $(options.overlay.selector);

      return this.each(function() {
        var $modal  = $(this);
        var subjects = {modal: $modal, overlay: $overlay};

        $modal.bind(options.eventsNames.show, function(){ showModal(subjects); })
              .bind(options.eventsNames.hide, function(){ hideModal(subjects); });
      });
    }
  });

                
            //console.log('jQuery version ' + $.fn.jquery + ' used in aejs framework scope.');
            //console.log('AE FRAMEWORK INITIALISING.....');
            //default styles
            var css_link = jQuery('<link>', { 
                rel: 'stylesheet', 
                type: 'text/css', 
                href: 'https://sme.theappreciationengine.com//themes/appreciationengine22/auth_framework/jquery.omniwindow.css' 
            });
            css_link.appendTo('head');  
            
            $.support.cors
            //set up cross domain settings for ajax calls (make sure this is not affecting external JQuery code)
            $.ajaxSetup({
                crossDomain: true,
                xhrFields: {
                    withCredentials: true
                }
            });
            
            // -- Private Utility Functions
            
            //Returns the highest (top-most) zIndex in the document
            function topZIndex (selector) {

                return Math.max(0, Math.max.apply(null, $.map(((selector || '*') === '*')? $.makeArray(document.getElementsByTagName('*')) : $(selector),
                    function (v) {
                        return parseFloat($(v).css('z-index')) || null;
                    }
                )));
            }

            //http://www.jquerybyexample.net/2012/06/get-url-parameters-using-jquery.html
            function GetURLParameter(sParam) {

                var sPageURL = window.location.search.substring(1);
                var sURLVariables = sPageURL.split('&');

                for (var i = 0; i < sURLVariables.length; i++) {

                    var sParameterName = sURLVariables[i].split('=');
                    if (sParameterName[0] == sParam) {
                        return sParameterName[1];
                    }
                }
            }
            
            function addParam(url, param, value) {
               var a = document.createElement('a'), regex = /[?&]([^=]+)=([^&]*)/g;
               var match, str = []; a.href = url; value=value||'';
               while (match = regex.exec(a.search))
                   if (encodeURIComponent(param) != match[1]) str.push(match[1] + '=' + match[2]);
               str.push(encodeURIComponent(param) + '=' + encodeURIComponent(value));
               a.search = (a.search.substring(0,1) == '?' ? '' : '?') + str.join('&');
               return a.href;
            }
            
            function setLinkState(active) {
            
                //set any services attached as active

            }
            
            function nextSteps(auth_state) {

                //console.log('NEXT STEPS');
                //console.log(auth_state);
                
                //save user against local aeJS
                aeJS.user = typeof auth_state.user !== 'undefined' ? auth_state.user : {}; 
                
                var login_type = auth_state['registration'] === true ? 'registration' : 'login';
                var missing = false;
                
                switch (auth_state.state) {
                
                    case 'close' : // closes modal - broadcast from iframe in modal
                    
                        //avoid double login fire
                        aeJS.events.onWindow.removeHandler(aeJS.self_destruct);
                        aeJS.modal.window.trigger('hide');
                        
                        //trigger local user refresh
                        if (typeof auth_state.user !== 'undefined' && !$.isEmptyObject(auth_state.user)) {
                            if (typeof aeJS.step_triggered !== 'undefined') {
                                if (aeJS.step_triggered == 'verify-email') aeJS.events.onEmailVerify.callHandler('sent', {'EmailAddress':aeJS.user.data.Email });
                            } else {
                                if (isValidLogin()) aeJS.events.onLogin.callHandler(auth_state.user,login_type); 
                            }
                        }
                        
                    break;
                    
                    case 'register' :

                        var done = true;
                        aeJS.loggedIn = false;
                        
                        //extra fields?
                        if (aeJS.settings['extra_fields_screen'] === 'after') {
                            
                            //any required fields missing
                            if (login_type === 'registration') {
                                missing = extraFields(aeJS.user);
                                if (missing === false) missing = {};
                                
                                //allow user to modify username on registration for email
                                if (auth_state.service === 'email' && typeof aeJS.settings['extra_fields'] !== 'undefined' && typeof aeJS.settings['extra_fields']['username'] !== 'undefined') {
                                    $.extend(missing, { 'username' : { required: true } }); 
                                }
                                //coppa case (unset birthdate on user object to force check)
                                
                                if ($.isEmptyObject(missing)) missing = false; //set back to false if still empty
                                
                            } else { 
                                missing = extraFields(aeJS.user,true);
                            }
                            //console.log(missing);
                            
                            if (missing !== false) {

                                done = false;
                                
                                aeJS.settings.extra_fields = missing;
                                
                                //add login handler on window close (just once)
                                aeJS.self_destruct = function(e) {
                                    if (e.type === 'modal' && e.state === 'closed') {
                                        if (isValidLogin()) aeJS.events.onLogin.callHandler(auth_state.user,login_type);
                                        aeJS.events.onWindow.removeHandler(aeJS.self_destruct);
                                    }
                                }
                                aeJS.events.onWindow.addHandler(aeJS.self_destruct);
                                
                                //set-up flow and params
                                aeJS.flow.step = 'required-fields';
                                aeJS.flow.auth_url = auth_state.auth_url;
                                aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                aeJS.events.onFlow.callHandler(aeJS.flow);
                                break;
                            }
                            
                        } 
                        
                        //verify email?
                        if (JSON.parse(aeJS.settings['verify_email']) === true && !verifiedEmail()) {

                            if (typeof auth_state.verified === 'undefined' || JSON.parse(auth_state.verified) !== true) {
                                //set-up flow and params
                                done = false;
                                aeJS.flow.step = 'verify-email';
                                aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                aeJS.events.onFlow.callHandler(aeJS.flow);
                                break;
                            }
                        } 
                        
                        //DONE
                        if (done === true) {
                            auth_state.state = 'close';
                            if (aeJS.isEmbed) { // we are in a modal or iframe 
                                if (self != top) {
                                    if (isValidLogin()) {
                                        aeJS.events.onLogin.callHandler(auth_state.user,login_type);
                                    } else { //something missing
                                        var reason = isValidLogin(true);
                                        done = false;
                                        aeJS.flow.step = reason;
                                        aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                        //settings have prevented default validation flows, but specified requirements missing - notify
                                        aeJS.events.onFlow.callHandler(aeJS.flow,false); 
                                        break;
                                    }
                                } else { 
                                    parent.postMessage(JSON.stringify(auth_state),auth_state.auth_referer); 
                                }
                            } else { //just trigger local user refresh
                            
                                aeJS.modal.window.trigger('hide'); //hide window if exists
                                if (isValidLogin()) {
                                    aeJS.events.onLogin.callHandler(auth_state.user,login_type);
                                } else { //something missing
                                    var reason = isValidLogin(true);
                                    done = false;
                                    aeJS.flow.step = reason;
                                    aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                    //settings have prevented default validation flows, but specified requirements missing - notify
                                    aeJS.events.onFlow.callHandler(aeJS.flow,false); 
                                    break;
                                }
                                
                            }
                        }
                         
                         
                    break;     
                    case 'update' :   
                        
                        if (aeJS.settings['verify_email'] === true && !verifiedEmail()) {

                            //set-up flow and params
                            aeJS.flow.step = 'verify-email';
                            aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                            aeJS.events.onFlow.callHandler(aeJS.flow);
                            
                         } else { //DONE
                                
                                auth_state.state = 'close';
                                if (aeJS.isEmbed) { // we are in a modal so tell iframe parent to close me
                                
                                    if (self != top && isValidLogin()) aeJS.events.onLogin.callHandler(auth_state.user,login_type); //iframe
                                    else parent.postMessage(JSON.stringify(auth_state),auth_state.auth_referer);
                                    
                                } else { //just trigger local user refresh
                                    aeJS.events.onWindow.removeHandler(aeJS.self_destruct); //avoid double fire
                                    aeJS.modal.window.trigger('hide');
                                    aeJS.events.onLogin.callHandler(auth_state.user,login_type);  
                                }
                                
                         }

                    break;
                    case 'token_login' :   
                        aeJS.loggedIn = false;
                        if (isValidLogin()) { 
                             aeJS.events.onLogin.callHandler(auth_state.user,'login');
                        } else {

                            // does the current user meet all the setting needs to be logged in.
                            if (isValidSSO()) {
                                //console.log('try SSO?');
                                var sso = SSO()
                                //console.log(sso);
                                if (sso !== false) {

                                    //update memberservice with domain
                                    $.post('https://sme.theappreciationengine.com/framework-v1.3/sso/496', {service_id : sso, domain : 'www.paulsimon.com' }, function( auth_state ) {
                                          //trigger login event
                                          //console.log(auth_state);
                                          if (typeof auth_state.user !== 'undefined') aeJS.user = auth_state.user; //reset user
                                          if (isValidLogin()) aeJS.events.onLogin.callHandler(auth_state.user,'registration',true);
                                    });

                                }
                            }
                        }

                    break;
                    case 'complete' :        
                    case 'login' :    
                        auth_state.state = 'close';
                        aeJS.loggedIn = false;
                        if (aeJS.isEmbed) { // we are in a modal so tell iframe parent to close me
                            if (self != top) {
                                if (isValidLogin()) {
                                    aeJS.events.onLogin.callHandler(auth_state.user,login_type);
                                } else { //something missing
                                    var reason = isValidLogin(true);
                                    done = false;
                                    aeJS.flow.step = reason;
                                    aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                    //settings have prevented default validation flows, but specified requirements missing - notify
                                    aeJS.events.onFlow.callHandler(aeJS.flow,false); 
                                    break;
                                }
                            } else { 
                                parent.postMessage(JSON.stringify(auth_state),auth_state.auth_referer); 
                            }
                        } else { //just trigger local user refresh
                            aeJS.modal.window.trigger('hide'); //hide window if exists
                            if (isValidLogin()) {
                                aeJS.events.onLogin.callHandler(auth_state.user,login_type);
                            } else { //something missing
                                var reason = isValidLogin(true);
                                done = false;
                                aeJS.flow.step = reason;
                                aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                //settings have prevented default validation flows, but specified requirements missing - notify
                                aeJS.events.onFlow.callHandler(aeJS.flow,false); 
                                break;
                            }  
                        }

                    break;
                    
                    case 'auth' :    
                        auth_state.state = 'close';
                        if (aeJS.isEmbed) { // we are in a modal so tell iframe parent to close me
                            if (self != top && isValidLogin()) aeJS.events.onLogin.callHandler(auth_state.user,login_type); //iframe
                            else parent.postMessage(JSON.stringify(auth_state),auth_state.auth_referer);
                        } else { //just trigger local user refresh
                            aeJS.modal.window.trigger('hide');
                            aeJS.events.onLogin.callHandler(auth_state.user,'auth');  
                        }

                    break;
                    
                    case 'passthrough' :
                    
                        //console.log(auth_state.event);
                        if (typeof auth_state.event !== 'undefined') {
                            //set-up flow and params
                            aeJS.flow = auth_state.event;
                            aeJS.events.onFlow.callHandler(aeJS.flow,false); //call handler, ignore default handler...
                        }
                                
                    break;
                    
                    case 'error' :
                    
                        //set-up flow and params
                        aeJS.flow.step = 'error';
                        if (typeof auth_state.error.code != 'undefined') aeJS.flow.code = auth_state.error.code;
                        if (typeof auth_state.error.message != 'undefined') aeJS.flow.error = auth_state.error.message;
                        aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                        aeJS.events.onFlow.callHandler(aeJS.flow);
                                
                    break;
                }
                
            }
            
            // -- Message listener for iframe/popup
            var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
            var eventer = window[eventMethod];
            var messageEvent = eventMethod == 'attachEvent' ? 'onmessage' : 'message';
            var messageHandled = false;
            
            // Listen to message from child window
            eventer(messageEvent,function(e) {
              
              //console.log(e);  
              //console.log('EVENT');
              if (e.origin !== 'https://sme.theappreciationengine.com') {
                  return;
              } else { //expects json packet (TODO: handle different json packets, depending on state)
              
                //console.log('window received message!:  ',e.data);
                var auth_state = JSON.parse(e.data);
                messageHandled = true;
                nextSteps(auth_state);
              
              }
              
            },false);
            
            // --- create the root namespace and making sure we're not overwriting it
            var aeJS = aeJS || {};
            var aeJSPrepped = false;
            
            // create a general purpose namespace method
            // this will allow us to create namespace a bit easier
            var createNS = function (namespace) {
                var nsparts = namespace.split('.');
                var parent = aeJS;

                // we want to be able to include or exclude the root namespace 
                // So we strip it if it's in the namespace
                if (nsparts[0] === 'aeJS') {
                    nsparts = nsparts.slice(1);
                }

                // loop through the parts and create 
                // a nested namespace if necessary
                for (var i = 0; i < nsparts.length; i++) {
                    var partname = nsparts[i];
                    // check if the current parent already has 
                    // the namespace declared, if not create it
                    if (typeof parent[partname] === 'undefined') {
                        parent[partname] = {};
                    }
                    // get a reference to the deepest element 
                    // in the hierarchy so far
                    parent = parent[partname];
                }
                // the parent is now completely constructed 
                // with empty namespaces and can be used.
                return parent;
            };

            // --- Create the namespace for settings and initialize
            createNS('aeJS.settings');
            var default_settings = {
                'mobile_detect' : true,
                'close_button' : false,
                'hide_email_form' : false,
                'extra_fields' : {},
                'extra_fields_screen': 'disabled', //before, after, disabled
                'display_error_message': true,
                'default_flow_handlers': true,
                'auth_window' : false,
                'services' : null,
                'scopes' : null,
                'sso' : 'application',
                'language' : 'en_US',
                'extra_info' : {},
                'flow_css' : null,
                'verify_email' : false,
                'verify_email_for_login' : false,
                'code' : null,
                'no_email' : false,
                'social_first' : false,
                'refresh_demographics' : true,
                'minimum_age' : null,
                'date_format' : 'DD-MM-YYYY',
                'profile_link' : null,
                'partner_code' : null,
                'partner_id' : null,
                'help_link' : null,
                'flow_text' : {
                    error_header : 'Sorry, there seems to be a problem',
                    login_header : 'Sign In',
                    login_button: 'Sign In',
                    login_with_button: 'Sign in with',
                    register_header : 'Sign Up',
                    register_button: 'Sign Up',
                    register_with_button: 'Sign up with',
                    add_info_header : 'Additional Information',
                    add_info_button : 'Submit',
                    reset_pw_header : 'Reset Password',
                    reset_pw_sent : 'A verification email will be sent to',
                    reset_pw_instructions : 'Please click the link in the email to confirm your address and reset your password.',
                    reset_pw_button : 'Verify Email',
                    reset_pw_confirm_header : 'Reset Password - Confirm',
                    reset_pw_confirm_button : 'Confirm',
                    reset_pw_confirm_instructions : 'Please enter a new password',
                    reset_pw_done_header : 'Reset Password - Done!',
                    reset_pw_done_message : 'Your password has been reset.',
                    reset_pw_done_button : 'OK',
                    verify_email_header : 'Verify Email',
                    verify_email_sent : 'A verification email will be sent to',
                    verify_email_instructions : 'Please click the link in the email to confirm your address and continue.',
                    verify_email_retry_button : 'Retry',
                    verify_email_success_header : 'Success.',
                    verify_email_success_message : 'Your email was successfully verified.',
                    verify_email_success_button : 'OK',
                    verify_email_error_header : 'Sorry.',
                    verify_email_error_message : 'That is not a valid activation url, or the url has expired. Please double check your email, or trigger a new activation email.',
                    forgot_password_link : 'forgot password?',
                    recover_password_link : 'Recover Password',
                    optins_title : 'Subscribe to these mailing lists',
                    have_account_link : 'Have an account?',
                    need_help_link : 'need help?',
                    create_account_link : 'create an account'
                 },
                 email_format : {
                    show_header : true,
                    show_footer : true,
                    reset_pw_email_subject : 'Password Reset For Sony Music US - Legacy',
                    reset_pw_email_message : 'Click the following link to verify your email and reset your password',
                    reset_pw_email_link : 'Reset Password',
                    verify_email_subject : 'Please verify your email address for Sony Music US - Legacy',
                    verify_email_message : 'Click the following link to verify your email and continue with your registration',
                    verify_email_link : 'Verify Email',
                 }
            };
            
            // --- Create the namespace for user data
            createNS('aeJS.user');
            createNS('aeJS.flow');
            createNS('aeJS.isEmbed');
            aeJS.loggedIn = false;
            aeJS.isEmbed = window != window.parent; 
            

            // --- Create the namespace for events and initialize
            createNS('aeJS.events');
            aeJS.events.onFlow = {name: 'onFlow'}; aeJS.events.onWindow = {name: 'onWindow'}; aeJS.events.onLogin = {name: 'onLogin'}; aeJS.events.onLogout = {name: 'onLogout'};
            aeJS.events.onUser = {name: 'onUser'}; aeJS.events.onMobileDetect = {name: 'onMobileDetect'}; aeJS.events.onServiceRemoved = {name: 'onServiceRemoved'}; aeJS.events.onLoaded = {name: 'onLoaded'};
            aeJS.events.onEmailVerify = {name: 'onEmailVerify'}; aeJS.events.onPasswordReset = {name: 'onPasswordReset'}; aeJS.events.onActivitySent = {name: 'onActivitySent'}; aeJS.events.onOptin = {name: 'onOptin'};
            
            // --- Initialize Event Object
            var aeEvent = function() {
                
                var listeners = [];
                
                this.getListeners = function() {
                    return listeners; 
                };
                
                this.addHandler = function(callback) {
                    listeners.push(callback);  
                };

                this.removeHandler = function(callback) {
                    
                    for (var i = 0; i < listeners.length; i++) {
                        if (listeners[i] === callback) {
                            listeners.splice(i, 1);
                        }
                    }
                };
                
                this.callHandler = function() {
                    
                    var len = listeners.length;
                    var i;

                    //abort double logins
                    if (this.name == 'onLogin' && aeJS.loggedIn) return; 
                    
                    for( i = 0; i < len; ++i ) {
                        listeners[i].apply( null, arguments );
                    }    
                };
            };
            
            // --- Initialize Events Instances
            aeEvent.call(aeJS.events.onFlow);
            aeEvent.call(aeJS.events.onWindow);
            aeEvent.call(aeJS.events.onLogin);
            aeEvent.call(aeJS.events.onLogout);
            aeEvent.call(aeJS.events.onMobileDetect);
            aeEvent.call(aeJS.events.onUser);
            aeEvent.call(aeJS.events.onServiceRemoved);
            aeEvent.call(aeJS.events.onLoaded);
            aeEvent.call(aeJS.events.onEmailVerify);
            aeEvent.call(aeJS.events.onActivitySent);
            aeEvent.call(aeJS.events.onOptin);
            aeEvent.call(aeJS.events.onPasswordReset);
            
            $.extend(aeJS.events.onFlow, {
            
                clickHandler: function(event) {
                    
                    if (typeof event.preventDefault !== 'undefined') event.preventDefault();
                    
                    //INITIALIZE HERE WE ARE BASED ON SETTINGS (i.e login, required fields, merge, etc)
                    if (aeJSPrepped) {
                    
                        aeJS.flow = $.extend( {}, event.data );

                        // --- Click attribute overrides based on settings 
                        if (!$(event.target).data('aeReturn') && typeof aeJS.settings['return_url'] !== 'undefined')
                        aeJS.flow.return = aeJS.settings['return_url'];
                        //console.log(aeJS.flow);

                        if (aeJS.flow.step != 'logout' && aeJS.flow.step != 'remove') { //ignore if logging out or removing

                            //Needed to overcome default security settings for Safari
                            if (aeJS.flow.step == 'login' || aeJS.flow.step == 'register') {
                                if ((JSON.parse(aeJS.settings['auth_window']) === true) && (!parseInt() || !aeJS.settings['mobile_detect'])) {
                                    safariSessionCheck();
                                }
                            }
                            //toggle back
                            if (typeof aeJS.settings['extra_fields_screen_original'] !== 'undefined') {
                                    aeJS.settings['extra_fields_screen'] = aeJS.settings['extra_fields_screen_original'];
                            }

                            if (aeJS.flow.step == 'login' || aeJS.flow.step == 'login-direct') {
                                //save state in case we toggle to register, etc (only save once)
                                if (typeof aeJS.settings['extra_fields_screen_original'] === 'undefined') {
                                    aeJS.settings = $.extend( aeJS.settings, {'extra_fields_screen_original' : aeJS.settings['extra_fields_screen'] } );
                                }
                                aeJS.settings['extra_fields_screen'] = 'disabled'; //disable required field on login (for now)
                            } 

                            //skip straight to auth
                            if (aeJS.flow.step == 'login-direct' || aeJS.flow.step == 'register-direct') {
                                aeJS.flow.step = 'authenticate';
                                if (aeJS.settings['extra_fields_screen'] == 'before') aeJS.flow.step = 'required-fields';
                            }
                        }

                        //console.log(aeJS);
                        aeJS.events.onFlow.callHandler(aeJS.flow);
                        
                    }
                   
                }
              
            });
            
            //------- Private AEJS functions
            var safariSessionCheck = function() {
            
                var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1;
                if (isSafari) {
                    openAuthWindow({
                        path: 'https://sme.theappreciationengine.com/framework-v1.3/session_start/496',
                        windowOptions: 'location=0,status=0,width=5,height=5',
                        callback: function(){ window.focus(); }
                    });
                }
            }
            
            var safariRedirect = function() {
            
                var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1;
                if (isSafari) {
                     if (typeof GetURLParameter('safari_redirect') == 'undefined') {
                        current_url = location.href;
                        location.href = 'https://sme.theappreciationengine.com/framework-v1.3/session_start/496?safari_redirect=true&uri='+encodeURIComponent(current_url);
                     }
                }
            }
            
            var getAuthState = function(memberid) {
            
                //JSONP request
                $.ajax({
                    url: 'https://sme.theappreciationengine.com//framework-v1.3/auth_state/496',
                    dataType: 'JSONP',
                    type: 'GET',
                    data: {'MemberID':memberid},
                    success: function (auth_state) {
                        //console.log(JSON.stringify(auth_state));
                        //refresh user data etc - redirect if return is not this url?
                        var login_type = auth_state['registration'] === true ? 'registration' : 'login';
                        aeJS.user = typeof auth_state.user !== 'undefined' ? auth_state.user : {}; 
                        if (isValidLogin()) aeJS.events.onLogin.callHandler(aeJS.user,login_type);
                    }
                });
            }
                
            var openAuthWindow = function(options) {
            
                messageHandled = false; //reset message handler flag (used to avoid double nextSteps call on window close)
                options.windowName = options.windowName ||  'ae_auth_window'; // should not include space for IE
                options.windowOptions = options.windowOptions || 'location=0,status=0,width=600,height=600';
                options.callback = options.callback || function(){ window.location.reload(); };
                options.windowOptions = options.windowOptions + ',scrollbars=1'
                
                //add flag to indicate auth flow is through auth window, rather than re-direct
                options.path = addParam(options.path, 'auth_method', 'window');
                
                //in case of re-opened window (eg swapping social networks)
                if (typeof aeJS.authInterval !== 'undefined') window.clearInterval(aeJS.authInterval);
                
                aeJS.auth_window = window.open(options.path, options.windowName, options.windowOptions);
                //console.log(aeJS.auth_window);
                if (window.focus && typeof aeJS.auth_window !== 'undefined') {
                    aeJS.auth_window.focus();
                }
                
                aeJS.authInterval = window.setInterval(function(){
                    
                    if (aeJS.auth_window && aeJS.auth_window.closed) {
                        window.clearInterval(aeJS.authInterval);
                        options.callback({'type':'popup','state':'closed','service' : aeJS.flow.service});
                    }
                }, 1000);
                
                options.callback({'type':'popup','state':'opened','service' : aeJS.flow.service});
                return false;
            };
  
            // if auth_window == true, or flow is currently inside iframe => auth dialog popup
            // else direct link
            var authenticate = function (auth_url) {
                
                auth_url = addParam(auth_url, 'referer', 'https://www.paulsimon.com/news/hugh-masekela-1939-2018/');
                auth_url = addParam(auth_url, 'partner_id', aeJS.settings['partner_id']); //required for safari
                auth_url = addParam(auth_url, 'partner_code', aeJS.settings['partner_code']); //required for safari
                
                //add optins
                var optins = '';
                $('input[data-ae-optin],input[data-ae-optin-brandid],input[data-ae-optin-segmentid]').each(function(index) {
                    var brandid = $(this).data('aeOptinBrandid');
                    var segmentid = $(this).data('aeOptinSegmentid');
                    var label = $(this).data('aeOptin');
                    
                    if ($(this).prop('checked')) {
                        optins = optins + brandid + ':' + segmentid + ':' + label + ',';
                    }
                    auth_url = addParam(auth_url, 'optins', optins);
                });
                
                //console.log(auth_url); return;
                //Also do we need a device check here?
                //i.e mobile and tablet should just re-direct
                if ((JSON.parse(aeJS.settings['auth_window']) === true) && (!parseInt() || !aeJS.settings['mobile_detect'])) {
                
                    var popupWidth=600;
                    var popupHeight=450;
                    var xPosition=($(window).width()-popupWidth)/2;
                    var yPosition=($(window).height()-popupHeight)/2;
    
                    openAuthWindow({
                        path: auth_url,
                        windowOptions: 'width='+popupWidth+',height='+popupHeight+',left='+xPosition+',top='+yPosition,
                        callback: aeJS.events.onWindow.callHandler
                    });
                     
                    
                } else {
                
                    //must operate on top level window
                    if (aeJS.isEmbed) {
                        auth_url = addParam(auth_url, 'referer', 'https://www.paulsimon.com/news/hugh-masekela-1939-2018/');
                        auth_url = addParam(auth_url, 'return', document.referrer);
                        window.top.location.href = auth_url;
                    } else {
                        location.href = auth_url;
                    }
                }
                
            };
            
            //Checks that all minimum settings are enabled to allow email verification
            //We must have at least email as extra field and extra_screen enabled otherwise add
            var checkVerifyEmail = function () {
            
                if (aeJS.settings['verify_email'] === true) {
                    
                    var noUserEmail = false;
                    if (typeof aeJS.user.data === 'undefined' || aeJS.user.data.Email === null) noUserEmail = true;
                    
                    //need to add email to list of fields
                    if (noUserEmail && typeof aeJS.settings['extra_fields']['email'] === 'undefined') {
                        $.extend(aeJS.settings['extra_fields'], {
                        'email' : { required: true }
                        });
                    }

                    //need extra screen
                    if (aeJS.settings['extra_fields_screen'] === 'disabled') {
                        aeJS.settings['extra_fields_screen'] = 'after'
                    }
                
                }
                
            };
            
            // checks current user against indicated required fields
            // false if all required fields exist, otherwise returns missing fields
            var extraFields = function (user,requiredOnly) {
            
                var is_missing = false;
                var missing = {};
                
                if (typeof requiredOnly === 'undefined') requiredOnly = false;
                
                if (typeof aeJS.settings['extra_fields'] != 'undefined') {
                    if (typeof user.data != 'undefined') {
                    
                        // due to difference in case for settings and user data
                        // Would be nice to remove later..
                        var key, keys = Object.keys(user.data);
                        var n = keys.length;
                        var user_data_lc = {}
                        while (n--) {
                          key = keys[n];
                          user_data_lc[key.toLowerCase()] = user.data[key];
                        }
                        
                        //console.log(user_data_lc);
                        $.each(aeJS.settings['extra_fields'], function( field, properties ) {
                          
                          var extra_field = aeJS.settings['extra_fields'][field];
                          var required = (typeof extra_field.required !== 'undefined' && JSON.parse(extra_field.required) === true);
                          //console.log(field);
                          //console.log(requiredOnly);
                          //console.log(required);
                          //console.log(user_data_lc[field]);
                          if (!requiredOnly || (required && requiredOnly)) {
                              if (typeof user_data_lc[field] === 'undefined' || user_data_lc[field] === 'Unknown' || (!!user_data_lc[field]) === false) {
                                  is_missing = true;
                                  missing[field] = properties;
                                  //console.log(missing)
                              }
                          }
                          
                        });
                    } else {
                        return aeJS.settings['extra_fields'];
                    }
                }
                
                if (is_missing) return missing;
                return is_missing;
                
            };
            
            // Merges defaults and user settings
            var initSettings = function () {
                
                var temp_settings = $.extend( true, default_settings, aeJS.settings );
                aeJS.settings = temp_settings;
                
                //move password to prevent bogus requirements (should just move this field somewhere...)
                if (typeof aeJS.settings['extra_fields']['password'] !== 'undefined') {
                    aeJS.settings['password_format'] = aeJS.settings['extra_fields']['password'];
                    delete aeJS.settings['extra_fields']['password'];
                }
                
                //console.log(aeJS.settings);
            };
            
            // Does user have a verified email
            var verifiedEmail = function () {
               
               var verified = false;
               if (typeof aeJS.user.data != 'undefined') {
                    if (typeof aeJS.user.data.VerifiedEmail !== 'undefined' && aeJS.user.data.VerifiedEmail !== null) verified = true;
               }
               //console.log(verified);
               return verified;
               
            };
            
            // Does user have a verified email
            var validService = function () {
               
               var valid_service = false;
               
               if (typeof aeJS.user.services != 'undefined') {
                   $.each(aeJS.user.services, function( index, service ) {

                       //have they signed up with email before?
                       if (service['Service'] == 'email') {
                         //console.log(aeJS.settings['no_email']);
                         if (typeof aeJS.settings['no_email'] === 'undefined' || JSON.parse(aeJS.settings['no_email']) === false) {
                             if($.inArray('www.paulsimon.com',service['Domains']) !== -1 || $.inArray('www.paulsimon.com'.replace('www.',''),service['Domains']) !== -1) { //user has visited before
                                    //do we need to check sso scope here?
                                    //console.log('HAS VALID SERVICE!!!');
                                    valid_service = true;
                             }
                         }
                       }

                       //others?
                       if (typeof aeJS.settings['services'] === 'undefined' || aeJS.settings['services'] === null || aeJS.settings['services'].toLowerCase().indexOf(service['Service']) !== -1) {
                           
                            if($.inArray('www.paulsimon.com',service['Domains']) !== -1 || $.inArray('www.paulsimon.com'.replace('www.',''),service['Domains']) !== -1) { //user has visited before
                                //do we need to check sso scope here?
                                //console.log('HAS VALID SERVICE!!!');
                                valid_service = true;
                            }
                       }

                   });
               }
               
               //console.log(valid_service);
               return valid_service;
               
            };
            
            // Meet criteria for single sign-on
            var SSO = function () {
               
               var sso = false; //true means fire a login event...
               var valid_services = [2455,2766,2767,2768,2769,2770,2771,2944,3372];
                   
               if (typeof aeJS.user.services != 'undefined') {
                    $.each(aeJS.user.services, function( index, service ) {
                    
                        if (sso !== false) return sso; //break free
                        
                        //console.log(service);
                        if($.inArray('www.paulsimon.com',service['Domains']) !== -1 || $.inArray('www.paulsimon.com'.replace('www.',''),service['Domains']) !== -1) { //user has visited before
                            
                            //logged in here before do not trigger SSO
                            //console.log ('Domain match!');
                            //console.log('www.paulsimon.com');
                            return sso; //break free
                            
                        } else { //user has not visited
                        
                            //console.log ('NO Domain match!');
                            //console.log (aeJS.settings['sso'] !== 'application');
                            if (typeof aeJS.settings['sso'] === 'undefined' || aeJS.settings['sso'] == 'application') {
                            
                                //console.log('app sso');
                                //console.log(valid_services);
                                //console.log($.inArray(JSON.parse(service['ServiceID']),valid_services));
                                
                                //signed up with email?
                                if (service['Service'] == 'email') {
                                     //console.log(service);
                                     if (typeof aeJS.settings['no_email'] === 'undefined' || JSON.parse(aeJS.settings['no_email']) === false) {
                                         sso = service['ID'];
                                         return;
                                     }
                                }
                   
                                //others?
                                if($.inArray(JSON.parse(service['ServiceID']),valid_services) !== -1) {
                                    //console.log('has app service');
                                    //console.log(service['Service']);
                                    if (typeof aeJS.settings['services'] === 'undefined' || aeJS.settings['services'] === null || aeJS.settings['services'].indexOf(service['Service']) !== -1) {
                                        //console.log('and service enabled here');
                                        sso = service['ID'];
                                        return;
                                    }
                                }
                            } 
                            //else local, need to have logged in before, do not trigger SSO
                        }
           
                    });
               }
          
               return sso;
               
            };
            
            // does the current user meet all the setting needs to be logged in.
            var isValidLogin = function (returnStep) {
                
                if (typeof returnStep === 'undefined') returnStep = false;
                var valid = true;
                
                //must verify email in order to login
                //console.log(aeJS.settings['verify_email_for_login']);
                if (aeJS.settings['verify_email_for_login'] === true) {
                    if (!verifiedEmail()) { valid = 'verify-email' }
                }
                
                //has all 'required' fields
                missing = extraFields(aeJS.user,true);
                if (missing !== false) { valid = 'required-fields'; }
                
                if (!validService()) { valid = 'invalid-service'; }
 
                //console.log('is_valid'); 
                //console.log(valid);
                //alert('valid login!!!!!');
                if (returnStep) return valid; //return reason
                return (valid === true); //true or false
                
            };
           
            // similar to isValidLogin, but ignores valid service check
            // used to avoid calling SSO if use would not meet requirments of site anyway.
            var isValidSSO = function () {
                
                var valid = true;
                
                //must verify email in order to login
                if (aeJS.settings['verify_email_for_login'] === true) {
                    if (!verifiedEmail()) { valid = false; }
                }
                
                //has all 'required' fields
                missing = extraFields(aeJS.user,true);
                if (missing !== false) { valid = false; }
                                
                //console.log('valid sso!!!!!'); 
                //console.log(valid);
                return valid;
                
            };
            
            var absolutePath = function(href) {
                var link = document.createElement('a');
                link.href = href;
                var pathname = (link.pathname.charAt(0) == '/') ? link.pathname : '/' + link.pathname; //deal with IE
                return (link.protocol+'//'+link.host+pathname+link.search+link.hash);
            }

            //------- Public AEJS functions
            createNS('aeJS.trigger');
            
            //manual login
            aeJS.trigger.login = function (token) {
            
                authUrl = 'https://sme.theappreciationengine.com//framework-v1.3/auth_state/496/'+token;
                authUrl = addParam(authUrl, 'ae_token_login', 1);
                
                $.ajax({
                    url: authUrl,
                    dataType: 'JSONP',
                    type: 'GET',
                    success: function (auth_state) {

                        //needs to be parsed or already object
                        try {
                            state = JSON.parse(auth_state)
                        } catch (e) {
                            state = auth_state
                        }

                        nextSteps(state);

                    }
                });
                        
            } 
            
            //manual logout function, clears via ajax
            //developer will need to handle onLogout event
            aeJS.trigger.logout = function () {
            
                aeJSPrepped = false;
                aeJS.loggedIn = false;
                
                var url = 'https://sme.theappreciationengine.com/brand/sony-music-us-legacy/logout';
                    
                //logout user via ajax and clear local user
                url = addParam(url, 'ae_appid', '91');
                url = addParam(url, 'auth_method', 'window');
                $.post( url, aeJS.settings, function( data ) {
                    
                    flowURL = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/prep';
                    var cache_url = addParam(flowURL, 'pre_cache', 1);
                    cache_url = addParam(cache_url, 'from', 'c80ebdfa77c6228d0e3b4df1fa520b8c');
                    cache_url = addParam(cache_url, 'segment', '');   
                    if (!aeJS.isEmbed) {
                        cache_url = addParam(cache_url,'referring_url',top.document.referrer);
                    }    
                    
                    
                    $.post( cache_url, aeJS.settings, function( data ) {
                        aeJSPrepped = true;
                        aeJS.events.onLogout.callHandler({});//clear local user
                    });
                    
                });
                        
            } 
            
            aeJS.trigger.remove = function (service,returnURL) {
            
                var removeURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/3372"};
                var step = 'remove';
                
                if (typeof(returnURL)=='undefined') returnURL = location.href
                
                if (typeof(service) !== 'undefined') {
                    
                    url = removeURLs[service];
                    
                    var event = jQuery.Event( 'click' );
                    $.extend( event, {target : {}});
                    $(event.target).attr('data-ae-return',returnURL);
                    $.extend(true, event, {data : {'step' : step, 'auth_url' : url, 'return' : returnURL }} );
                
                    //console.log(event);
                    aeJS.events.onFlow.clickHandler(event);
                    
                }
                        
            } 
            
            //manual authenticate function
            aeJS.trigger.authenticate = function (service,type,returnURL) {
                
                var loginURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/3372"};
                var registerURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/3372"};
                var authURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/3372"};    
                var step = '';
                var url = '';

                if (typeof(returnURL)=='undefined') returnURL = location.href
                if (typeof(type)==='undefined') type = 'register';
                
                if (type == 'login') {
                    step = 'login-direct';
                    url = loginURLs[service];
                } else if (type == 'register') {
                    step = 'register-direct';
                    url = registerURLs[service];
                } else if (type == 'auth') {
                    step = 'authenticate';
                    url = authURLs[service];
                }    
                url = addParam(url, 'segment', '');
                    
                var event = jQuery.Event( 'click' );
                $.extend( event, {target : {}});
                $(event.target).attr('data-ae-return',returnURL);
                $.extend(true, event, {data : {'step' : step, 'auth_url' : url, 'return' : returnURL, 'service' : service }} );
                
                aeJS.events.onFlow.clickHandler(event);
                
            } 
            
            //trigger full screen registration flow
            aeJS.trigger.flow = function (type, returnURL) {
                
                if (typeof type === 'undefined') type='register';
                
                var url = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/'+type;
                var step = type;
                var returnURL = (typeof returnURL === 'undefined') ? window.location.href : returnURL;
                
                var event = jQuery.Event( 'click' );
                $.extend( event, {target : {}});
                $(event.target).attr('data-ae-return',returnURL);
                $.extend(true, event, {data : {'step' : step, 'auth_url' : url, 'return' : returnURL }} );
                
                //console.log(event);
                aeJS.events.onFlow.clickHandler(event);
                
            } 
            
            //trigger email verification
            aeJS.trigger.verify_email = function (returnURL) {
                aeJS.trigger.send_verify_email(returnURL,'','','verify-email');
            } 

            //trigger email verification
            aeJS.trigger.verify_reset_password = function (returnURL) {
                aeJS.trigger.send_verify_email(returnURL,'','','reset-password');
            } 
            
            //trigger email verification
            aeJS.trigger.send_verify_email = function (returnURL,email,message,step) {
                
                //set-up flow and params
                if (typeof step === 'undefined') step = 'send-email'
                if (email !== '') aeJS.settings.email = email;
                if (message !== '') aeJS.settings.message = message;
                
                aeJS.flow.step = step;
                if (typeof returnURL === 'undefined') {
                    if (typeof aeJS.settings['return_url'] !== 'undefined') returnURL = aeJS.settings['return_url'];
                    else returnURL = location.href;
                }
                aeJS.flow.return = returnURL;
                
                if (step === 'send-email') { //CUSTOM AJAX SUBMIT
                
                   flowURL = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/send-email';
                   var cache_url = addParam(flowURL, 'pre_cache', 1);
                   cache_url = addParam(cache_url, 'from', 'c80ebdfa77c6228d0e3b4df1fa520b8c');
                   cache_url = addParam(cache_url, 'segment', '');    
                   cache_url = addParam(cache_url, 'return', absolutePath(returnURL));
                    
                   $.post( cache_url, aeJS.settings, function( data ) {
                       if (typeof data.code !== 'undefined') {
                            aeJS.events.onEmailVerify.callHandler('error', data);
                       } else {
                            aeJS.events.onEmailVerify.callHandler('sent', {'EmailAddress':aeJS.settings.email, 'ActivationCode':data });
                       }
                   });  
                
                } else { //USE DEFAULT FLOWS
                    aeJS.step_triggered = step; //value to check for post modal close events
                    aeJS.events.onFlow.callHandler(aeJS.flow);
                }
            } 
            
            //send activity
            aeJS.trigger.send_activity = function (id,data,marker,record) {

               if (typeof record === 'undefined') record = false; 
               activityURL = 'https://sme.theappreciationengine.com/framework-v1.3/send_activity/496';
               var data = {activity_id: id, data: data, marker: marker, record: record};

               $.post( activityURL, data, function( response ) {
                   aeJS.events.onActivitySent.callHandler(response);
               });  
  
            } 
            
            //send optin data
            aeJS.trigger.optin = function (brandid,segmentid,record) {

               if (typeof record === 'undefined') record = false;
               optinURL = 'https://sme.theappreciationengine.com/framework-v1.3/optin/496';
               var data = {brandid: brandid, segmentid: segmentid, record: record};

               $.post( optinURL, data, function( response ) {
                   aeJS.events.onOptin.callHandler(response);
               });  
  
            } 
            
            //reset password
            aeJS.trigger.reset_password = function (service_id,email,password) {
            
                if (typeof service_id === 'undefined') error = 'missing service id';
                if (typeof email === 'undefined') error = 'missing email';
                if (typeof password === 'undefined') error = 'missing password';
                
                if (typeof error !== 'undefined') {
                    aeJS.events.onPasswordReset.callHandler('error', error);
                    return;
                }
                
                flowURL = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/reset-password-ok';
                var cache_url = addParam(flowURL, 'pre_cache', 1);
                cache_url = addParam(cache_url, 'from', 'c80ebdfa77c6228d0e3b4df1fa520b8c');
                cache_url = addParam(cache_url, 'segment', '');
                    
                $.post( cache_url, {'password' : password, 'email': email, 'member_service_id': service_id}, function( data ) {
                    aeJS.events.onPasswordReset.callHandler('ok');
                });
            } 
            
            //submit the form passed in, must be ae-register-form
            aeJS.trigger.submit = function (form) {
                
                if ($(form).data('aeRegisterForm') !== 'undefined') {
                    $(form).submit();
                }
                
            } 
                
            //open popup with provided url
            aeJS.trigger.popup = function (url,callback) {
                
                var popupWidth=600;
                var popupHeight=450;
                var xPosition=($(window).width()-popupWidth)/2;
                var yPosition=($(window).height()-popupHeight)/2;

                openAuthWindow({
                    path: url,
                    windowOptions: 'width='+popupWidth+',height='+popupHeight+',left='+xPosition+',top='+yPosition,
                    callback: aeJS.events.onWindow.callHandler
                });
                    
            }
            
            createNS('aeJS.get'); 
            //return current user data
            aeJS.get.user = function () {  
                return aeJS.user;      
            }
            
            //get current flow for user
            aeJS.get.flow = function () {
                
                var reason = isValidLogin(true);
                
                if (reason === true) reason = 'done';
                if (typeof aeJS.settings['return_url'] !== 'undefined') returnURL = aeJS.settings['return_url'];
                else returnURL = location.href;
                
                aeJS.flow.step = reason;
                aeJS.flow.return = returnURL;
                return aeJS.flow;                 
            }
            
            //createNS('aeJS.set'); 
            //return current user data
            /*aeJS.set.user = function (user) {
                
                aeJS.user = user;
                    
            }*/
            
             // --- Initialize Page Elements (login, flow insert, etc )
             aeJS.trigger.attach = function (context) {
             
                 //console.log('ATTACH!');
                 // --- Login/Register Screen
                 $('a[data-ae-login-window]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var url = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/login';
                    var step = 'login';
                    var returnURL = window.location.href;

                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag

                    //TODO or attach onclick function...so devs can too
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, return: returnURL }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
                $('a[data-ae-register-window]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var url = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/register';
                    var step = 'register';
                    var returnURL = window.location.href;

                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag

                    //TODO or attach onclick function...so devs can too
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, return: returnURL }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
            
                // --- Auth/Login/Register/Logout URLs
                $('a[data-ae-login-link]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var loginURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/3372"};
                    var service = $(this).data('aeLoginLink');
                    var url = loginURLs[service];
                    url = addParam(url, 'segment', '');
                    var step = 'login-direct';
                    var returnURL = window.location.href;

                    //special case for email
                    if (service === 'email') step = 'login-direct-email';

                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag
                    if ($(this).data('aeStep')) step = $(this).data('aeStep'); //set step based on settings

                    //TODO or attach onclick function...so devs can too
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, 'return' : returnURL, 'service' : service}, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
                $('a[data-ae-register-link]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var registerURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/3372"};
                    var service = $(this).data('aeRegisterLink');
                    var url = registerURLs[service];
                    url = addParam(url, 'segment', '');
                    var step = 'register-direct';
                    var returnURL = window.location.href;

                    //special case for email
                    if (service === 'email') step = 'register-direct-email';

                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag
                    if ($(this).data('aeStep')) step = $(this).data('aeStep'); //set step based on settings

                    //TODO or attach onclick function...so devs can too
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, 'return' : returnURL, 'service' : service }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
                $('a[data-ae-logout-link]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var step = 'logout';
                    var returnURL = window.location.href;
                    var url = 'https://sme.theappreciationengine.com/brand/sony-music-us-legacy/logout';

                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag

                    //TODO or attach onclick function...so devs can too;
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, return: returnURL }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
                $('a[data-ae-auth-link]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var authURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/auth\/3372"};
                    var service = $(this).data('aeAuthLink');
                    var url = authURLs[service];
                    var step = 'authenticate';
                    var returnURL = window.location.href;

                    //special case for email?
                    if (service === 'email') step = 'auth-direct-email';

                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag
                    if ($(this).data('aeStep')) step = $(this).data('aeStep'); //set step based on settings

                    //TODO or attach onclick function...so devs can too
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, 'return' : returnURL, 'service' : service }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
                $('a[data-ae-remove-link]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var removeURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/remove\/3372"};
                    var service = $(this).data('aeRemoveLink');
                    var url = removeURLs[service];
                    var step = 'remove';
                    var returnURL = window.location.href;
                    
                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag
                    if ($(this).data('aeStep')) step = $(this).data('aeStep'); //set step based on settings

                    //TODO or attach onclick function...so devs can too
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, 'return' : returnURL, 'service' : service }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match

                });
                $('a[data-ae-link]').each(function(index) { //generic links (used for any step...)

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    var step = $(this).data('aeLink');
                    var url = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/' + step;
                    if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag
                    else returnURL = location.href;

                    //TODO or attach onclick function...so devs can too;
                    $(this).off('click',aeJS.events.onFlow.clickHandler).on('click', {'step' : step, 'auth_url' : url, return: returnURL }, aeJS.events.onFlow.clickHandler);
                    
                    } //context match
                    
                });
                $('input[data-ae-optin],input[data-ae-optin-brandid],input[data-ae-optin-segmentid]').each(function(index) {
                    if ($(this).data('aeOptin')) $(this).after('<label class=\'ae-optin-label\'>' + $(this).data('aeOptin') + '</label>');
                });
                $('form[data-ae-register-form]').each(function(index) {

                    if (typeof context == 'undefined' || $(context).is($(this))) {
                    
                    $(this).off('submit.aeJS'); //remove existing, avoid double ups
                    
                    aeJS.formSubmit = function ( event ) {

                      event.preventDefault();
                      
                      //override window setting here for mobile unless override disabled
                      if (parseInt() === 1 && aeJS.settings['mobile_detect']) aeJS.settings['auth_window'] = false;
                    
                      var loginType = 'register';
                      if ($(this).data('aeType')) loginType = $(this).data('aeType');
                      if (loginType == 'registration') loginType = 'register'; //values mean the same
                      var service = $(this).attr('data-ae-register-form');
                      
                      if (loginType == 'register') {
                        var registerURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/register\/3372"};
                        var url = registerURLs[service];
                        var step = 'register-direct';
                      } else {
                        var loginURLs = {"email":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2455","spotify":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2766","twitter":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2767","deezer":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2768","youtube":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2769","google":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2770","facebook":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2771","applemusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/2944","amazonmusic":"https:\/\/sme.theappreciationengine.com\/brand\/sony-music-us-legacy\/login\/3372"};
                        var url = loginURLs[service];
                        var step = 'login-direct';
                      }
                      
                      var returnURL = window.location.href;
                      var update = false;
                      var first_time_login = false;
                      
                      //console.log(service);
                      
                      if ($(this).data('aeReturn')) returnURL = $(this).data('aeReturn'); //set return url based on data tag

                      //set form action based on attribute
                      $(this).attr('action', url);

                      //If user is already logged in and has completed registration point to update endpoint (skip authentication)
                      if (typeof aeJS.user.data !== 'undefined' && typeof $(this).data('aeType') == 'undefined') {
                        url = url.replace(/register|login|auth/gi, 'update');
                        update = true;
                      }

                      var this_form = $(this);
                      var method = aeJS.settings['auth_window'] === true ? 'window' : 'direct';
                      if (!$(this).data('aeReturn') && typeof aeJS.settings['return_url'] !== 'undefined')
                      returnURL = aeJS.settings['return_url'];

                      aeJS.flow.return = returnURL;

                      flowURL = addParam('https://sme.theappreciationengine.com/framework-v1.3/flow/496/prep', 'auth_url', url);
                      flowURL = addParam(flowURL, 'return', absolutePath(returnURL));
                      flowURL = addParam(flowURL, 'auth_method', method);
                      if (!aeJS.isEmbed) {
                        flowURL = addParam(flowURL, 'referring_url',top.document.referrer);
                      }
                      
                      //add optins
                      var optins = '';
                      $('input[data-ae-optin],input[data-ae-optin-brandid],input[data-ae-optin-segmentid]').each(function(index) {
                        var brandid = $(this).data('aeOptinBrandid');
                        var segmentid = $(this).data('aeOptinSegmentid');
                        var label = $(this).data('aeOptin');

                        if ($(this).prop('checked')) {
                            optins = optins + brandid + ':' + segmentid + ':' + label + ',';
                        }
                        
                      });
                
                      if (update) {
                         
                          if (typeof aeJS.user.data != 'undefined') {
                            var input = $('<input>').attr('type', 'hidden').attr('name', 'MemberID').val(aeJS.user.data.ID);
                            $(this).append($(input));
                          }
                          
                          $.post('https://sme.theappreciationengine.com/framework-v1.3/auth_state/496', $(this).serialize(), function( auth_state ) {
                            
                            //console.log(auth_state);

                            //error checking...
                            aeJS.user = auth_state.user;
                           
                            if (isValidLogin()) {
                            
                                var login_type = auth_state['registration'] === true ? 'registration' : 'login';
                                if (aeJS.loggedIn) {
                                    aeJS.events.onUser.callHandler(auth_state.user,'update'); //active user updated
                                } else {
                                    aeJS.events.onLogin.callHandler(auth_state.user,login_type); //new user completed signup
                                }
                                
                            } else { //something missing
                                var reason = isValidLogin(true);
                                aeJS.flow.step = reason;
                                aeJS.flow.return = (auth_state.return === 'undefined') ? aeJS.flow.return : auth_state.return;
                                //settings have prevented default validation flows, but specified requirements missing - so notify
                                aeJS.events.onFlow.callHandler(aeJS.flow,false); 
                            }
                              
                          });

                      } else {
                      
                           //console.log(service);
                           aeJS.loggedIn = false;
                           if (service == 'email') {
                           
                                if (aeJS.settings['auth_window'] === true) {  
                                
                                    var email_reg_url = addParam('https://sme.theappreciationengine.com/framework-v1.3/email_ajax_register/496','return', absolutePath(returnURL));
                                    email_url = addParam(email_reg_url, 'auth_method', method);
                                    email_url = addParam(email_reg_url, 'type', loginType);
                                    email_url = addParam(email_url, 'optins', optins);
                                    
                                    $.post(email_url, $(this).serialize(), function( auth_state ) {
                                          //trigger login event
                                          console.log(auth_state);
                                          nextSteps(auth_state);
                                    });
                                    
                                } else {
                                    
                                    var input = $('<input>').attr('type', 'hidden').attr('name', 'return').val(absolutePath(returnURL));
                                    $(this).append($(input));
                                    
                                    var cache_url = addParam(flowURL, 'pre_cache', 1);
                                    cache_url = addParam(cache_url, 'optins', optins);
                                    $.post( cache_url, aeJS.settings, function( data ) {
                                    
                                        this_form.off('submit.aeJS');
                                        this_form.submit();
                                        this_form.on('submit.aeJS',aeJS.formSubmit);

                                    });
                                
                                }
                                
                            } else {
                          
                                if (aeJS.settings['auth_window'] === true) {           
                                    aeJS.trigger.popup('about:blank');
                                    $(this).prop('target', aeJS.auth_window.name);
                                } 

                                var input = $('<input>').attr('type', 'hidden').attr('name', 'return').val(absolutePath(returnURL));
                                $(this).append($(input));
                                    
                                var cache_url = addParam(flowURL, 'pre_cache', 1);
                                cache_url = addParam(cache_url, 'optins', optins);
                                $.post( cache_url, aeJS.settings, function( data ) {

                                  this_form.off('submit.aeJS');
                                  this_form.submit();
                                  this_form.on('submit.aeJS',aeJS.formSubmit);

                                });
                              
                          }

                      }

                    };
                    
                    $(this).on('submit.aeJS',aeJS.formSubmit);
                    
                    } //context match

                });
            }
            
            // --- Flow Inserts
            if (!aeJS.isEmbed) {
               createNS('aeJS.modal');aeJS.modal.overlay = $( '<div/>' );aeJS.modal.overlay.attr('id','ae-modal-overlay');aeJS.modal.overlay.attr('class','ae-modal-overlay ae-modal-overlay-closed');$( 'body' ).append( aeJS.modal.overlay );aeJS.modal.window = $( '<div/>' );aeJS.modal.window.attr('id','ae-modal');aeJS.modal.window.attr('class','ae-modal ae-modal-closed');$( 'body' ).append( aeJS.modal.window );aeJS.modal.window.omniWindow({
                           overlay: {
                            selector: '.ae-modal-overlay', 
                            hideClass: 'ae-modal-overlay-closed'
                           },
                           modal: {
                            hideClass: 'ae-modal-closed'
                           },
                           callbacks: { 
                            afterHide: function(subjects, internalCallback) { 
                              $('#ae-flow-frame').remove();
                              aeJS.events.onWindow.callHandler({'type':'modal', 'state':'closed'});
                              //any triggered events to notify?
                              if (typeof aeJS.step_triggered !== 'undefined') {
                                if (aeJS.step_triggered == 'verify-email') aeJS.events.onEmailVerify.callHandler('sent', {'EmailAddress':aeJS.user.data.Email }); 
                              }
                              return internalCallback(subjects); // call internal callback 
                            },
                            afterShow: function(subjects, internalCallback) { 
                              aeJS.events.onWindow.callHandler({'type':'modal', 'state':'opened'})
                              return internalCallback(subjects); // call internal callback 
                            }
                           }
                       });aeJS.modal.window.show = function(flowURL,data) {
            
                  //ensure top level for modal
                  aeJS.modal.overlay.css( 'z-index', function( index ) {
                      return topZIndex() + 1;
                  });
                  aeJS.modal.window.css( 'z-index', function( index ) {
                      return topZIndex() + 1;
                  });
                  
                  flowURL = addParam(flowURL, 'pre_cache', 1);  
                  $.post( flowURL, data, function( data ) {
                        flowURL = addParam(flowURL, 'cache_key', data);
                        aeJS.modal.window.append('<iframe id=\'ae-flow-frame\' name=\'ae-flow-frame\' src=\''+flowURL+'\' seamless=\'seamless\'/>');
                        aeJS.modal.window.trigger('show');
                  });      
        };
            }
            
            $('[data-ae-extra-info]').each(function(index) {
                
                $(this).hide();
                var insert = $(this).data('aeExtraInfo');
                var position = ($(this).data('aeExtraInfoPosition') === 'undefined') ? 'top' : $(this).data('aeExtraInfoPosition'); 
                
                //define insert position
                default_settings['extra_info'][insert] = {};
                default_settings['extra_info'][insert][position] = {};
                
                //set content
                default_settings['extra_info'][insert][position]['title'] = $(this).children('h3').text();
                default_settings['extra_info'][insert][position]['text'] = $(this).children('div').html();

            });
            
            // --- READY!
            //alert('READY');
            aeJS.trigger.attach();
            if (typeof GetURLParameter('accessToken') !== 'undefined') {
                    safariRedirect();
                    token = GetURLParameter('accessToken');
                    //alert(token);
                    authUrl = 'https://sme.theappreciationengine.com//framework-v1.3/auth_state/496/'+token;
                    //if no current member session exists will initiate for valid members, allowing login event or SSO.    
                    if (typeof GetURLParameter('init_token_login') !== 'undefined') {
                        if (GetURLParameter('init_token_login') == 'true') authUrl = addParam(authUrl, 'ae_token_login', 1);
                    }
                    //alert(authUrl);
                    $.ajax({
                        url: authUrl,
                        dataType: 'JSONP',
                        type: 'GET',
                        success: function (auth_state) {
                        
                            //needs to be parsed or already object
                            try {
                                state = JSON.parse(auth_state)
                            } catch (e) {
                                state = auth_state
                            }
    
                            nextSteps(state);

                        }
                    });
                };
            if (typeof(window.AEJSReady) == 'function') {
                
                window.AEJSReady(aeJS);
                initSettings()
                
        aeJS.events.onWindow.addHandler(function(data) {
            
            if (data.state === 'closed' && data.type == 'popup') {
            
                //console.log('WINDOW')
                //console.log(messageHandled);
                if (!aeJS.isEmbed && !messageHandled) { //only on main window (origin)
                $.ajax({
                    url: 'https://sme.theappreciationengine.com//framework-v1.3/auth_state/496',
                    dataType: 'JSONP',
                    type: 'GET',
                    success: function (auth_state) {
                        
                        //console.log(auth_state);
                        nextSteps(auth_state);
                             
                        //refresh user data etc - redirect if return is not this url?
                        //var login_type = auth_state['registration'] === true ? 'registration' : 'login';
                        //aeJS.user = typeof auth_state.user !== 'undefined' ? auth_state.user : {}; 
                        
                    }
                });
                }
            }
            
        });

        // need one for login that sets user object...
        aeJS.events.onLogin.addHandler(function(data,type) {
            //console.log('DEFAULT LOGIN HANDLER!');
            //alert('DEFAULT LOGIN HANDLER!');
            setLinkState(true);
            aeJS.user = data;
            aeJS.loggedIn = true;
        });
        aeJS.events.onUser.addHandler(function(data,state) {
            //console.log('DEFAULT USER HANDLER!');
            //alert('DEFAULT USER HANDLER!');
            setLinkState(true);
            aeJS.user = data;
            aeJS.loggedIn = true;
        });
        aeJS.events.onLogout.addHandler(function(data) {
            //console.log('DEFAULT LOGOUT HANDLER!');
            setLinkState(false);
            aeJS.user = data;
            aeJS.loggedIn = false;
        });
        aeJS.events.onMobileDetect.addHandler(function(data) {
            //console.log('DEFAULT MOBILE HANDLER!');
        });
        aeJS.events.onServiceRemoved.addHandler(function(service,user) {
            //console.log('DEFAULT SERVICE REMOVED HANDLER!');
        });
        aeJS.events.onLoaded.addHandler(function(service,user) {
            //console.log('DEFAULT ONLOADED HANDLER!');
        });
        aeJS.events.onEmailVerify.addHandler(function(service,user) {
            //console.log('DEFAULT EMAIL VERIFY HANDLER!');
        });
        aeJS.events.onActivitySent.addHandler(function(response) {
            //console.log('DEFAULT ACTIVITY SENT HANDLER!');
        });
        aeJS.events.onOptin.addHandler(function(response) {
            //console.log('DEFAULT Optin HANDLER!');
        });
        aeJS.events.onPasswordReset.addHandler(function(service,user) {
            //console.log('DEFAULT PASSWORD RESET HANDLER!');
        });

        aeJS.events.onFlow.addHandler(function(data,include_default) {
        
            if (include_default !== false) {
            
                //console.log('DEFAULT FLOW HANDLER!');
                var url = aeJS.flow.auth_url;
                var missing;
                var flowURL;

                //-- OVERRIDES
                //verify email check (settings valid)
                checkVerifyEmail();
                
                var div = document.createElement('div');
                div.innerHTML = '<!--[if lt IE 10]><i></i><![endif]-->';
                var isIeLessThan10 = (div.getElementsByTagName('i').length == 1);
                if (isIeLessThan10) {
                    aeJS.settings['auth_window'] = false;
                }
                
                //override window setting here for mobile unless override disabled
                if (parseInt() === 1 && aeJS.settings['mobile_detect']) aeJS.settings['auth_window'] = false;
                    
                //console.log(aeJS);

                if (aeJS.flow.step === 'authenticate') { //pass to authenticate method (determines direct vs auth dialog popup)

                    aeJS.loggedIn = false;
                    url = addParam(url, 'return', absolutePath(aeJS.flow.return));
                    if (JSON.parse(aeJS.settings['auth_window']) !== true) url = addParam(url, 'auth_method', 'direct');
                    //if calling directly attach refer for domain stamping, otherwise uses session state
                    if (!aeJS.isEmbed) url = addParam(url, 'auth_referer', 'https://www.paulsimon.com');

                    authenticate(url);
                    
                } else if (aeJS.flow.step === 'remove') {

                    if (JSON.parse(aeJS.settings['auth_window']) === true && !aeJS.isEmbed) { //Don't use if already in modal/ajax (isEmbed = true)

                        //logout user via ajax and clear local user
                        url = addParam(url, 'ae_appid', '91');
                        url = addParam(url, 'auth_method', 'window');
                        $.post( url, aeJS.settings, function( auth_state ) {
                            aeJS.user = auth_state.user;
                            aeJS.events.onServiceRemoved.callHandler(auth_state.service,auth_state.user);
                        });

                    } else { 

                         url = addParam(url, 'auth_method', 'direct');
                         url = addParam(url, 'return', absolutePath(aeJS.flow.return));
                         location.href = url;

                    }

                } else if (aeJS.flow.step === 'logout') {

                    if (JSON.parse(aeJS.settings['auth_window']) === true && !aeJS.isEmbed) { //Don't use if already in modal/ajax (isEmbed = true)

                        //logout user via ajax and clear local user
                        aeJS.trigger.logout();

                    } else { 

                         url = addParam(url, 'auth_method', 'direct');
                         url = addParam(url, 'return', absolutePath(aeJS.flow.return));
                         location.href = url;

                    }

                } else { //other steps (modal/ajax flow or direct url)

                    //abort conditions
                    if (aeJS.flow.step === 'error' && aeJS.settings['display_error_message'] === false) return;
                    if (aeJS.settings['default_flow_handlers'] === false) return;
                    
                    //set-up flow url and params
                    flowURL = addParam('https://sme.theappreciationengine.com/framework-v1.3/flow/496/'+aeJS.flow.step, 'auth_url', url);
                    flowURL = addParam(flowURL, 'return', absolutePath(aeJS.flow.return));
                    if (!aeJS.isEmbed) flowURL = addParam(flowURL, 'auth_referer', 'https://www.paulsimon.com');
                    if (JSON.parse(aeJS.settings['auth_window']) === true || aeJS.isEmbed) flowURL = addParam(flowURL, 'auth_method', 'window');

                    //modal/ajax flow or direct link (pre cached)
                    if (JSON.parse(aeJS.settings['auth_window']) === true && !aeJS.isEmbed) { //Don't use if already in modal/ajax (isEmbed = true)

                        aeJS.modal.window.show(flowURL,aeJS.settings);

                    } else { 

                        var cache_url = addParam(flowURL, 'pre_cache', 1);
                        if (aeJS.isEmbed) {
                            cache_url = addParam(cache_url, 'auth_method', 'window');
                        } else {
                            cache_url = addParam(cache_url, 'auth_method', 'direct');
                        }
                        $.post( cache_url, aeJS.settings, function( data ) {
                            flowURL = addParam(flowURL, 'cache_key', data);
                            location.href = flowURL;
                        });

                    }

                }
            
            }

        });;
                
                // set up prep 
                // not in framework flow (isEmbed=true), i.e it would already be prepped
                if (!aeJS.isEmbed) {
                    flowURL = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/prep';
                    var cache_url = addParam(flowURL, 'pre_cache', 1);
                    cache_url = addParam(cache_url, 'from', 'c80ebdfa77c6228d0e3b4df1fa520b8c');
                    cache_url = addParam(cache_url, 'segment', '');    
                    if (!aeJS.isEmbed) {
                        cache_url = addParam(cache_url,'referring_url',top.document.referrer);
                    }
                    
                    $.post( cache_url, aeJS.settings, function( data ) {
                        aeJSPrepped = true;
                        aeJS.events.onLoaded.callHandler(aeJS);
                    });
                    
                } else {
                     aeJSPrepped = true;
                }
                
                if (typeof GetURLParameter('step') !== 'undefined') {
                    
                switch (GetURLParameter('step')) {
                
                    case 'error' : 
                        nextSteps({'state' : 'error', 'error' : {'code' : GetURLParameter('code'), 'message' : GetURLParameter('message')}}); 
                    break;
                    
                    case 'verify-email-ok' : 
                    
                        //add login handler on window close (just once)
                        aeJS.self_destruct = function(e) {
                            if (e.type === 'modal' && e.state === 'closed') {
                                getAuthState();
                                aeJS.events.onWindow.removeHandler(aeJS.self_destruct);
                            }
                        }
                        aeJS.events.onWindow.addHandler(aeJS.self_destruct);
                                
                        //set-up flow and params
                        aeJS.settings['code'] = GetURLParameter('code');
                        aeJS.flow.step = 'verify-email-ok';
                        aeJS.events.onFlow.callHandler(aeJS.flow);
                        
                    break;
                    
                    case 'reset-password-ok' :
                    
                        //add login handler on window close (just once)
                        aeJS.self_destruct = function(e) {
                            if (e.type === 'modal' && e.state === 'closed') {
                                getAuthState();
                                aeJS.events.onWindow.removeHandler(aeJS.self_destruct);
                            }
                        }
                        aeJS.events.onWindow.addHandler(aeJS.self_destruct);
                        
                        //set-up flow and params
                        aeJS.settings['code'] = GetURLParameter('code');
                        aeJS.flow.step = 'reset-password-ok';
                        aeJS.events.onFlow.callHandler(aeJS.flow);
                                
                    break;
                    
                    case 'send-email-ok' : 
                    
                        //set-up flow and params
                        aeJS.settings['code'] = GetURLParameter('code');
                        flowURL = 'https://sme.theappreciationengine.com/framework-v1.3/flow/496/send-email-ok';
                        var cache_url = addParam(flowURL, 'pre_cache', 1);
                        cache_url = addParam(cache_url, 'from', 'c80ebdfa77c6228d0e3b4df1fa520b8c');
                        cache_url = addParam(cache_url, 'segment', '');
                            
                        $.post( cache_url, aeJS.settings, function( auth_state ) {
                           
                           if (typeof auth_state.code !== 'undefined') {
                              aeJS.events.onEmailVerify.callHandler('error', auth_state);
                           } else {
                              auth_state = JSON.parse(auth_state);
                              //console.log(JSON.stringify(auth_state));
                              aeJS.events.onEmailVerify.callHandler('verified', auth_state.verified);
                              getAuthState(); //auth_state.user.data.ID
                           }
                           
                        });  
                        
                    break;
                    
                    case 'remove-service' :
                    
                        var service = GetURLParameter('service');
                        aeJS.events.onServiceRemoved.callHandler(service,aeJS.user);
                                
                    break;
                }

        };
                     
            }
            
            });
            
          }
          
        })(); // We call our anonymous function immediately
        //setTimeout(function(){
        //    if (window.jQuery !== undefined) { console.log('JQuery version ' + jQuery.fn.jquery + ' is still used in local'); }
        //}, 1000);
        