﻿/// <reference path="jquery-1.4.4.vsdoc.js"/>
/// <reference path="dsutil.js"/>
/// <reference path="parseXml.js"/>
/// <reference path="xml2json.js"/>
/// <reference path="xmlWriter.js"/>
/// <reference path="tools.js"/>
/// <reference path="layout.js"/>
/// <reference path="log.js"/>

auth = (function () {

    var firstTimeLogin = true;
    var loginCallback = [];
    var greeningConnection = null;
    var greeningPassport = null;
    var gettingPassport = [];
    var sessionID = "";
    var logoutCallBack = [];
    var onloginCallBack = [];
    var connectionPool = {};
    var currentSessionID = "";
    var currentUserAccount = "";
    var openingWindow = null;

    var status = "unknow";
    var statusChangedCallBack = [];
    function statusChanged() {
        for (var i = 0; i < statusChangedCallBack.length; i++) {
            statusChangedCallBack[i](status);
        }
    }

    var justAlived = false;
    function resetAlive() {
        justAlived = false;
    }
    function aliveConnection(callback) {
        if (!justAlived) {
            justAlived = true;
            setTimeout(resetAlive, 900000);
            try {
                if (greeningConnection && greeningConnection.send) {
                    greeningConnection.send({//讓greeningConnection的SessionID展期
                        service: 'DS.Base.Connect',
                        body: {},
                        result: function (resp, errorInfo, XMLHttpRequest) {
                            if (errorInfo == null) {
                                if (callback) callback();
                            }
                            else {
                                greeningPassport = null;
                                for (var i in connectionPool) {
                                    connectionPool[i].send({ service: 'DS.Base.InvalidateSession' });
                                }
                                if (callback) callback();
                            }
                        }
                    });
                }
                else {
                    for (var i in connectionPool) {
                        connectionPool[i].send({ service: 'DS.Base.InvalidateSession' });
                    }
                    if (callback) callback();
                }
            }
            catch (ex) {
                greeningPassport = null;
                for (var i in connectionPool) {
                    connectionPool[i].send({ service: 'DS.Base.InvalidateSession' });
                }
                if (callback) callback();
            }
        }
        else {
            if (callback) callback();
        }
    }

    function requestLogin(newStatus, callback) {
        if (callback) {
            loginCallback.push(callback);
        }
        if (status != newStatus) {
            status = newStatus;
            statusChanged();
        }
    }
    function login(callback) {
        if (callback) {
            loginCallback.push(callback);
        }
        if ((!!greeningConnection) && greeningConnection.send) {
            greeningConnection.reConnect(sessionID);
        }
        else {
            greeningConnection = dsutil.creatConnection('http://web.ischool.com.tw/service/shared/user', sessionID);
            greeningConnection.OnLoginError(function () {
                requestLogin("unknow");
            });
        }
        greeningConnection.send({
            service: 'DS.Base.Connect',
            autoRetry: true,
            result: function (resp, errorInfo, XMLHttpRequest) {
                if (errorInfo == null) {
                    //#region 設定rootAlive
                    justAlived = true;
                    setTimeout(resetAlive, 900000);
                    //#endregion
                    //#region 整理UserInfo
                    var userInfo = greeningConnection.getUserInfo();
                    if (userInfo && userInfo.Property) {
                        for (var i = 0; i < userInfo.Property.length; i++) {
                            userInfo[userInfo.Property[i].Name] = userInfo.Property[i]['@text'];
                        }
                    }
                    //#endregion
                    //#region 如果是重新登入但登入的使用者不同，幹掉原使用者的暫存狀態
                    if (currentUserAccount && (currentUserAccount != userInfo.UserName)) {
                        if (currentSessionID) {
                            dsutil.creatConnection('http://web.ischool.com.tw/service/shared/user', currentSessionID).send({ service: 'DS.Base.InvalidateSession' });
                        }
                        for (var i in connectionPool) {
                            connectionPool[i].send({ service: 'DS.Base.InvalidateSession' });
                        }
                        loginCallback = [];
                        greeningPassport = null;
                        gettingPassport = [];
                        connectionPool = {};
                        for (var i = 0; i < logoutCallBack.length; i++) {
                            logoutCallBack[i]();
                        }
                    }
                    //#endregion
                    //#region 處理loginCallback
                    var cacheloginCallback = loginCallback;
                    loginCallback = [];
                    for (var i = cacheloginCallback.length - 1; i >= 0; i--) {
                        cacheloginCallback[i]();
                    };
                    //#endregion
                    //#region 設定登入者身份及狀態
                    if (userInfo.UserName != currentUserAccount) {
                        for (var i = 0; i < onloginCallBack.length; i++) {
                            onloginCallBack[i]();
                        }
                    }
                    currentSessionID = sessionID;
                    currentUserAccount = userInfo.UserName;
                    if (status != "authorized") {
                        status = "authorized";
                        statusChanged();
                    }
                    //#endregion
                }
                else {
                    requestLogin("unknow");
                }
            }
        });
    }

    function getPassportThenCallBack() {
        greeningConnection.send({
            service: 'DS.Base.GetPassportToken',
            body: {},
            autoRetry: true,
            result: function (resp, errorInfo, XMLHttpRequest) {
                if (resp) {
                    greeningPassport = {
                        '@': ['type'],
                        Type: 'Passport',
                        DSAPassport: resp.DSAPassport
                    };
                    var cachegettingPassport = gettingPassport;
                    gettingPassport = [];
                    for (var i = cachegettingPassport.length - 1; i >= 0; i--) {
                        cachegettingPassport[i]();
                    };
                }
                else {
                    if (errorInfo && errorInfo.dsaError) {
                        if (errorInfo.dsaError.status == '511') {
                            requestLogin("authenticationExpired", getPassportThenCallBack);
                        }
                        else
                            alert('unexcept error on GetPassportToken and errorInfo.dsaError.status=' + errorInfo.dsaError.status);
                        //                            if (errorInfo.dsaError.status == '512') {
                        //                                //應在此判斷當dsaError.status == '511'(SessionExpire)時進行重登後再重試
                        //                                //alert('dsa error on GetPassportToken' + errorInfo.dsaError.status + ' ' + errorInfo.dsaError.message);
                        //                                callLoginWithCallBack(getPassportThenCallBack);
                        //                            } else {
                        //                                alert('dsa error on GetPassportToken' + errorInfo.dsaError.status + ' ' + errorInfo.dsaError.message);
                        //                            }
                    }
                    else {
                        alert('unexcept error on GetPassportToken and no errorInfo!!');
                    }
                }
            }
        });
    }

    function getPassport(callback) {
        if (callback) {
            gettingPassport.push(callback);
        }
        else {
            gettingPassport.push(function () { });
        }
        if (greeningConnection && greeningConnection.send) {
            if (gettingPassport.length == 1) {
                getPassportThenCallBack();
            }
        }
        else {
            loginCallback.push(getPassportThenCallBack);
        }
    }

    function getConnectionProxy(accesspoint, account, password) {
        var reqlist = [];
        var usePassport = !account;
        var conn = {};
        var readyCallBackQueue = [];
        function sendAllReq() {
            if (conn.send) {
                var cachelist = reqlist;
                reqlist = [];
                for (var i = cachelist.length - 1; i >= 0; i--) {
                    sendReq(cachelist[i]);
                };
            }
        }
        function sendReq(req) {
            var proxyReq = {};
            proxyReq.service = req.service || '';
            proxyReq.body = req.body || {};
            proxyReq.autoRetry = req.autoRetry || false;
            proxyReq.result = function (resp, errorInfo, XMLHttpRequest) {// errorInfo=null||{'loginError': null,'dsaError': null,'networkError': null,'ajaxException': null}
                if (resp || resp === "") {
                    req.title = "Service：" + req.service;
                    req.response = resp;
                    req.errorInfo = errorInfo;
                    req.accessPoint = conn.getAccessPoint();
                    req.ueerInfo = conn.getUserInfo();
                    log.logRequest(req);
                    if (req.result) {
                        req.result(resp, errorInfo, XMLHttpRequest);
                    }
                }
                else {
                    if (errorInfo.loginError !== null && errorInfo.loginError.statusCode == '512') {//如果是正在登入且發生Passport過期(conn的onLoginError會自動進行更換passport再重登)
                        getPassport(function () {
                            conn.send(proxyReq);
                        });
                    }
                    else
                        if (errorInfo.dsaError !== null && errorInfo.dsaError.status == '511') {//連到這個accessPoint的sessionID過期
                            conn.reConnect(greeningPassport); //直接用passport重連，如果passport也過期會進入onLoginError自動進行更換passport再重登
                            conn.send(proxyReq);
                        }
                        else {
                            req.title = "Service：" + req.service;
                            req.response = resp;
                            req.errorInfo = errorInfo;
                            req.accessPoint = conn.getAccessPoint();
                            req.ueerInfo = conn.getUserInfo();
                            log.logRequest(req);
                            if (req.result) {
                                req.result(resp, errorInfo, XMLHttpRequest);
                            }
                        }
                }
            };
            aliveConnection(function () {
                conn.send(proxyReq);
            });
        }
        var connectionProxy = {
            send: function (req) {
                reqlist.push(req);
                sendAllReq();
            },
            getUserInfo: function () {
                return conn.getUserInfo ? conn.getUserInfo() : "";
            },
            getAccessPoint: function () {
                return conn.getAccessPoint ? conn.getAccessPoint() : "";
            },
            ready: function (fn) {
                if (conn.ready) {
                    conn.ready(function () {
                        fn();
                    });
                }
                else {
                    readyCallBackQueue.push(fn);
                }
            }
        };
        function onLoginError(loginError) {
            if (loginError.statusCode == '512') {
                getPassport(function () {
                    conn.reConnect(greeningPassport);
                });
            }
            else {
                log.logRequest({
                    title: "Login Faild!!!",
                    accesspoint: accesspoint,
                    loginError: loginError
                });
            }
        };
        if (!usePassport) {
            if (password)
                conn = dsutil.creatConnection(accesspoint, account, password);
            else
                conn = dsutil.creatConnection(accesspoint, account);
        }
        else {
            if (connectionPool[accesspoint] === undefined) {
                //conn=XXXX
                if (greeningPassport == null) {
                    getPassport(function () {//只有在最開始連passport都是null的情況下會出現conn={}的空窗期(直到getPassport的callBack)
                        if (connectionPool[accesspoint] === undefined) {
                            log.logRequest({
                                title: "Connect",
                                accesspoint: accesspoint
                            });
                            conn = dsutil.creatConnection(accesspoint, greeningPassport);
                            conn.OnLoginError(onLoginError);
                            connectionPool[accesspoint] = conn;
                        }
                        else {
                            conn = connectionPool[accesspoint];
                        }
                        $(readyCallBackQueue).each(function () {
                            var fn = this;
                            conn.ready(function () {
                                fn();
                            });
                        });
                        readyCallBackQueue = [];
                        sendAllReq();
                    });
                }
                else {
                    log.logRequest({
                        title: "Connect",
                        accesspoint: accesspoint
                    });
                    conn = dsutil.creatConnection(accesspoint, greeningPassport);
                    conn.OnLoginError(onLoginError);
                    connectionPool[accesspoint] = conn;
                }
            }
            else {
                conn = connectionPool[accesspoint];
            }
        }
        return connectionProxy;
    }

    var result = {
        connectTo: function (accesspoint, account, password) { return getConnectionProxy(accesspoint, account, password); },
        login: function (sid) {
            sessionID = sid || "";
            login();
        },
        logout: function () {
            greeningConnection.send({ service: 'DS.Base.InvalidateSession' });
            for (var i in connectionPool) {
                connectionPool[i].send({ service: 'DS.Base.InvalidateSession' });
            }
            loginCallback = [];
            greeningPassport = null;
            gettingPassport = [];
            connectionPool = {};
            currentSessionID = "";
            currentUserAccount = "";
            if (status != "unauthorized") {
                status = "unauthorized";
                statusChanged();
            }
            for (var i = 0; i < logoutCallBack.length; i++) {
                logoutCallBack[i]();
            }
        },
        checkCurrentUser: function (account) {
            return (currentUserAccount && (currentUserAccount != account));
        },
        onLogout: function (fn) {
            if (fn) {
                logoutCallBack.push(fn);
            }
        },
        onLogin: function (fn) {
            if (fn) {
                onloginCallBack.push(fn);
            }
        },
        getStatus: function () {
            return status;
        },
        onStatusChanged: function (fn) {
            if (fn) {
                statusChangedCallBack.push(fn);
            }
        }
    };

    return result;
} ());

