// IDCRL Account Types
var WLID_ACCOUNT_TYPE_WLID = '0';
var WLID_ACCOUNT_TYPE_FED = '1';
var WLID_ACCOUNT_TYPE_UNKNOWN = '2';

// IDCRL UserExtendedProperty Names
var WLID_USER_EX_PROP_LAST_USED_CRED = 'LastUsedCredType';  
var WLID_USER_EX_PROP_LAST_USED_FED_TYPE = 'LastUsedFedType';  
var WLID_USER_EX_PROP_AUTO_SIGN_IN = 'AutoSignIn';
var WLID_USER_EX_PROP_USER_TILE_URL = 'UserTileUrl';
var WLID_USER_EX_PROP_CERT_THUMB = 'CertThumbprint';
    
// IDCRL SetCredential Types
var PPCRL_CREDTYPE_PASSWORD = 'ps:password';
var PPCRL_CREDTYPE_MEMBERNAMEONLY = 'ps:membernameonly';
var PPCRL_CREDTYPE_PIN = 'ps:pin';
var PPCRL_CREDTYPE_EID = 'ps:eid';

// IDCRL Stored User Types
var PPCRL_USER_SAVED_PASSWORD = '1';
var PPCRL_USER_MEMBERNAME_ONLY = '16';

// IDCRL Credential Types
var WLID_LAST_USED_CRED_PASSWORD = '1';
var WLID_LAST_USED_CRED_FEDERATION = '3';
var WLID_LAST_USED_CRED_EID = '4';
var WLID_LAST_USED_CRED_FED_PASSWORD = '5';
var WLID_LAST_USED_CRED_FED_EID = '6';
var WLID_LAST_USED_CRED_FED_WIAUTH = '7';
var WLID_LAST_USED_CRED_UNKNOWN = '';

// IDCRL Input Property Names
var x_wstrUIOptionValueTRUE  = 'TRUE';
var x_wstrUIOptionValueFALSE = 'FALSE';

var k_wstrInProp_DefaultUser = 'DefaultUser';
var x_wstrUIOptionRememberMe = 'UIOptionRememberMe';
var x_wstrUIOptionSavePassword = 'UIOptionSavePassword';
var x_wstrUIOptionSavedUsers = 'UIOptionSavedUsers';
var x_wstrUIOptionDifferentUser = 'UIOptionDifferentUser';
var k_wstrInProp_SmartCardEnabled = 'SCEnabled';
var k_wstrInProp_AppDisableSmartCard = 'AppSCDisabled';
var k_wstrInProp_SmartCardForce ='SCForce';
var k_wstrInProp_ForceSavePassword= 'PWDSaveForce';
var k_wstrInProp_DisableSignupLink= 'DisableSignup';
var k_wstrInProp_ForceFed ='ForceFed';

var k_wstrInProp_RTLTestEnabled = 'RTLTestEnabled';
var k_wstrInProp_TestHookEnabled = 'TestHookEnabled';

// IDCRL Output Property Names
var k_wstrOutProp_Member_name = 'MemberName';
var k_wstrOutProp_OptIn = 'OptIn';
var k_wstrOutProp_Confirmed = 'Confirmed';
var k_wstrOutProp_Change = 'Change'; // change user from confirmation ui
var k_wstrOutProp_Resolved = 'Resolved';
var k_wstrOutProp_LoginType = 'LoginType';

// IDCRL Config URL Property Names
var WLID_CONFIG_PROP_URL_REGISTRATION = 'URL_Registration';
var WLID_CONFIG_PROP_URL_PASSWORD_RESET = 'URL_PasswordReset';
var WLID_CONFIG_PROP_URL_HELP_FRAME = 'URL_PaneHelpFrame';
var WLID_CONFIG_PROP_URL_PRIVACY = 'URL_Privacy';
var WLID_CONFIG_PROP_URL_MANAGEEID = 'URL_Manageeid';

// Help Query String Search Term values
var WLID_SEARCH_TERM_REMEMBER_ME = 'emrebmemer';
var WLID_SEARCH_TERM_REMEMBER_PWD = 'ssaprebmemer';
var WLID_SEARCH_TERM_HELP = 'plehdievil';

// IDCRL HIP Property Names
var WLID_REQUEST_HIP_IMAGE = 'HIPImage';
var WLID_REQUEST_HIP_AUDIO_QS = 'HIPAudioURLAdditionalQS';
var WLID_REQUEST_HIP_AUDIO_URL = 'HIPAudioURL';
var WLID_REQUEST_HIP_AUDIO_SOLUTION = 'HIPAudioSolution';
var WLID_REQUEST_HIP_RESPONSE = 'HIPResponse';
var WLID_REQUEST_HIP_RESOLVED = 'Resolved';
var WLID_REQUEST_HIP_SOLUTION = 'HIPSolution';

// Default User Image Path
var WLID_IMAGE_DEFAULT_USER_TILE = 'WLID_UserTile.gif';

// URL ID's
var WLID_URL_HELP = 'URLHelp';
var WLID_URL_FORGOT_PWD = 'URLForgot';
var WLID_URL_SIGN_UP = 'URLSignup';
var WLID_URL_HELP_REMEMBER_ME = 'URLHelpRememberMe';
var WLID_URL_HELP_REMEMBER_PWD = 'URLHelpRememberPwd';
var WLID_URL_MANAGEEID = "URLManageEID";
var WLID_URL_PRIVACY = 'URLPrivacy';

// Consts used for URL creation
var WLID_URL_QS_LCID = 'lcid=';
var WLID_URL_QS_SEARCH_TERM = 'SEARCHTERM=';

// IDCRL Co-Branding Property Names
var k_wstrCoBrandingLogo           = 'logo';
var k_wstrCoBrandingText               = 'text';
var k_wstrCoBrandingAppName              = 'appname';
var k_wstrCoBrandingHeaderBgImg             = 'headerbg';
var k_wstrCoBrandingSignupTxt             = 'signuptxt';
var k_wstrCoBrandingURLColor         = 'urlcolor';
var k_wstrCoBrandingBgColor         = 'bgcolor';
var k_wstrCoBrandingTileBgColor         = 'tilebgcolor';
var k_wstrCoBrandingTileBdColor         = 'tilebdcolor';
var k_wstrCoBrandingFieldBdColor         = 'fieldbdcolor';
var k_wstrCoBrandingBtTxtColor              = 'bttxtcolor';
var k_wstrCoBrandingTileLbColor              = 'tilelbcolor';
var k_wstrCoBrandingCheckBoxBdColor         = 'checkboxbdcolor';
var k_wstrCoBrandingSignupUrl             = 'signupurl';
var k_wstrCoBrandingLeft                         = 'left';
var k_wstrCoBrandingTop                         = 'top';
var k_wstrCoBrandingCenterX                      = 'cx'; 
var k_wstrCoBrandingCenterY                      = 'cy'; 


var k_wstrInProp_LastVisitedPage = 'LastVisitedPage';
var k_wstrInProp_LastLoginType = 'LastLoginType';

// Realm Properties
var WLID_REALM_PROP_STATE = 'State';
var WLID_REALM_PROP_LOGIN = 'Login';
var WLID_REALM_PROP_FED_GLOBAL_VER = 'FederationGlobalVersion';
var WLID_REALM_PROP_DOMAIN_NAME = 'DomainName';
var WLID_REALM_PROP_AUTH_URL = 'AuthURL';
var WLID_REALM_PROP_IS_FEDERATED = 'IsFederatedNS';
var WLID_REALM_PROP_STS_AUTH_URL = 'STSAuthURL';
var WLID_REALM_PROP_FED_TIER = 'FederationTier ';
var WLID_REALM_PROP_FED_BRAND_NAME = 'FederationBrandName';
var WLID_REALM_PROP_ALLOW_WLID_SIGN_IN = 'AllowFedUsersWLIDSignIn';
var WLID_REALM_PROP_CERT = 'Certificate';

var PPCRL_REQUEST_E_AUTHTYPE_NOT_ASSOCIATED = 2147780855;
var min_Height = 430;
var max_Username = 113;
var max_Password = 16;

// *************************************************************************************************************************
// ExternalWrapperObj (Javascript Object)
//
// Wrapper around external object which provides calls to IDCRL functionality.
// *************************************************************************************************************************

// Dependencies:
/// <reference path="uicore.js" />
/// <reference path="saveduser.js" />
ExternalWrapperObj = function()
{
    this.handle = external;
}

ExternalWrapperObj.prototype = 
{
    defined:function()
    {
        /// <summary>Helper function to verify the IDCRL entry point is valid</summary>
        return (this.handle != undefined);
    },
    
    closeWindow:function()
    {
        /// <summary>Closes the window and returns functionality to calling application</summary>
        if(this.defined())
            this.handle.ReturnToApp();
    },
    
    resizeMoveWindow:function(leftValue, topValue, widthValue, heightValue)
    {
        /// <summary>Resizes and moves the application window</summary>
        /// <param name="leftValue">(int) X coordinate of top left corner</param>
        /// <param name="topValue">(int) Y coordinate of top left corner</param>
        /// <param name="widthValue">(int) Width of window</param>
        /// <param name="heightValue">(int) Height of window</param>
        if(this.defined())
            this.handle.MoveWindow(leftValue, topValue, widthValue, heightValue, false);
    },
    enableWindow:function(fEnable)
    {
        this.handle.EnableWindow(fEnable);
    },
    adjustWindowSize:function( id_tbLayout, objCobranding, changesizeonly, minHeight)
    {
        /// <summary>resize the windows based on the size of layout table</summary>
        /// <param name="id_tbLayout">(string) id of the layout table</param>

        // set default
        if ( !this.defined() )
            return;
        
        var tbLayout = 'pd_id_TableLayout';

        if ( id_tbLayout != null && id_tbLayout != undefined)
            tbLayout = id_tbLayout;

        var LayoutTable = document.getElementById(tbLayout);
        if ( null == LayoutTable || undefined == LayoutTable )
            return;

        
        var doc_width = LayoutTable.offsetWidth;
        var doc_height = LayoutTable.offsetHeight;

        if ( null != minHeight && undefined != minHeight )
        {
            if ( doc_height < minHeight )
                doc_height = minHeight;
        }

        var cx = screen.width / 2;                    
        var cy = screen.height / 2;
        var winleft = cx -doc_width / 2;
        var wintop = cy - doc_height / 2;

        this.handle.enableWindow(true);
        // resize based on the size of the layout table
        //
        if ( typeof changesizeonly != 'undefined' && changesizeonly )
        {
            this.handle.MoveWindow( -1 , -1,  doc_width, doc_height, true);
            return;
        }

        // resize based on the size of the layout table and move the window to the center of screen
        if ( null ==  objCobranding  || undefined == objCobranding )
        {
            this.handle.MoveWindow( winleft , wintop,  doc_width, doc_height, false);
            return;
        }

        // resize and move windows based on the cobranding data
        if ( objCobranding.m_strLeft && objCobranding.m_strLeft.length > 0 
            && objCobranding.m_strTop && objCobranding.m_strTop.length > 0 ) // specified left&top
        {
            winleft = parseInt(objCobranding.m_strLeft);
            wintop = parseInt(objCobranding.m_strTop); 
        }
        else
        {
            // set default
            if ( objCobranding.m_strCx && objCobranding.m_strCx.length > 0 )
                cx = parseInt(objCobranding.m_strCx);
            if ( objCobranding.m_strCy && objCobranding.m_strCy.length > 0 )
                cy = parseInt(objCobranding.m_strCy);

            winleft = cx -doc_width / 2;
            wintop = cy - doc_height / 2;
            
            if ( winleft < 0 ) winleft = 0;
            if ( wintop < 0 ) wintop = 0;
        }
        this.handle.MoveWindow( winleft , wintop,  doc_width, doc_height, false);
    },
    idcrlTrace:function(value)
    {
        if ( undefined == value || null == value )
            return;
            
        this.handle.trace( 3 /*PPTRACE_VERB_LEVEL*/, value );
    },
    getHIPImage:function()
    {
        /// <summary>Retrieves the HIP Image</summary>
        var toReturn = '';
        if(this.defined())
            toReturn = this.handle.GetHipChallenge(WLID_REQUEST_HIP_IMAGE);
        return toReturn;
    },
    
    createTempFile:function(file)
    {
        /// <summary>Creates a temporary file for the provided path</summary>
        /// <param name="file">(string) file to create</param>
        var toReturn = '';
        if(this.defined() && (file != undefined) && (file.length>0))
            toReturn = this.handle.CreateTempFile(file);
        return toReturn;
    },
    
    getHIPAudioURL:function()
    {
        /// <summary>Retrieves URL for HIP Audio</summary>
        var toReturn = '';
        if(this.defined())
        {
            toReturn = this.handle.GetHipChallenge(WLID_REQUEST_HIP_AUDIO_URL);
            var audioQS = this.handle.GetHipChallenge(WLID_REQUEST_HIP_AUDIO_QS);
            
            if((toReturn != undefined) && (toReturn.length>0))
            {
                toReturn = toReturn + '?lc=' + this.getLCID();
                if(audioQS)
                    toReturn = toReturn + '&' + audioQS;
            }
        }
        return toReturn;
    },
    
    setAudioHIPCookie:function()
    {
        /// <summary>Sets cookie signifying this is now a HIP audio challenge</summary>
        if(this.defined())
            this.handle.SetAudioHipCookie();
    },
    
    getHIPAudioSolution:function()
    {
        /// <summary>Retrieves the solution to the current HIP Audio challenge</summary>
        var toReturn = '';
        if(this.defined())
            toReturn = this.handle.GetHipChallenge(WLID_REQUEST_HIP_AUDIO_SOLUTION);
            
        return toReturn;
    },
    
    setHIPSolution:function(value)
    {
        /// <summary>Sets the solution of the current HIP Audio challenge</summary>
        /// <param name="value">(string) Solution</param>
        if(this.defined() && (value != undefined))
        {
            this.handle.SetHipSolution(WLID_REQUEST_HIP_RESPONSE, value);
            if(value!='')
                this.resolve();
        }
    },
    
    resolve:function()
    {
        /// <summary>Sets the 'Resolved' output property as true</summary>
        if(this.defined())
            this.handle.SetOutputProp(WLID_REQUEST_HIP_RESOLVED, 'true');
    },  
    
    getCobranding:function()
    {
        /// <summary>Returns a CobrandingObj containing the current Cobranding settings</summary>
        toReturn = new CobrandingObj();
        if(this.defined())
        {
            var coImage = this.handle.GetCobrandingData(k_wstrCoBrandingLogo);
            var coHeadBgImg = this.handle.GetCobrandingData(k_wstrCoBrandingHeaderBgImg);
            var coSignupTxt = this.handle.GetCobrandingData(k_wstrCoBrandingSignupTxt);
            var coSignupUrl = this.handle.GetCobrandingData(k_wstrCoBrandingSignupUrl);
            
            var coText = this.handle.GetCobrandingData(k_wstrCoBrandingText);
            var coAppName = this.handle.GetCobrandingData(k_wstrCoBrandingAppName);

            var coLink = this.handle.GetCobrandingData(k_wstrCoBrandingURLColor);
            var coBG = this.handle.GetCobrandingData(k_wstrCoBrandingBgColor);
            var coTileBG = this.handle.GetCobrandingData(k_wstrCoBrandingTileBgColor);
            var coTileBd = this.handle.GetCobrandingData(k_wstrCoBrandingTileBdColor);
            var coFieldBd = this.handle.GetCobrandingData(k_wstrCoBrandingFieldBdColor);
            var coCheckboxBd = this.handle.GetCobrandingData(k_wstrCoBrandingCheckBoxBdColor);
            var coBtTxt = this.handle.GetCobrandingData(k_wstrCoBrandingBtTxtColor);            
            var coTileLb = this.handle.GetCobrandingData(k_wstrCoBrandingTileLbColor);            
            
            var coLeft = this.handle.GetCobrandingData(k_wstrCoBrandingLeft);  
            var coTop = this.handle.GetCobrandingData(k_wstrCoBrandingTop);  
            var coCx = this.handle.GetCobrandingData(k_wstrCoBrandingCenterX);            
            var coCy = this.handle.GetCobrandingData(k_wstrCoBrandingCenterY);
            
            
            if(coImage && coImage.length>0)
                toReturn.setImage(coImage);
            if(coText && coText.length>0)
                toReturn.setText(coText);
            if(coLink && coLink.length>0)
                toReturn.setLinkColor(coLink);
            if(coBG && coBG.length>0)
                toReturn.setBGColor(coBG);

            if(coHeadBgImg && coHeadBgImg.length>0)
                toReturn.setBgImage( coHeadBgImg );
            if(coSignupTxt && coSignupTxt.length>0)
                toReturn.m_strSignupText = coSignupTxt;
            if(coFieldBd && coFieldBd.length>0)
                toReturn.m_strFieldBdColor = coFieldBd;
            if(coCheckboxBd && coCheckboxBd.length>0)
                toReturn.m_strCheckboxLbColor = coCheckboxBd;
            if(coSignupUrl && coSignupUrl.length>0)
                toReturn.m_strSignupUrl = coSignupUrl;
            if(coBtTxt && coBtTxt.length>0)
                toReturn.m_strBtTxtColor = coBtTxt;
            
            if((coTileLb != undefined) && (coTileLb.length > 0))
                toReturn.setTileLBColor(coTileLb);            
            if((coTileBG != undefined) && (coTileBG.length > 0))
                toReturn.setTileBGColor(coTileBG);
            if((coTileBd != undefined) && (coTileBd.length > 0))
                toReturn.setTileBorderColor(coTileBd);
            if((coAppName != undefined ) && (coAppName.length > 0 ) )
                toReturn.setAppName( coAppName );

            if(coLeft && coLeft.length>0)
                toReturn.m_strLeft = coLeft;
            if(coTop && coTop.length>0)
                toReturn.m_strTop = coTop;
            if(coCx && coCx.length>0)
                toReturn.m_strCx = coCx;
            if(coCy && coCy.length>0)
                toReturn.m_strCy = coCy;
        }
        return toReturn;
    },
    
    getFlowURL:function()
    {
        /// <summary>Retrieves the Flow URL from IDCRL</summary>
        var toReturn = '';
        if(this.defined())
            toReturn = this.handle.GetFlowURL();
        return toReturn;
    },
    
    getLCID:function()
    {
        /// <summary>Retrieves the LCID for the current machine</summary>
        var toReturn = '';
        if(this.defined())
            toReturn = this.handle.Lcid;
        return toReturn;
    },
    
    getConfig:function(configValue)
    {
        /// <summary>Retrieves the value of the provided configuration parameter</summary>
        /// <param name="configValue">(string) Name of config parameter to retrieve</param>
        var toReturn = '';
        if(this.defined() && (configValue != undefined))
            toReturn = this.handle.GetServiceURI(configValue);
        return toReturn;
    },
    AppendQS:function(url,qs)
    {
        var sS="&";
        if(url.indexOf('?')==-1)
        {
            sS="?";
        }
        return url + sS + qs;
    },
    getURL:function(urlID)
    {
        /// <summary>Retrieves a specified URL</summary>
        /// <param name="urlID">(string) ID of URL to retrieve</param>
        var toReturn = '';
        if(this.defined() && (urlID != undefined))
        {
            var lcid = this.handle.Lcid;
            switch(urlID)
            {
                case WLID_URL_HELP:
                    var helpURL = this.getConfig(WLID_CONFIG_PROP_URL_HELP_FRAME);
                    if(helpURL && helpURL.length>0)
                        helpURL = this.AppendQS( helpURL , WLID_URL_QS_LCID + lcid );
                        toReturn = this.AppendQS( helpURL, WLID_URL_QS_SEARCH_TERM + WLID_SEARCH_TERM_HELP );
                    break;
                case WLID_URL_FORGOT_PWD:
                    var helpURL = this.getConfig(WLID_CONFIG_PROP_URL_PASSWORD_RESET);
                    if(helpURL && helpURL.length>0)
                        toReturn = this.AppendQS( helpURL , WLID_URL_QS_LCID + lcid );
                    break;
                case WLID_URL_SIGN_UP:
                    var helpURL = this.getConfig(WLID_CONFIG_PROP_URL_REGISTRATION);
                    if(helpURL && helpURL.length>0)
                        toReturn = this.AppendQS( helpURL, WLID_URL_QS_LCID + lcid );
                    break;
                case WLID_URL_HELP_REMEMBER_ME:
                    var helpURL = this.getConfig(WLID_CONFIG_PROP_URL_HELP_FRAME);
                    if(helpURL && helpURL.length>0)
                        helpURL = this.AppendQS( helpURL, WLID_URL_QS_LCID + lcid);
                        toReturn = this.AppendQS( helpURL, WLID_URL_QS_SEARCH_TERM + WLID_SEARCH_TERM_REMEMBER_ME );
                    break;
                case WLID_URL_HELP_REMEMBER_PWD:
                    var helpURL = this.getConfig(WLID_CONFIG_PROP_URL_HELP_FRAME);
                    if(helpURL && helpURL.length>0)
                        helpURL = this.AppendQS( helpURL, WLID_URL_QS_LCID + lcid );
                        toReturn = this.AppendQS( helpURL, WLID_URL_QS_SEARCH_TERM + WLID_SEARCH_TERM_REMEMBER_PWD );
                    break;
                case WLID_URL_MANAGEEID:
                    var url = this.getConfig(WLID_CONFIG_PROP_URL_MANAGEEID);
                    if ( url && url.length > 0 )
                        toReturn = this.AppendQS( url,  WLID_URL_QS_LCID + lcid ); 
                    break;
                case WLID_URL_PRIVACY:
                    // FWLink http://go.microsoft.com/fwlink/?LinkId=74170, browser language set
                    // will be honored automatically, don't need to append any lcid info
                    var helpURL = this.getConfig(WLID_CONFIG_PROP_URL_PRIVACY);
                    if(helpURL && helpURL.length>0)
                        toReturn = helpURL;
                    else
                        toReturn = "http://go.microsoft.com/fwlink/?LinkId=74170";
                    break;
                    
            }
        }
        return toReturn;
    },
    
    cleanError:function()
    {
        /// <summary>Clears the error from IDCRL</summary>
        if(this.defined())
            this.handle.CleanError();
    },
    
    getHideStatus:function(option)
    {
        /// <summary>Gets the hide status for the specified ID</summary>
        /// <param name="option">(string) ID of hide status to get</param>
        var toReturn = false;
        if(this.defined() && (option != undefined))
        {
            var stringResult = '';
            switch(option)
            {
                case x_wstrUIOptionRememberMe:
                case x_wstrUIOptionSavePassword:
                case x_wstrUIOptionSavedUsers:
                case x_wstrUIOptionDifferentUser:
                    stringResult = this.getProperty(option);
                    break;
                default:
                    stringResult = 'true';
                    break;
            }
            if(stringResult != undefined)
            {
                stringResult = stringResult.toLowerCase();
                if(stringResult == '0' || stringResult == 'false')
                    toReturn = true;
            }
        }
        return toReturn;
    },
    
    getString:function(stringID)
    {
        /// <summary>Gets the localized string</summary>
        /// <param name="stringID">(int) ID of localized string (See UIResource.js for allowed string ID's)</param>
        var toReturn = '';
        if(this.defined())
            toReturn = this.handle.GetString(stringID);
        return toReturn;
    },
    
    getCertList:function(applyFilter)
    {
        /// <summary>Creates an array of DisplayObj containing the Friendly Name, and Cert Thumb of each Smart Card certificate on the machine</summary>
        var toReturn = new Array();
        if(this.defined() && applyFilter != undefined)
        {
            eval(this.handle.GetCertList(applyFilter));
            if (typeof eids != 'undefined')
            {
                for (var i = 0; i < eids.length; i++ )
                    toReturn.push(new DisplayObj('CertType'+i, eids[i][0], eids[i][1]));
            }
        }
        return toReturn;
    },
    
    getErrorCode:function()
    {
        /// <summary>Gets any error code found in IDCRL</summary>
        var toReturn = 0;
        if(this.defined())
            toReturn = this.handle.GetErrorCode();
        return toReturn;
    },

    removeUser:function(username)
    {
        /// <summary>Removes any persisted credentials for the provided username</summary>
        /// <param name="username">(string) Username to remove credentials for</pararm>
        if(this.defined() && (username != undefined) && (username.length>0))
            this.handle.DeleteAccount(username);
    },
    
    getProperty:function(propertyName)
    {
        /// <summary>Gets the value for the provided input property</summary>
        /// <param name="propertyName">(string) Name of input property to get value for</param>
        var toReturn = '';
        if(this.defined() && (propertyName != undefined))
            toReturn = this.handle.GetInputProp(propertyName);
        return toReturn;
    },
    
    setProperty:function(propertyName, propertyValue)
    {
        /// <summary>Sets the value for the provided output property</summary>
        /// <param name="propertyName">(string) Name of output property</param>
        /// <param name="propertyValue">(string/int) Value of output property</param>
        if(this.defined() && (propertyName != undefined) && (propertyValue != undefined))
            this.handle.SetOutputProp(propertyName, propertyValue);
    },

    removeInputProperty:function(propName)
    {
        if(this.defined() && (propName != undefined))
            this.handle.RemoveInputProp(propName);
    },
    
    getIdentityType:function(username)
    {
        /// <summary>Gets the Account Type of the provided user</summary>
        /// <param name="username">(string) Username to get identity type for</param>
        var toReturn = WLID_ACCOUNT_TYPE_UNKNOWN;
        if(this.defined() && (username != undefined) && (username.length>0))
            toReturn = this.handle.GetIdentityType(username);
        return toReturn;
    },
    
    getNamespaceProperty:function(username, propName)
    {
        /// <summary>Gets a namespace property for the namespace the username belongs to</summary>
        /// <param name="username">(string) Username to get property for</param>
        /// <param name="propName">(string) Name of property to get value for</param>
        var toReturn = '';
        if(this.defined() && (username != undefined) && (username.length>0) && (propName != undefined) && (propName.length>0))
            toReturn = this.handle.GetFedRealm(username, propName);
        return toReturn;
    },
    
    getSupportedAuthTypes:function(username)
    {
        /// <summary>Gets an array of DisplayObj containing the localized friendly name, and auth type ID allowed for users in the namespace this user belongs to</summary>
        /// <param name="username">(string) Username to retrieve supported auth types for</param>
        var toReturn = new Array();
        if(this.defined() && (username != undefined))
        {
            // Returns a javascript statment which creates the 'authtypes' array
            eval(this.handle.GetSupportedAuthType(username));
//            eval("var authtypes = new Array();authtypes[0] = ['5', 4720];authtypes[1] = ['6', 3463];");

            if(typeof authtypes != 'undefined')
            {
                for (var i = 0; i < authtypes.length; i++ )
                    toReturn.push(new DisplayObj('AuthType'+authtypes[i][0], this.getString(authtypes[i][1]), authtypes[i][0]));
            }
        }
        return toReturn;
    },
    
    getImageForUser:function(username)
    {
        /// <summary>Retrieves the path to user image, if none is found the default user image is returned</summary>
        /// <param name="username">(string) Username to retrieve image for</param>
        var toReturn = null;
        if(this.defined() && (username != undefined))
            toReturn = this.getExtendedProperty(username, WLID_USER_EX_PROP_USER_TILE_URL);
            
        if((toReturn == undefined) || (toReturn.length==0))
            toReturn = WLID_IMAGE_DEFAULT_USER_TILE;
        return toReturn;
    },
    
    setOptIn:function(username, value)
    {
        /// <summary>Sets the opt in state of the user in memory</summary>
        /// <param name="username">(string) Username to set opt in state for</param>
        /// <param name="value">(string/bool) Value to set for opt in state</param>
        if(this.defined() && (username != undefined) && (value != undefined))
            this.handle.SetOptInState(username, value);
    },
    
    isUserPersisted:function(username, credtype)
    {
        /// <summary>Retrieves value representing whether this is a persisted user</summary>
        /// <param name="username">(string) Username to check persisted state for</param>
        var toReturn = false;
        var type = '';
        if ( credtype != null && credtype != undefined )
            type = credtype;
            
        if(this.defined() && (username != undefined))
        {
            var result = this.handle.IsPersistUser(username, type);
            if(result != undefined)
            {
                result = result.toLowerCase();
                if(result == '1' || result == 'true')
                    toReturn = true;
            }
        }
        return toReturn;
    },

    isSmartCardCert:function(thumbprint)
    {
        var toReturn = false;
        if(this.defined() && (thumbprint != undefined))
        {
            var result = this.handle.IsSmartCardCert(thumbprint);
            if(result != undefined)
            {
                result = result.toLowerCase();
                if(result == '1' || result == 'true')
                    toReturn = true;
            }
        }
        return toReturn;
    },
    isCapsLockOn:function()
    {
        var on = false;
        if ( this.defined() )
        {
            if ( this.handle.IsCapsLockOn() == 'true' )
                on = true;
        }
        return on;
    },
    getExtendedProperty:function(username, propName)
    {
        /// <summary>Gets specified UserExtendedProperty</summary>
        /// <param name="username">(string) Username to get UserExtendedProperty for</param>
        /// <param name="propName">(string) Name of UserExtendedProperty to retrieve value of</param>
        var toReturn = null;
        if(this.defined() && (propName != undefined) && (username != undefined))
            toReturn = this.handle.GetUserExtendedProperty(username, propName);
        return toReturn;
    },
    
    setExtendedProperty:function(username, propName, propValue)
    {
        /// <summary>Sets the value of a UserExtendedProperty only if the specified user is a persisted user</summary>
        /// <param name="username">(string) Username to set UserExtendedProperty for</param>
        /// <param name="propName">(string) Name of UserExtendedProperty to set</param>
        /// <param name="propValue">(string) Value of UserExtendedProperty to set</param>
        if(this.defined() && (username != undefined) && (propName != undefined) && (propValue != undefined) && this.isUserPersisted(username))
            this.handle.SetUserExtendedProperty(username, propName, propValue);
    },
    
    signInPasswordUser:function(username, password, optIn, userCredType)
    {
        /// <summary>Signs in a password user through a call to SetCredential(username, password, PPCRL_CREDTYPE_PASSWORD),
        ///  sets optIn state for user, and sets login type for user</summary>
        /// <param name="username">(string) Username to sign in</param>
        /// <param name="password">(string) Password of user (blank means saved password)</param>
        /// <param name="optIn">(bool) OptIn state of this user</param>
        /// <param name="userCredType">(string) Credential Type this user is using</param>
        if(this.defined() && (username != undefined))
        {
            if(password == undefined || null == password)
                password = '';
            this.handle.SetCredential(username, password, PPCRL_CREDTYPE_PASSWORD);
            this.setOptIn(username, (optIn) ? 'true' : 'false');
            if(userCredType != undefined)
                this.setProperty(k_wstrOutProp_LoginType, userCredType);
        }
    },
    
    signInEIDUser:function(username, thumb, pin, optIn, userCredType)
    {
        /// <summary>Signs in a EID (Smart Card/Certificate) user through a call to SetCredential(username, thumb, PPCRL_CREDTYPE_EID).
        /// if PIN is defined, calls SetCredential(username, pin, PPCRL_CREDTYPE_PIN). Also sets optIn state and login type</summary>
        /// <param name="username">(string) Username to sign in</param>
        /// <param name="thumb">(string) Certificate thumbprint to set</param>
        /// <param name="pin">[OPTIONAL] (string) If defined, sets PIN for this user</param>
        /// <param name="optIn">(bool) OptIn state of this user</param>
        /// <param name="userCredType">(string) Credential Types this user is using</param>
        if(this.defined() && (username != undefined))
        {
            this.handle.SetCredential(username, thumb, PPCRL_CREDTYPE_EID);
            if(pin != undefined && pin != null)
                this.handle.SetCredential(username, pin, PPCRL_CREDTYPE_PIN);
            else
                this.handle.SetCredential(username, '', PPCRL_CREDTYPE_PIN);
                
            this.setOptIn(username, (optIn) ? 'true' : 'false');
            if(userCredType != undefined)
                this.setProperty(k_wstrOutProp_LoginType, userCredType);
        }
    },
    
    signInUserObj:function(userObj)
    {
        /// <summary>Signs in and persists/removes (if necessary) user represented by a SavedUserObj</summary>
        /// <param name="userObj">(SavedUserObj) User to sign in and persist/remove (if necessary)</param>
        if(this.defined() && (userObj != undefined))
        {
            var userCredType = userObj.getCredType();
            if(userCredType == undefined)
                userCredType = WLID_LAST_USED_CRED_PASSWORD;

            switch(userCredType)
            {
                case WLID_LAST_USED_CRED_EID:
                case WLID_LAST_USED_CRED_FED_EID:
                    this.signInEIDUser(userObj.getUsername(), userObj.getProperty(SAVED_USER_PROP_CERT_THUMB), userObj.getPassword(), userObj.getSSO(), userCredType);
                    break;
                case WLID_LAST_USED_CRED_FED_PASSWORD:
                case WLID_LAST_USED_CRED_PASSWORD:
                    this.signInPasswordUser(userObj.getUsername(), userObj.getPassword(), userObj.getSSO(), userCredType);
                    break;
            }
            this.persistUserObj(userObj);
        }
    },
    persistCredential:function(username, type, flag)
    {
        this.handle.PersistCredential(username, type, flag );
    },
    persistAUser:function(username, rememberMe, wasRememberMe, savePwd, wasSavePwd, optIn, credType, userProperties)
    {
        /// <summary>Persists/Removes a user if necessary.  If user is persisted, persists Cred Type, OptIn State, and/or Certificate Thumbpring (for EID users)</summary>
        /// <param name="username">(string) Username of user to persist/remove</param>
        /// <param name="rememberMe">(bool) Current 'Remember Me' state</param>
        /// <param name="wasRememberMe">(bool) Original 'Remember Me' state</param>
        /// <param name="savePwd">(bool) Current 'Remember Password' state</param>
        /// <param name="wasSavePwd">(bool) Original 'Remember Password' state</param>
        /// <param name="optIn">(bool) Current OptIn state</param>
        /// <param name="credType">(string) Credential Type of this user</param>
        /// <param name="userProperties">(String[]) Map of extra user properties (currently users: SAVED_USER_PROP_CERT_THUMB)</param>
        if(this.defined() && (username != undefined) && (username.length>0))
        {
            // See if we need to clean this guy out
            if(!rememberMe )
            {
                this.handle.DeleteAccount(username);
            }
            if(rememberMe)
            {
                var cType = (savePwd) ? PPCRL_CREDTYPE_PASSWORD : PPCRL_CREDTYPE_MEMBERNAMEONLY;
                var optInString = (optIn) ? 'true' : 'false';
                
                this.handle.PersistCredential(username, cType, 0);
                
                //if((credType == undefined) || (credType.length == 0))
                //    credType = WLID_LAST_USED_CRED_PASSWORD;
                if (credType == WLID_LAST_USED_CRED_FED_PASSWORD || credType == WLID_LAST_USED_CRED_FED_EID || credType == WLID_LAST_USED_CRED_FED_WIAUTH)
                {
                    this.setExtendedProperty(username, WLID_USER_EX_PROP_LAST_USED_FED_TYPE, credType);
                    credType = WLID_LAST_USED_CRED_FEDERATION;
                }
                this.setExtendedProperty(username, WLID_USER_EX_PROP_LAST_USED_CRED, credType);                                
                this.setExtendedProperty(username, WLID_USER_EX_PROP_AUTO_SIGN_IN, optInString);
                if(credType == WLID_LAST_USED_CRED_EID || credType == WLID_LAST_USED_CRED_FED_EID)
                {
                    if(userProperties != undefined)
                    {
                        var certThumb = userProperties[SAVED_USER_PROP_CERT_THUMB];
                        if(certThumb != undefined)
                            this.setExtendedProperty(username, WLID_USER_EX_PROP_CERT_THUMB, certThumb);
                    }
                }
            }
        }
    },
    
    persistUserObj:function(userObj)
    {
        /// <summary>Persist/Remove the user represented by a SavedUserObj</summary>
        /// <param name="userObj">(SavedUserObj) User to persist/remove</param>
        if(this.defined() && (userObj != undefined) && (userObj.getUsername() != undefined))
        {
            var username = userObj.getUsername();
            var credType = userObj.getCredType();
            var doPersistUser = userObj.getRememberMe(false);
            var wasPersistUser = userObj.getRememberMe(true);
            var savedPassword = userObj.getSavePassword(false);
            var wasSavedPassword = userObj.getSavePassword(true);
            var doOptIn = userObj.getSSO();
            var userProps = userObj.getProperties();
            
            this.persistAUser(username, doPersistUser, wasPersistUser, savedPassword, wasSavedPassword, doOptIn, credType, userProps);
        }
    },
    
    getSavedUsers:function()
    {
        /// <summary>Retrieves an Array of SavedUserObj representing all Signed In and Persisted Users </summary>
        var toReturn = new Array();
        if(this.defined())
        {
            // GetUserList() returns a javascript expression string which creates the 'users' Array
            eval(this.handle.GetUserList(''));
            if(typeof users != 'undefined')
            {
                // users Element: [0] = Username | [1] = Password/MembernameOnly/SignedInOnly | [2] = User Image | [3] = SignedIn State
                for (var i = 0; i < users.length; i++ )
                {
                    if(users[i][0] != undefined)
                    {
                        var currUsername = users[i][0];
                        var newUser = new SavedUserObj(currUsername);

                        newUser.setIndex(i);
                        newUser.setNewPassword(false);

                        newUser.setRememberMe(false,true);
                        newUser.setSavePassword(false,true);

                        var val = users[i][1];
                        var isPersisted = ((val == PPCRL_USER_MEMBERNAME_ONLY) || (val == PPCRL_USER_SAVED_PASSWORD)) ? true : false;
                        newUser.setRememberMe(isPersisted, true);
                        newUser.setSavePassword((val == PPCRL_USER_SAVED_PASSWORD) ? true : false, true);

                        newUser.setImage(users[i][2]);
                        
                        newUser.setSignedIn((users[i][3]=='1') ? true : false);

                        if(isPersisted) 
                        {
                             // Get Cred Type & Get SSO (UserExtendedProperties)
                            var currCredType = this.getExtendedProperty(currUsername, WLID_USER_EX_PROP_LAST_USED_CRED);
                            if(currCredType == WLID_LAST_USED_CRED_UNKNOWN)
                            {
                                var identityType = this.getIdentityType(currUsername);
                                if (identityType == WLID_ACCOUNT_TYPE_FED)
                                {
                                    currCredType = WLID_LAST_USED_CRED_FED_PASSWORD;
                                }
                                // Default to WLID
                                else 
                                {
                                    currCredType = WLID_LAST_USED_CRED_PASSWORD;
                                }
                            }
                            else if (currCredType == WLID_LAST_USED_CRED_FEDERATION)
                            {
                                var currFedType = this.getExtendedProperty(currUsername, WLID_USER_EX_PROP_LAST_USED_FED_TYPE);    
                                // default to password type
                                currCredType = WLID_LAST_USED_CRED_FED_PASSWORD;
                                if (currFedType == WLID_LAST_USED_CRED_FED_EID ||
                                    currFedType == WLID_LAST_USED_CRED_FED_PASSWORD)
                                {
                                    currCredType = currFedType;
                                }
                            }

                            var currSSO = this.getExtendedProperty(currUsername, WLID_USER_EX_PROP_AUTO_SIGN_IN);
                            var boolSSO = false;
                            if((currSSO != undefined) && (currSSO.toLowerCase()=='true'))
                                boolSSO = true;
                                
                            if(currCredType == WLID_LAST_USED_CRED_EID || currCredType == WLID_LAST_USED_CRED_FED_EID)
                                newUser.setProperty(SAVED_USER_PROP_CERT_THUMB, this.getExtendedProperty(currUsername, WLID_USER_EX_PROP_CERT_THUMB));

                            newUser.setCredType(currCredType);
                            newUser.setSSO(boolSSO);      
                        }
                        else
                        {
                            newUser.setCredType(null);
                            newUser.setSSO(false);
                        }
                        
                        toReturn[i] = newUser;
                    }
                }
            }
        }
        // Sort Users ( 1) Signed In w/ Password  2) Signed In w/ MemberName  3) Signed In Non-Persisted  4) Persisted w/ Password  5) Persisted)
        toReturn.sort(SavedUserObj.compare);
        return toReturn;
    },
    getErrMsg:function(errCode )
    {
        if ( this.defined() )
        {
            return this.handle.GetErrMsg(errCode);
        }
    },
    getErrType:function(errCode )
    {
        if ( this.defined() )
        {
            return this.handle.GetErrType(errCode);
        }
    },    
    getActiveUsers:function()
    {
        /// <summary>Retrieves an Array of SavedUserObj representing all Signed In and Persisted Users </summary>
        var toReturn = new Array();
        if(this.defined())
        {
            // GetUserList() returns a javascript expression string which creates the 'users' Array
            eval(this.handle.GetUserList('', true));
            if(typeof users != 'undefined')
            {
                // users Element: [0] = Username | [1] = Password/MembernameOnly/SignedInOnly | [2] = User Image | [3] = SignedIn State
                for (var i = 0; i < users.length; i++ )
                {
                    if(users[i][0] != undefined)
                    {
                        var currUsername = users[i][0];
                        var newUser = new SavedUserObj(currUsername);

                        newUser.setIndex(i);
                        newUser.setNewPassword(false);

                        newUser.setRememberMe(false,true);
                        newUser.setSavePassword(false,true);

                        var val = users[i][1];
                        var isPersisted = ((val == PPCRL_USER_MEMBERNAME_ONLY) || (val == PPCRL_USER_SAVED_PASSWORD)) ? true : false;
                        newUser.setRememberMe(isPersisted, true);
                        newUser.setSavePassword((val == PPCRL_USER_SAVED_PASSWORD) ? true : false, true);

                        newUser.setImage(users[i][2]);
                        newUser.setSignedIn( true );

                        toReturn[i] = newUser;
                    }
                }
            }
        }
        // Sort Users ( 1) Signed In w/ Password  2) Signed In w/ MemberName  3) Signed In Non-Persisted  4) Persisted w/ Password  5) Persisted)
        toReturn.sort(SavedUserObj.compare);
        return toReturn;
    }    ,
    isRtlTest:function()
    {
        return x_wstrUIOptionValueTRUE == this.getProperty( k_wstrInProp_RTLTestEnabled );
    },
    hasDummyCertOnly:function(aCertList)
    {
        if ( null == aCertList || undefined == aCertList )
            return true;

        if ( aCertList.length < 1)
            return true;

        if ( aCertList[0].Value == '__dummy__' )
            return true;

        return false;                           
    },
    setTestHook_Error:function(errorCode, localobj)
    {
        if ( x_wstrUIOptionValueTRUE != this.handle.GetInputProp( k_wstrInProp_TestHookEnabled  ) )
            return;
            
        var _th_ErrorCode = "__TestHook_ErrorCode__";
        var _th_ErrorMsg = "__TestHook_ErrorMsg__";
        var _th_ErrorType = "__TestHook_ErrorType__";

        var testhooktype = "span";
        
        if ( null == errorCode || undefined == errorCode )
            return;
        if ( null == localobj || undefined == localobj )
            return;

        var holder = document.getElementById("TestHook");
        if ( null == holder || undefined == holder )
            return;
            
        var errorMsg = localobj.getErrMsg( errorCode );
        var errorType = localobj.getErrType( errorCode );

        // set err code
        var th_errcode = document.getElementById( _th_ErrorCode );
        if ( null == th_errcode || undefined == th_errcode )
        {
            th_errcode = document.createElement(testhooktype);
            th_errcode.setAttribute("id", _th_ErrorCode); 
            holder.appendChild( th_errcode );
        }
        th_errcode.innerText =  errorCode ;

        // set error type
        var th_errtype = document.getElementById( _th_ErrorType );
        if ( null == th_errtype || undefined == th_errtype )
        {
            th_errtype = document.createElement(testhooktype);
            th_errtype.setAttribute("id", _th_ErrorType); 
            holder.appendChild( th_errtype );
        }
        th_errtype.innerText = errorType;
        
        // set error msg
        var th_errmsg = document.getElementById( _th_ErrorMsg );
        if ( null == th_errmsg || undefined == th_errmsg )
        {
            th_errmsg = document.createElement(testhooktype);
            th_errmsg.setAttribute("id", _th_ErrorMsg); 
            holder.appendChild( th_errmsg );
        }
        th_errmsg.innerText = errorMsg;
        
    }
}

CobrandingObj = function()
{
    /// <summary>Constructor for CobrandingObj which contains cobranding data: (UserImage, Text, Background Color, Link Color, Tile Background Color, Tile Border Color)
    /// Defaults: [Image: ''] | [Text: 'Text'] | [BGColor: '#ffffff'] | [LinkColor: 'Blue'] | [TileBGColor: '#ffffff'] | [TileBorderColor: '#ffffff']</summary>
    this.m_strImage = '';
    this.m_strHeaderBgImg = '';
    this.m_strText = 'Text';
    this.m_strSignupText = '';  // "Don't have a Windows Live ID?"
    this.m_strBGColor = '#ffffff';
    this.m_strLinkColor = 'Blue';
    this.m_strTileBGColor = '#e1f3fc';
    this.m_strTileBorderColor = '#bae4fc';
    this.m_strFieldBdColor = ''; // see global_default.css
    this.m_strCheckboxLbColor = ''; 
    this.m_strBtTxtColor = '';     // http://www.live.com for example
    this.m_strTileLbColor = '';     // example@hotmail.com for example   
    this.m_strSignupUrl = ''; // http://www.live.com for example
    this.m_strAppName = 'Unknown';
}

CobrandingObj.prototype =
{
    getImage:function()
    {
        /// <summary>Retrieves logo image path for this Cobranding data</summary>
        return this.m_strImage;
    },
    
    setImage:function(newImage)
    {
        /// <summary>Sets image path for this Cobranding data</summary>
        /// <param name="newImage">(string) Image path to set</param>
        if(newImage != undefined)
            this.m_strImage = newImage;
    },
    getBgImage:function()
    {
        return this.m_strHeaderBgImg;
    },
    setBgImage:function(newImage)
    {
        if(newImage != undefined && newImage != null)
            this.m_strHeaderBgImg = newImage;
    },
    getText:function()
    {
        /// <summary>Retrieves Cobranding Text</summary>
        return this.m_strText;
    },
    
    setText:function(newText)
    {
        /// <summary>Sets text for this Cobranding data</summary>
        /// <param name="newText">(string) Text to set</param>
        if(newText != undefined)
            this.m_strText = newText;
    },

    getAppName:function()
    {
        /// <summary>Retrieves App Name</summary>
        return this.m_strAppName;
    },
    
    setAppName:function(newText)
    {
        /// <summary>Sets text for this Cobranding data</summary>
        /// <param name="newText">(string) Text to set</param>
        if(newText != undefined)
            this.m_strAppName = newText;
    },
    
    getBGColor:function()
    {
        /// <summary>Retrieves Background Color</summary>
        return this.m_strBGColor;
    },
    
    setBGColor:function(newColor)
    {
        /// <summary>Sets Background Color for this Cobranding data</summary>
        /// <param name="newColor">(string) Background Color to set</param>
        if(newColor != undefined)
            this.m_strBGColor = newColor;
    },
    
    getLinkColor:function()
    {
        /// <summary>Retrieves Cobranding Link Color</summary>
        return this.m_strLinkColor;
    },
    
    setLinkColor:function(newColor)
    {
        /// <summary>Sets Link Color for this Cobranding data</summary>
        /// <param name="newColor">(string) Link Color to set</param>
        if(newColor != undefined)
            this.m_strLinkColor = newColor;
    },
    
    getTileBGColor:function()
    {
        /// <summary>Retrieves Cobranding Active Tile Background Color</summary>
        return this.m_strTileBGColor;
    },
    
    setTileBGColor:function(newColor)
    {
        /// <summary>Sets Active Tile Bakground Color for this Cobranding data</summary>
        /// <param name="newColor">(string) Background Color to set</param>
        if(newColor != undefined)
            this.m_strTileBGColor = newColor;
    },

    getTileLBColor:function()
    {
        /// <summary>Retrieves Cobranding Active Tile label Color</summary>
        return this.m_strTileLbColor;
    },
    
    setTileLBColor:function(newColor)
    {
        /// <summary>Sets Active Tile label Color for this Cobranding data</summary>
        /// <param name="newColor">(string) label Color to set</param>
        if(newColor != undefined)
            this.m_strTileLbColor = newColor;
    },
    
    getTileBorderColor:function()
    {
        /// <summary>Retrieves Cobranding Active Tile Border Color</summary>
        return this.m_strTileBorderColor;
    },
    
    setTileBorderColor:function(newColor)
    {
        /// <summary>Sets Active Tile Border Color for this Cobranding data</summary>
        /// <param name="newColor">(string) Border Color to set</param>
        if(newColor != undefined)
            this.m_strTileBorderColor = newColor;
    }
}

