﻿/*此脚本封装了访问Windows Live Messenger服务API*/

/*定义一个对象，处理用户的登录，发送、接收消息，和联系人的获取和增删*/
/**
 * config - 配置对象，参数如下
 * SignInDiv - SignIn控件所在div元素的id
 * Privacy - 私有政策页面
 * Channel - 回调页面
 * Language - 语言
 *
 * SignInCompleted - 当登录完成时产生此事件
 * SignOutCompleted - 当注销完成时产生此事件
 * AddContactCompleted - 当增加联系人完成时产生此事件
 * UserPropertyChanged - 当用户属性改变时产生此事件
 * OnLineCollectionChanged - 在线用户集合发生变化时产生此事件
 * OffLineCollectionChanged - 离线用户集合发生变化时产生此事件
 * UserPresencePropertyChanged - 用户在线状态变化时产生此事件
 * ConversationCollectionChanged - 会话集合变化时产生此事件
 * ReceivedMessage - 接收到消息后的处理事件
 * SendMessageFailed - 当发送消息失败后产生此事件 
 *  
 **/
function Messenger(config)
{

    /*===================================*/
    /**                 私有属性        **/
    /*===================================*/

    var _SignIn;    //登录控件
    var _User;      //用户
    var _Status;    //登录状态
    var _Conv;      //当前会话

    /*===================================*/
    /**      事件(微软类库事件)         **/
    /*===================================*/

    var _SignInCompleted;                       //当登录完成时产生此事件
    var _SignOutCompleted;                      //当注销完成时产生此事件
    var _AddContactCompleted;                   //当增加联系人完成时产生此事件
    var _UserPropertyChanged;                   //当用户属性改变时产生此事件
    var _OnLineCollectionChanged;               //在线用户集合发生变化时产生此事件
    var _OffLineCollectionChanged;              //离线用户集合发生变化时产生此事件
    var _UserPresencePropertyChanged;           //用户在线状态变化时产生此事件
    var _ConversationCollectionChanged;         //会话集合变化时产生此事件
    var _ContactPresencePropertyChanged;        //联系人在线属性变化时产生此事件
    var _ReceivedMessage;                       //当接收到消息后产生此事件
    var _SendMessageFailed;                     //发送消息失败后产生此事件

    var _SignInDiv;
    var _Privacy;
    var _Channel;
    var _Language;

    /*===================================*/
    /**       初始化参数                **/
    /*===================================*/

    _SignInCompleted = config.SignInCompleted;
    _SignOutCompleted = config.SignOutCompleted;
    _AddContactCompleted = config.AddContactCompleted;
    _UserPropertyChanged = config.UserPropertyChanged;
    _OnLineCollectionChanged = config.OnLineCollectionChanged;
    _OffLineCollectionChanged = config.OffLineCollectionChanged;
    _UserPresencePropertyChanged = config.UserPresencePropertyChanged;
    _ConversationCollectionChanged = config.ConversationCollectionChanged;
    _ContactPresencePropertyChanged = config.ContactPresencePropertyChanged;
    _ReceivedMessage = config.ReceivedMessage;
    _SendMessageFailed = config.SendMessageFailed;

    _SignInDiv = config.SignInDiv;
    _Privacy = config.Privacy;
    _Channel = config.Channel;
    _Language = config.Language;

    /*===================================*/
    /**            公开属性GET          **/
    /*===================================*/
    
    
    /*===================================*/
    /**              公开方法           **/
    /*===================================*/
    
    //签入方法
    this.SignIn = function()
    {
        _SignIn = new Microsoft.Live.Messenger.UI.SignInControl(_SignInDiv,_Privacy,_Channel,_Language);
        _SignIn.add_authenticationCompleted(authenticationCompleted);
    }

    //签出方法，此方法才会触发SignOutCompleted事件。
    this.SignOut = function() {
        if (_User){
            _User.signOut(Microsoft.Live.Messenger.SignOutLocations.all);
        }
    }

    //设置用户状态
    this.SetUserStatus = function(index)
    {
        var presenceStatus = [ Microsoft.Live.Messenger.PresenceStatus.appearOffline,
        Microsoft.Live.Messenger.PresenceStatus.away,
        Microsoft.Live.Messenger.PresenceStatus.beRightBack,
        Microsoft.Live.Messenger.PresenceStatus.busy,
        Microsoft.Live.Messenger.PresenceStatus.idle,
        Microsoft.Live.Messenger.PresenceStatus.inACall,
        Microsoft.Live.Messenger.PresenceStatus.online,
        Microsoft.Live.Messenger.PresenceStatus.outToLunch ];

        if (_User.get_presence().get_status() !== Microsoft.Live.Messenger.PresenceStatus.offline)
        {
            _User.get_presence().set_status(presenceStatus[index]);
        }
    }
    
    //设置个人信息
    //message - 个人信息
    this.SetPersonalMessage = function(message)
    {
        var messageText = message;
        messageText = messageText.replace(/</g, "").replace(/>/g, "");
        if (_User) {
            _User.get_presence().set_personalMessage(messageText);
        }
    }
   
    //设置显示名称
    this.SetDisplayName = function(displayname) 
    {
        var display = displayname.replace(/</g,"").replace(/>/g,"");
        if (_User)
        {
            _User.get_presence().set_displayName(display);
        }
    }

    //增加一个新的联系人
    //id - 新联系人的email地址
    //message - 发送给联系人的邀请信息
    this.AddNewContact = function(id,message)
    {
        var address = id;
        if (_User)
            _User.addContact(address, message, null);
    }

    //删除一个联系人
    //id - 要删除的联系人的email
    this.RemoveExistingContact = function(id) 
    {
        var address = id;
        var contacts = _User.get_contacts();   //获取全部联系人
        var contact;

        if (_User.get_presence().get_status() !== Microsoft.Live.Messenger.PresenceStatus.offline)
        {
            contact = contacts.find(address, Microsoft.Live.Messenger.IMAddressType.windowsLive);
            if (contact)
            {
                contacts.remove(contact);
            }
        }
    }

    //发送消息
    //message - 要发送的消息
    //_Conv - 当前会话，内部数据
    this.SendMsg = function(message) {
        var messageText = message;
        var message = new Microsoft.Live.Messenger.TextMessage(messageText, null);
        if (_User) {
            if (_Conv)
            {
                _Conv.sendMessage(message, null);
            }
        }
    }

    //切换会话
    //id - 会话Index
    //_Conv - 内部数据，当前会话
    //返回 - Microsoft.Live.Messenger.Conversation对象
    this.SwitchConv = function(id)
    {
        //获得指定id的会话
        var c = _User.get_conversations().get_item(id);
        var ci = new Object();

        if (c)
        {
            if (_Conv) {
                //删除消息接收事件的处理
                _Conv.remove_messageReceived(receivedMessage);
                //删除消息发送失败事件的处理
                _Conv.remove_sendMessageFailed(sendMessageFailed);
            }
            _Conv = c;
            
            //增加对消息接收事件的处理，处理函数为recvmsg
            _Conv.add_messageReceived(receivedMessage);
            //增加对发送消息失败的处理
            _Conv.add_sendMessageFailed(sendMessageFailed);
        }
        
        ci = addConvInfo(ci,c,id);
        return ci;
    }

    //关闭会话
    //id - 会话Index
    this.CloseConv = function(id)
    {
        var c = _User.get_conversations().get_item(id);
        c.close();
    }
    
    //创建会话
    //email - Windows Live ID
    this.CreateConv = function(email)
    {
        var c ; //联系人
        var conv;   //会话
        var contacts = _User.get_contacts();

        c = contacts.find(email,Microsoft.Live.Messenger.IMAddressType.windowsLive);

        if (c)
        {
            conv = _User.get_conversations().create(c.get_currentAddress());  //创建新的会话
        }
    }

    /*===================================*/
    /**            私有方法             **/
    /*===================================*/

    //内部认证完成事件的处理
    var authenticationCompleted = function(sender,e)
    {
        //获取登录状态
        _Status = e.get_status();

        _User = new Microsoft.Live.Messenger.User(e.get_identity());

        //调用内部处理函数处理用户的相关事件
        _User.add_signInCompleted(signInCompleted);
        _User.add_signOutCompleted(signOutCompleted);
        _User.add_addContactCompleted(addContactCompleted);

        _User.signIn(null);

        //处理用户属性改变事件
        _User.add_propertyChanged(userPropertyChanged);
    }

    //内部处理注销完成的方法
    var signOutCompleted = function(sender,e)
    {
        if (_SignOutCompleted)
        {
            sender = addUserInfo(sender);
            _SignOutCompleted(sender,e);
        }
    }

    //内部处理添加联系人完毕的方法
    var addContactCompleted = function(sender,e)
    {
        if (_AddContactCompleted)
        {
            sender = addUserInfo(sender);
            _AddContactCompleted(sender,e);
        }
    }

    //内部处理用户属性改变的方法
    var userPropertyChanged = function(sender,e)
    {
        if (_UserPropertyChanged)
        {
            sender = addUserInfo(sender);
            _UserPropertyChanged(sender,e);
        }
    }

    //内部处理登录完成时的事件
    var signInCompleted = function(sender,e)
    {
        if (e.get_resultCode() === Microsoft.Live.Messenger.SignInResultCode.success) 
        {
            //用户在线状态变化事件
            _User.get_presence().add_propertyChanged(userPresencePropertyChanged);

            //获取联系人
            _contactCollection = _User.get_contacts();

            //处理会话集合变化事件。
            _User.get_conversations().add_collectionChanged(conversationCollectionChanged);

            // Set event handlers to online and offline contacts collections.
            _User.get_onlineContacts().add_collectionChanged(onLineCollectionChanged);
            _User.get_offlineContacts().add_collectionChanged(offLineCollectionChanged);

            onLineCollectionChanged();
            offLineCollectionChanged(); 
        }

        //调用外部登录完成处理函数
        if (_SignInCompleted)
        {
            sender = addUserInfo(sender);
            _SignInCompleted(sender,e);
        }
    }
    
    //内部处理用户在线状态变化的事件
    var userPresencePropertyChanged = function(sender,e)
    {
        if (_UserPresencePropertyChanged)
        {
            sender = addUserInfo(sender);
            _UserPresencePropertyChanged(sender,e);
        }
    }

    //内部处理会话集合变化的事件
    var conversationCollectionChanged = function(sender,e)
    {
        var item = 0;
        var enum1 = _User.get_conversations().getEnumerator();
        var c;                     //当前会话
        var convs = new Array();   //会话数组
        var conv;

        //循环提取每个会话到convs数组中
        while (enum1.moveNext())
        {
            c = enum1.get_current();

            if (c.get_closed())
            {
                continue;//会话已关闭不做任何处理
            }

            //讲会话信息保存到一个对象中
            conv = new Object();
            conv = addConvInfo(conv,c,item);

            convs.push(conv);

            item++;
        }

        //调用用户自定义的事件处理函数，将保存所有会话信息的对象传给用户的处理程序
        if (_ConversationCollectionChanged)
        {
            e["Convs"] = convs;//设置会话数组
            sender = addUserInfo(sender);
            _ConversationCollectionChanged(sender,e);
        }
    }
    
    //内部处理在线人员变化的事件
    var onLineCollectionChanged = function(sender,e)
    {
        var online = _User.get_onlineContacts().getEnumerator();
        var onlines = new Array(); //在线联系人数组
        var c;   //Contact
        var ci;  //在线的联系人

        while(online.moveNext())
        {
            c = online.get_current();
            
            ci = new Object();
            ci = addContactInfo(ci,c);
            onlines.push(ci);

            //联系人属性变化时处理事件
            contactPresencePropertyChangedEvent(c);
        }

        if (_OnLineCollectionChanged)
        {
            sender = addUserInfo(sender);
            _OnLineCollectionChanged(sender,onlines);
        }
    }

    //内部处理离线人员变化的事件
    var offLineCollectionChanged = function(sender,e)
    {
        var offline = _User.get_offlineContacts().getEnumerator();
        var offlines = new Array(); //在线联系人数组
        var c;
        var ci;  //联系人信息

        while(offline.moveNext())
        {
            c = offline.get_current();    //获得当前的离线联系人
            ci = new Object();             //
            ci = addContactInfo(ci,c);   //添加联系人信息
            offlines.push(ci);
            
            //联系人属性变化时处理事件
            contactPresencePropertyChangedEvent(c);
        }

        if (_OffLineCollectionChanged)
        {
            sender = addUserInfo(sender);
            _OffLineCollectionChanged(sender,offlines);
        }
    }

    //内部的联系人属性变化时的处理事件
    //c - Contact
    var contactPresencePropertyChangedEvent = function(c)
    {
        var sender = new Object();

        c.get_currentAddress().get_presence().add_propertyChanged(function(sender,e){
            if (_ContactPresencePropertyChanged)
            {
                //设置ContactInfo的属性
                e = addContactInfo(e,c);
				//设置用户shuxing属性
                sender = addUserInfo(sender);
                
                _ContactPresencePropertyChanged(sender,e);
            }
        });
    }

    //内部接收消息的处理事件
    var receivedMessage = function(sender,e)
    {
        e["Message"] = e.get_message().get_text();
        e["SenderAddress"] = e.get_message().get_sender().get_address();
        e["SenderPresenceDisplayName"] = e.get_message().get_sender().get_presence().get_displayName();
        e["SenderPresencePersonalMessage"] = e.get_message().get_sender().get_presence().get_personalMessage();
        e["SenderPresenceStatus"] = e.get_message().get_sender().get_presence().get_status();
        e["Timestamp"] = e.get_message().get_timestamp();

        if (_ReceivedMessage)
        {
            sender = addUserInfo(sender);
            _ReceivedMessage(sender,e);
        }
    }

    //内部处理消息发送失败的函数
    var sendMessageFailed = function(sender,e)
    {
        if (_SendMessageFailed)
        {
            e["Message"] = e.get_message().get_text();
            e["ResultCode"] = e.get_resultCode();
            e["UserState"] = e.get_userState();
            e["SenderAddress"] = e.get_message().get_sender().get_address();
            e["SenderPresenceDisplayName"] = e.get_message().get_sender().get_presence().get_displayName();
            e["SenderPresencePersonalMessage"] = e.get_message().get_sender().get_presence().get_personalMessage();
            e["SenderPresenceStatus"] = e.get_message().get_sender().get_presence().get_status();
            e["Timestamp"] = e.get_message().get_timestamp();

            sender = addUserInfo(sender);
            _SendMessageFailed(sender,e);
        }
    }

    //内部函数，给一个对象添加用户相关的属性信息
    //obj - 要添加属性信息的对象
    //      处理完后的对象包含五个属性：UserStatus,UserAddress,UserPersonalMessage,UserPresenceStatus
    var addUserInfo = function(obj)
    {
        if (!obj)
        {
            obj = new Object();
        }

        obj["UserStatus"] = Enum.toString(Microsoft.Live.Messenger.UserStatus,_User.get_status());
        obj["UserAddress"] = _User.get_address().get_address();
        obj["UserDisplayName"] = _User.get_presence().get_displayName();
        obj["UserPersonalMessage"] = _User.get_presence().get_personalMessage();
        obj["UserPresenceStatus"] =  Enum.toString(Microsoft.Live.Messenger.PresenceStatus, _User.get_presence().get_status());

        return obj;
    }

    //内部函数，给一个对象动态添加联系人信息
    //obj - 要添加信息的对象
    //c - 要添加的联系人
    //      处理完后的obj包含四个属性：DisplayName,DisplayEmail,PresenceStatus,PersonalMessage
    var addContactInfo = function(obj,c)
    {
        obj["DisplayName"] = c.get_currentAddress().get_presence().get_displayName();
        obj["DisplayEmail"] = c.get_currentAddress().get_address();
        obj["PresenceStatus"] = Enum.toString(Microsoft.Live.Messenger.PresenceStatus,c.get_currentAddress().get_presence().get_status());
        obj["PersonalMessage"] = c.get_currentAddress().get_presence().get_personalMessage();

        return obj;
    }

    //设置会话，将一个对象附加上会话的信息
    //obj - 对象
    //conv - Conversation
    //index - conv在当前用户的会话集合中的索引
    //      处理完后的对象包含四个属性：Roster,History,Closed,Index。其中Roster和History是数组，Index是会话在会话集合中的索引。
    //      Roster:参与人，每个元素的信息包含四个属性：Address,DisplayName,PersonalMessage,Status。
    //      History:会话历史信息，每个元素包含七个属性：SenderAddress,SenderDisplayName,SenderPersonalMessage,SenderStatus,Text,Time,Type
    var addConvInfo = function(obj,conv,index)
    {
        var rosters = new Array();//参与者
        var history = new Array();//历史信息

        var enum1 = conv.get_roster().getEnumerator();//得到参与者的迭代
        var enum2 = conv.get_history().getEnumerator();//得到历史数据的迭代

        var r;
        var h;

        var rObj;
        var hObj;

        //保存会话参与人信息
        while (enum1.moveNext())
        {
            r = enum1.get_current();//IMAddress object
            
            rObj = new Object();    
            rObj["Address"] = r.get_address();
            rObj["DisplayName"] = r.get_presence().get_displayName();
            rObj["PersonalMessage"] = r.get_presence().get_personalMessage();
            rObj["Status"] = r.get_presence().get_status();

            rosters.push(rObj);//保存参与人对象
        }

        //保存历史信息
        while (enum2.moveNext())
        {
            h = enum2.get_current();//Message object
            
            hObj = new Object();
            hObj["SenderAddress"] = h.get_sender().get_address();
            hObj["SenderDisplayName"] = h.get_sender().get_presence().get_displayName();
            hObj["SenderPersonalMessage"] = h.get_sender().get_presence().get_personalMessage();
            hObj["SenderStatus"] = h.get_sender().get_presence().get_status();
            hObj["Text"] = h.get_text();
            hObj["Time"] = h.get_timestamp();
            hObj["Type"] = h.get_type();

            history.push(hObj);
        }

        obj["Roster"] = rosters;//保存参与者信息
        obj["History"] = history;//保存历史信息
        obj["Closed"] = conv.get_closed();//会话是否关闭
        obj["Index"] = index;

        return obj;
    }
}
