void RaiseSyncEvents(SyncEvents data)
        {

            foreach (MessageEventArgs e in data.messageEvents)
                OnMessageReceived(e);

            foreach (GroupEventArgs e in data.groupAddedEvents)
                OnGroupAdded(e);

            foreach (GroupEventArgs e in data.groupRemovedEvents)
                OnGroupRemoved(e);

            foreach (UserListUserEventArgs e in data.userAddedToListEvents)
                OnUserAddedToList(e);

            foreach (UserListUserEventArgs e in data.userRemovedFromListEvents)
                OnUserRemovedFromList(e);

            foreach (GroupUserEventArgs e in data.userAddedToGroupEvents)
                OnUserAddedToGroup(e);

            foreach (GroupUserEventArgs e in data.userRemovedFromGroupEvents)
                OnUserRemovedFromGroup(e);

            foreach (GroupNameEventArgs e in data.groupNameChangedEvents)
                OnGroupNameChanged(e);

            foreach (UserNicknameEventArgs e in data.userNickNameChangedEvents)
                OnUserNicknameChanged(e);

            foreach (UserPropertyEventArgs e in data.userPropertyChangedEvents)
                OnUserPropertyChanged(e);

            foreach (PrivacySettingEventArgs e in data.privacySettingChangedEvents)
                OnPrivacySettingChanged(e);
        }
        SyncEvents ProcessSyncCommands(List<Command> syncCommands)
        {

            SyncEvents events = new SyncEvents();

            List<User> referencedUsers = new List<User>();
            List<Group> referencedGroups = new List<Group>();

            User lastUser = null;

            foreach (Command cmd in syncCommands)
            {

                if (cmd is UserCommand)
                {

                    UserCommand listCmd = cmd as UserCommand;

                    User user = null;

                    if (GetUserInner(listCmd.LoginName, out user))
                    {
                        user.guid = listCmd.Guid;
                        user.Nickname = listCmd.Nickname;
                    }
                    else
                    {

                        user.guid = listCmd.Guid;

                        if (user.Nickname != listCmd.Nickname)
                        {
                            string prevName = user.Nickname;
                            user.Nickname = listCmd.Nickname;

                            events.userNickNameChangedEvents.Add(new UserNicknameEventArgs(user, user.Nickname, prevName, false));
                        }

                    }

                    //user added to lists
                    foreach (UserList list in UserLists.Where(x => listCmd.Lists.Contains(x.listCode) && !x.Users.Contains(user)))
                    {
                        list.Users.AddUserInner(user);
                        events.userAddedToListEvents.Add(new UserListUserEventArgs(user, list, true));
                    }

                    //user removed from lists
                    foreach (UserList list in UserLists.Where(x => !listCmd.Lists.Contains(x.listCode) && x.Users.Contains(user)))
                    {
                        list.Users.RemoveUserInner(user);
                        events.userRemovedFromListEvents.Add(new UserListUserEventArgs(user, list, true));
                    }

                    //user added to groups
                    foreach (Group group in Groups.Where(x => listCmd.Groups.Contains(x.Guid) && !x.Users.Contains(user)))
                    {
                        group.Users.AddUserInner(user);
                        events.userAddedToGroupEvents.Add(new GroupUserEventArgs(user, group, true));

                    }

                    //user removed from groups
                    foreach (Group group in Groups.Where(x => !listCmd.Groups.Contains(x.Guid) && x.Users.Contains(user)))
                    {
                        group.Users.RemoveUserInner(user);
                        events.userRemovedFromGroupEvents.Add(new GroupUserEventArgs(user, group, true));

                    }

                    referencedUsers.Add(user);

                    lastUser = user;

                }
                else if (cmd is GroupCommand)
                {

                    GroupCommand groupCmd = cmd as GroupCommand;

                    Group group = Groups.Where(gx => gx.Guid == groupCmd.Guid).SingleOrDefault();

                    if (group == null)
                    {

                        group = new Group(this, groupCmd.Guid, groupCmd.Name);

                        Groups.AddGroup(group);

                        events.groupAddedEvents.Add(new GroupEventArgs(group, true));

                    }
                    else
                    {

                        if (group.Name != groupCmd.Name)
                        {

                            string prevName = group.Name;
                            group.Name = groupCmd.Name;

                            events.groupNameChangedEvents.Add(new GroupNameEventArgs(group, groupCmd.Name, prevName, true));
                        }

                    }

                    referencedGroups.Add(group);

                }

                else if (cmd is UserPropertyCommand)
                {

                    UserPropertyCommand propCmd = cmd as UserPropertyCommand;

                    UserProperty property = User.StringToProperty(propCmd.Key);

                    if (lastUser.GetPropertyInner(property) != propCmd.Value)
                    {
                        lastUser.SetPropertyInner(property, propCmd.Value);
                        events.userPropertyChangedEvents.Add(new UserPropertyEventArgs(lastUser, property, propCmd.Value, true));
                    }

                }

                else if (cmd is LocalPropertyCommand && ((LocalPropertyCommand)cmd).Key == "MFN")
                {

                    LocalPropertyCommand nameCmd = cmd as LocalPropertyCommand;

                    if (LocalUser.Nickname != nameCmd.Value)
                    {

                        string prevName = LocalUser.Nickname;
                        LocalUser.Nickname = nameCmd.Value;

                        events.userNickNameChangedEvents.Add(new UserNicknameEventArgs(LocalUser, nameCmd.Value, prevName, true));
                    }

                }

                else if (cmd is LocalPropertyCommand)
                {

                    LocalPropertyCommand propCmd = cmd as LocalPropertyCommand;

                    UserProperty property = User.StringToProperty(propCmd.Key);

                    if (LocalUser.GetPropertyInner(property) != propCmd.Value)
                    {
                        LocalUser.SetPropertyInner(property, propCmd.Value);
                        events.userPropertyChangedEvents.Add(new UserPropertyEventArgs(LocalUser, property, propCmd.Value, true));
                    }

                }
                else if (cmd is PrivacySettingCommand)
                {

                    PrivacySettingCommand privCmd = cmd as PrivacySettingCommand;

                    PrivacySetting setting = MessengerClient.StringToPrivacySetting(privCmd.Key);

                    if (GetPrivacySettingInner(setting) != privCmd.Value)
                    {
                        SetPrivacySettingInner(setting, privCmd.Value);
                        events.privacySettingChangedEvents.Add(new PrivacySettingEventArgs(setting, privCmd.Value, true));
                    }

                }
                else if (cmd is MessageCommand)
                {
                    MessageCommand message = cmd as MessageCommand;

                    Message msg = new Message(message.Payload);
                    events.messageEvents.Add(new MessageEventArgs(message.Sender, message.SenderNickname, msg, true));

                }
                else if (cmd is SbsCommand)
                {
                    //todo: do something with this command
                }



            }

            // remove groups that no longer exist
            foreach (Group group in Groups.Except(referencedGroups))
            {
                Groups.RemoveGroup(group);

                events.groupRemovedEvents.Add(new GroupEventArgs(group, true));
            }

            //remove users that no longer exist from lists and groups which currently contain them

            foreach (UserList list in UserLists)
                foreach (User user in list.Users.Except(referencedUsers))
                {
                    list.Users.RemoveUserInner(user);
                    events.userRemovedFromListEvents.Add(new UserListUserEventArgs(user, list, true));
                }

            foreach (Group group in Groups)
                foreach (User user in group.Users.Except(referencedUsers))
                {
                    group.Users.RemoveUserInner(user);
                    events.userRemovedFromGroupEvents.Add(new GroupUserEventArgs(user, group, true));

                }


            return events;

        }