using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IMLibrary;
using P;
using Ourmsg.Enum;
using Ourmsg.Server.BaseObject;
using Ourmsg.Server.MemoryObject;

using STSdb4.Database;

namespace Ourmsg.Server
{
    /// <summary>
    /// 本地缓存操作
    /// </summary>
    public class Cache
    {
        #region 字段
        /// <summary>
        /// 本地缓存
        /// </summary>
        public static IStorageEngine engine;
        public static string CacheDBName = "Ourmsg2016.stsdb4";
        #endregion

        #region 打开本地缓存数据库
        /// <summary>
        /// 打开本地缓存数据库
        /// </summary>
        public static void OpenNoSQL()
        {
            engine = STSdb.FromFile(CacheDBName);
        }
        #endregion

        #region 关闭缓存数据库
        /// <summary>
        /// 关闭缓存数据库
        /// </summary>
        public static void CloseNoSQL()
        {
            if (engine != null)
            {
                engine.Close();
            }
        }
        #endregion

        #region 添加取一个缓存用户信息
        /// <summary>
        /// 添加取一个缓存非系统用户信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public static bool AddUser(RouterCacheUser user)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var table = engine.OpenXTable<UInt32, RouterCacheUser>("Users");
                table[user.UserID] = user;
                engine.Commit();
                return true;
            }
        }

        /// <summary>
        /// 添加取一个缓存系统用户信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public static bool AddSysUser(RouterCacheUser user)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            { 
                var table = engine.OpenXTable<UInt32, RouterCacheUser>("SysUsers");
                table[user.UserID] = user;
                engine.Commit();
                return true;
            }
        }
        #endregion

        #region 添加取一个缓存用户信息 
        /// <summary>
        /// 获取缓存非系统用户信息
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static RouterCacheUser GetUser(UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var table = engine.OpenXTable<UInt32, RouterCacheUser>("Users");
                if (table.Exists(userID))
                    return table[userID];
                else
                    return null;
            }
        }

        /// <summary>
        /// 获取缓存非系统用户信息
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static RouterCacheUser GetSysUser(UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var table = engine.OpenXTable<UInt32, RouterCacheUser>("SysUsers");
                if (table.Exists(userID))
                    return table[userID];
                else
                    return null;
            }
        }

        /// <summary>
        /// 获取所有系统用户
        /// </summary> 
        /// <returns></returns>
        public static KeyValuePair<UInt32, RouterCacheUser>[] GetSystemUsers()
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                List<RouterCacheUser> Users = new List<RouterCacheUser>();
                var table = engine.OpenXTable<UInt32, RouterCacheUser>("SysUsers");
                return table.ToArray();
            }
        }

        /// <summary>
        /// 获取所有非系统用户
        /// </summary>
        /// <returns></returns>
        public static KeyValuePair<UInt32, RouterCacheUser>[] GetUnSystemUsers()
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                List<RouterCacheUser> Users = new List<RouterCacheUser>();
                var table = engine.OpenXTable<UInt32, RouterCacheUser>("Users");
                return table.ToArray();
            }
        }

        /// <summary>
        /// 获取所有系统用户
        /// </summary>
        /// <returns></returns>
        public static KeyValuePair<UInt32, RouterCacheUser>[] GetSysUser()
        {
            List<RouterCacheUser> Users = new List<RouterCacheUser>();
            var table = engine.OpenXTable<UInt32, RouterCacheUser>("SysUsers");
            return table.ToArray();
        }
        #endregion

        #region 获取用户好友集合
        /// <summary>
        /// 获取用户好友集合
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static KeyValuePair<UInt32, RouterCacheFriend>[] GetFriends(UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "UserFriend" + userID;
                List<RouterCacheFriend> friends = new List<RouterCacheFriend>();
                var table = engine.OpenXTable<UInt32, RouterCacheFriend>(tableName);
                return table.ToArray();
            }
        }
        #endregion

        #region 获取用户的一个好友资料
        /// <summary>
        /// 获取用户的一个好友资料
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="friendID"></param>
        /// <returns></returns>
        public static RouterCacheFriend GetFriend(UInt32 userID, UInt32 friendID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "UserFriend" + userID;
                var table = engine.OpenXTable<UInt32, RouterCacheFriend>(tableName);
                if (table.Exists(friendID))
                    return table[friendID];
                else
                    return null;
            }
        }
        #endregion

        #region 添加好友(将两个用户添加为互为好友关系)
        /// <summary>
        /// 添加好友(将两个用户添加为互为好友关系)
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="friendID"></param>
        /// <returns></returns>
        public static bool AddFriend(UInt32 userID, UInt32 friendID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                {
                    var tableName = "UserFriend" + userID;
                    var table = engine.OpenXTable<UInt32, RouterCacheFriend>(tableName);
                    table[friendID] = new RouterCacheFriend() { UserID = userID, FriendID = friendID };
                }
                {
                    var tableName = "UserFriend" + friendID;
                    var table = engine.OpenXTable<UInt32, RouterCacheFriend>(tableName);
                    table[userID] = new RouterCacheFriend() { UserID = friendID, FriendID = userID };
                }
                engine.Commit(); 
                return true;
            }
        }
        #endregion

        #region 获取用户群帐号集合
        /// <summary>
        /// 获取用户群帐号集合
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static KeyValuePair<UInt32, UInt32>[] GetUserRooms(UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                List<UInt32> rooms = new List<uint>();
                var table = engine.OpenXTable<UInt32, UInt32>("UserRoom" + userID);
                return table.ToArray();
            }
        }
        #endregion

        #region 获取一个缓存群信息
        /// <summary>
        /// 获取一个缓存群信息
        /// </summary>
        /// <param name="roomID"></param>
        /// <returns></returns>
        public static RouterCacheRoom GetRoom(UInt32 roomID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var table = engine.OpenXTable<UInt32, RouterCacheRoom>("Rooms");
                if (table.Exists(roomID))
                    return table[roomID];
                else
                    return null;
            }
        }
        #endregion

        #region 获得群用户集合 
        /// <summary>
        /// 获得群用户集合
        /// </summary>
        /// <param name="roomID"></param>
        /// <returns></returns>
        public static KeyValuePair<UInt32, RouterCacheRoomUser>[] GetRoomUsers(UInt32 roomID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "Room" + roomID;
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                return table.ToArray();
            }
        }
        #endregion

        #region 获取缓存群管理员集合
        /// <summary>
        /// 获取缓存群管理员集合
        /// </summary>
        /// <param name="roomID"></param>
        /// <returns></returns>
        //public static List<RouterCacheRoomUser> GetRoomAdmins(UInt32 roomID)
        //{
        //    //using (var engine = STSdb.FromFile(CacheDBName))
        //    {
        //        var tableName = "Room" + roomID;
        //        List<RouterCacheRoomUser> users = new List<RouterCacheRoomUser>();
        //        var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
        //        foreach (var u in table)
        //            if (u.Value.Admin)
        //                users.Add(u.Value); 
             
        //        return users;
        //    }
        //}

        public static KeyValuePair<UInt32, RouterCacheRoomUser>[] GetRoomAdmins(UInt32 roomID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "Room" + roomID;
                List<RouterCacheRoomUser> users = new List<RouterCacheRoomUser>();
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                return  table.Where((user) => user.Value.Admin == true).ToArray(); 
            }
        }
        #endregion

        #region 获取一个缓存群用户信息
        /// <summary>
        /// 获取一个缓存群用户信息
        /// </summary>
        /// <param name="roomID"></param>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static RouterCacheRoomUser GetRoomUser(UInt32 roomID, UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "Room" + roomID;
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                if (table.Exists(userID))
                    return table[userID];
                return null;
            }
        }
        #endregion

        #region 设置群管理员
        /// <summary>
        /// 设置群管理员
        /// </summary>
        /// <param name="roomID">群号</param>
        /// <param name="userID">用户ID</param>
        /// <param name="admin"></param>
        /// <returns></returns>
        public static bool SetRoomAdmin(UInt32 roomID, UInt32 userID, bool admin)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "Room" + roomID;
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                if (table.Exists(userID))
                    if (table[userID].Admin == admin)//如果用户已经是管理员，返回false
                        return false;
                    else
                    {
                        table[userID] = new RouterCacheRoomUser { UserID = userID, Admin = admin };
                        engine.Commit();
                        return true;//设置成功
                    }
                else
                    return false;//如果用户不在退，返回false
            }
        }
        #endregion 

        #region 添加用户到群
        /// <summary>
        /// 添加用户到群
        /// </summary>
        /// <param name="user"></param>
        /// <param name="roomID"></param>
        /// <returns></returns>
        public static bool AddUserToRoom( UInt32 roomID,RouterCacheRoomUser user)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "Room" + roomID;
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                table[user.UserID] = user;
                engine.Commit();
                return true;
            }
        }
       
        /// <summary>
        /// 添加多个用户到群
        /// </summary>
        /// <param name="users">群成员ID</param>
        /// <param name="roomID">群ID</param>
        /// <returns></returns>
        public static bool AddUsersToRoom(UInt32 roomID, List<UInt32> users)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                if (users == null || users.Count == 0) return false;
                var tableName = "Room" + roomID;
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                foreach (var userID in users)
                    table[userID] = new RouterCacheRoomUser() { UserID = userID };
                engine.Commit();
                return true;
            }
        }

        /// <summary>
        /// 创建群并添加多个用户到群
        /// </summary>
        /// <param name="createUserID">群创建者ID</param>
        /// <param name="users">群成员ID</param>
        /// <param name="roomID">群ID</param>
        /// <returns></returns>
        public static bool CreateRoom(RouterCacheRoom room, List<UInt32> users, UInt32 roomID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                {
                    var table = engine.OpenXTable<UInt32, RouterCacheRoom>("Rooms");
                    table[room.RoomID] = room;
                }
                {
                    var tableName = "Room" + roomID;
                    var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                    if (users != null)
                        foreach (var userID in users)
                            table[userID] = new RouterCacheRoomUser() { UserID = userID };//添加群成员
                    table[room.CreateUserID] = new RouterCacheRoomUser() { UserID = room.CreateUserID, Admin = true };//添加群创建者为管理员
                }
                engine.Commit();
                return true;
            }
        }
        #endregion

        #region 删除群用户
        /// <summary>
        /// 删除群用户
        /// </summary>
        /// <param name="roomID"></param>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static bool DelUserFromRoom(UInt32 roomID, UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var tableName = "Room" + roomID;
                var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>(tableName);
                if (table.Exists(userID))
                {
                    table.Delete(userID);
                    engine.Commit();
                    return true;
                }
                else
                    return false;
            }
        }
        #endregion

        #region 添加请求加入群的检验消息
        /// <summary>
        /// 添加请求加入群的检验消息
        /// </summary>
        /// <param name="roomID">群ID</param>
        /// <param name="userID">用户ID</param>
        public static void AddRequestAddRoomProof(UInt32 roomID, UInt32 userID, int groupID, string remarkName)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var id = roomID + "_" + userID;
                Proof p = new Proof() { ID = id, GroupID = groupID, RemarkName = remarkName, Timestamp = DateTime.Now };
                var table = engine.OpenXTable<string, Proof>("RequestAddRoomProofs");
                table[id] = p;
                engine.Commit(); 
            }
        }
        #endregion

        #region 判断请求加入群的检验消息是否存在并删除
        /// <summary>
        /// 判断请求加入群的检验消息是否存在并删除
        /// </summary>
        /// <param name="roomID"></param>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static Proof GetRequestAddRoomProof(UInt32 roomID, UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var id = roomID + "_" + userID;
                Proof proof = null;
                var table = engine.OpenXTable<string, Proof>("RequestAddRoomProofs");
                if (table.Exists(id))
                {
                    proof = table[id];
                    table.Delete(id);
                }
                engine.Commit(); 
                return proof;
            }
        }
        #endregion

        #region 添加邀请用户加入群的凭据
        /// <summary>
        /// 添加邀请用户加入群的凭据
        /// </summary>
        /// <param name="roomID">群ID</param>
        /// <param name="userID">用户ID</param>
        public static void AddInviteAddRoomProof(UInt32 roomID, UInt32 userID, int groupID, string remarkName)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var id = roomID + "_" + userID;
                Proof p = new Proof() { ID = id, GroupID = groupID, RemarkName = remarkName, Timestamp = DateTime.Now };
                var table = engine.OpenXTable<string, Proof>("InviteAddRoomProofs");
                table[id] = p;
                engine.Commit(); 
            }
        }
        #endregion

        #region 判断邀请用户加入群的凭据是否存在并删除
        /// <summary>
        /// 判断邀请用户加入群的凭据是否存在并删除
        /// </summary>
        /// <param name="roomID"></param>
        /// <param name="userID"></param>
        /// <returns></returns>
        public static Proof GetInviteAddRoomProof(UInt32 roomID, UInt32 userID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var id = roomID + "_" + userID;
                Proof proof = null;
                var table = engine.OpenXTable<string, Proof>("InviteAddRoomProofs");
                if (table.Exists(id))
                {
                    proof = table[id];
                    table.Delete(id);
                }
                engine.Commit(); 
                return proof;
            }
        }
        #endregion

        #region 添加好友凭据
        /// <summary>
        /// 
        /// </summary>
        /// <param name="friendID"></param>
        /// <param name="userID"></param>
        /// <param name="groupID"></param>
        /// <param name="remarkName"></param>
        public static void AddFriendProof(UInt32 userID, UInt32 friendID, int groupID, string remarkName)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var id = userID + "_" + friendID;
                Proof p = new Proof() { ID = id, GroupID = groupID, RemarkName = remarkName, Timestamp = DateTime.Now };
                var table = engine.OpenXTable<string, Proof>("AddFriendProofs");
                table[id] = p;
                engine.Commit();
            }
        }
        #endregion

        #region 判断添加好友的凭据是否存在并删除
        /// <summary>
        /// 判断添加好友的检验消息是否存在并删除
        /// </summary>
        /// <param name="friendID">好友ID</param>
        /// <param name="userID">用户ID</param>
        /// <returns></returns>
        public static Proof GetAddFriendProof(UInt32 userID, UInt32 friendID)
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                var id = userID + "_" + friendID;
                Proof proof = null;
                var table = engine.OpenXTable<string, Proof>("AddFriendProofs");
                if (table.Exists(id))
                {
                    proof = table[id];
                    table.Delete(id);
                }
                return proof;
            }
        }
        #endregion

        #region 加载数据库数据到本地缓存
        /// <summary>
        /// 将数据库中用户和群的基础数据加载到缓存中,以实现高速访问与存储
        /// </summary>
        /// <returns></returns>
        public static void LoadDBtoCache()
        {
            //using (var engine = STSdb.FromFile(CacheDBName))
            {
                ////加载所有非系统用户 
                //{
                //    var sql = "Select * from Users  where SysUser=0";
                //    var us = DBAccess.Select<RouterCacheUser>(sql);
                //    var table = engine.OpenXTable<UInt32, RouterCacheUser>("Users");
                //    foreach (var u in us)
                //        table[u.UserID] = u;
                //}

                ////加载所有系统用户
                //{
                //    var sql = "Select * from Users where SysUser=1";
                //    var us = DBAccess.Select<RouterCacheUser>(sql);
                //    var table = engine.OpenXTable<UInt32, RouterCacheUser>("SysUsers");
                //    foreach (var u in us)
                //        table[u.UserID] = u;
                //}

                //加载所有用户好友
                {
                    var sql = "select * from UserFriends order by ID ";
                    var users = DBAccess.Select<MemoryObject.RouterCacheFriend>(sql );
                    foreach (var u in users)
                    {

                        var table = engine.OpenXTable<UInt32, RouterCacheFriend>("UserFriend" + u.UserID);
                        table[u.FriendID] = u;
                    }
                }

                //加载所有群 
                {
                    var sql = "Select * from Rooms;";
                    var rs = DBAccess.Select<RouterCacheRoom>(sql );
                    var table = engine.OpenXTable<UInt32, RouterCacheRoom>("Rooms");
                    foreach (var r in rs)
                        table[r.RoomID] = r;
                }

                //加载所有群用户,加载所有用户群关系
                {
                    var sql = "select * from RoomUsers order by ID;";
                    var rus = DBAccess.Select<MemoryObject.RouterCacheRoomUser>(sql );
                    foreach (var u in rus)
                    {
                        //加载所有群用户
                        {
                            var table = engine.OpenXTable<UInt32, RouterCacheRoomUser>("Room" + u.roomID);
                            table[u.UserID] = u;
                        }
                        //加载所有用户群关系
                        {
                            var table = engine.OpenXTable<UInt32, UInt32>("UserRoom" + u.UserID);
                            table[u.roomID] = u.roomID;
                        }
                    }
                }
                engine.Commit();
            }
        }
        #endregion
         
    }
}
