using FI.FIC;
using FI.FIC.Contracts.DataObjects;
using FI.FIC.Contracts.DataObjects.BaseObject;
using FI.FIC.Contracts.DataObjects.Enumeration;
using FI.FIC.Models;
using Foresight.Data;
using Foresight.Fleet.Services.Asset;
using Foresight.Fleet.Services.Customer;
using Foresight.Fleet.Services.User;
using Foresight.ServiceModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace IronIntel.Contractor.Users
{
    public static class UserManagement
    {
        public static UserInfo[] GetUsers(string companyid = null, string filter = null)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<UserQueryClient>(companyid, string.Empty).GetUsersByCustomerID(companyid, filter);
            if (users == null || users.Length == 0)
                return new UserInfo[0];

            var maps = GetGroupsMaps();
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                UserInfo u = ConvertUserItem(user);
                if (maps.ContainsKey(u.IID))
                    u.GroupNames = maps[u.IID].ToArray();
                list.Add(u);
            }
            return list.ToArray();
        }


        private static Dictionary<string, List<string>> GetGroupsMaps()
        {
            const string SQL = "select m.USERIID,m.GROUPID,g.GROUPNAME from USERGROUPMAP m left join USERGROUPS g on m.GROUPID=g.GROUPID order by GROUPNAME";

            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL);
            if (dt.Rows.Count == 0)
                return new Dictionary<string, List<string>>();

            Dictionary<string, List<string>> result = new Dictionary<string, List<string>>();
            foreach (DataRow dr in dt.Rows)
            {
                string useriid = FIDbAccess.GetFieldString(dr["USERIID"], string.Empty);
                string groupid = FIDbAccess.GetFieldString(dr["GROUPID"], string.Empty);
                string groupname = FIDbAccess.GetFieldString(dr["GROUPNAME"], string.Empty);
                if (!result.ContainsKey(useriid))
                    result[useriid] = new List<string>();
                if (!string.IsNullOrEmpty(groupname))
                    result[useriid].Add(groupname);

            }
            return result;
        }

        public static UserInfo[] GetActiveUsers(string sessionid, string companyid = null)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<UserQueryClient>(companyid, sessionid).GetUsersByCustomerID(companyid, "");
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                if (user.Active)
                    list.Add(ConvertUserItem(user));
            }
            return list.ToArray();
        }

        public static UserInfo[] GetAllFollowers(string sessionid, string companyid = null)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(companyid, sessionid);
            var users = client.GetUsersByCustomerID(companyid, "");
            var userattrs = client.GetUserAdditionalAttributeByCustomer(companyid);
            var followers = userattrs.Where(x => x.WorkOrderFollower).Select(x => x.UserIID);
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                if (user.Active && user.IsUser && followers.Contains(user.UID, StringComparer.OrdinalIgnoreCase))
                    list.Add(ConvertUserItem(user));
            }
            return list.ToArray();
        }

        public static UserInfo[] GetSalespersons(string sessionid, string companyid = null, string filter = "")
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<UserQueryClient>(companyid, sessionid).GetUsersByCustomerID(companyid, "");
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                if (user.Active)
                {
                    if (string.IsNullOrWhiteSpace(filter))
                        list.Add(ConvertUserItem(user));
                    else
                    {
                        if (user.ID.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0
                            || user.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0
                            || user.FOB.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)
                            list.Add(ConvertUserItem(user));
                    }
                }
            }
            return list.ToArray();
        }

        private static UserInfo ConvertUserItem(Foresight.Fleet.Services.User.UserInfo user)
        {
            if (user == null)
                return null;
            UserInfo u = new UserInfo();
            u.IID = user.UID;
            u.ID = user.ID;
            u.DisplayName = user.Name;
            u.UserType = (UserTypes)user.UserType;
            u.Active = user.Active;
            u.TextAddress = user.TextAddress;
            u.TextAddressDisplayText = user.TextAddressDisplayText;
            u.Mobile = user.Mobile;
            u.MobilePhoneDisplayText = user.MobilePhoneDisplayText;
            u.BusinessPhone = user.BusinessPhone;
            u.BusinessPhoneDisplayText = user.BusinessPhoneDisplayText;
            u.Notes = user.Remark;
            u.IsUser = user.IsUser;
            u.ContactType = (ContactTypes)user.ContactType;
            u.ManagerIID = user.ManagerIID;
            u.ManagerName = user.ManagerName;
            u.AssignedWorkOrders = user.AssignedWorkOrders;
            u.EmailOptOut = user.EmailOptOut;
            u.InspectEmailList = user.InspectEmailList;
            u.TeamIntelligenceUser = user.TeamIntelligenceUser;
            u.FOB = user.FOB;
            u.HourlyRate = user.HourlyRate;
            u.AllowLoginIntoPC = user.AllowLoginIntoPC;
            u.AllowLoginIntoFleetMobile = user.AllowLoginIntoFleetMobile;
            u.AllowLoginIntoInspectMobile = user.AllowLoginIntoInspectMobile;
            u.AllowMobileBarcodeScanning = user.AllowMobileBarcodeScanning;
            u.PreferredLanguage = user.PreferredLanguage;
            u.LoginVerifyType = user.LoginVerifyType;
            u.TimeZone = user.TimeZone;
            if (!string.IsNullOrWhiteSpace(u.ManagerIID))
                u.Managers = new UserInfo[] { new UserInfo() { IID = u.ManagerIID, DisplayName = u.ManagerName } };

            return u;
        }

        private static Foresight.Fleet.Services.User.UserInfo ConvertUserItem(UserInfo user)
        {
            if (user == null)
                return null;
            Foresight.Fleet.Services.User.UserInfo u = new Foresight.Fleet.Services.User.UserInfo();
            u.UID = user.IID;
            u.ID = user.ID;
            u.Name = user.DisplayName;
            u.UserType = (Foresight.Fleet.Services.User.UserTypes)user.UserType;
            u.Active = user.Active;
            u.Email = user.ID;
            u.TextAddress = user.TextAddress;
            u.Mobile = user.Mobile;
            u.BusinessPhone = user.BusinessPhone;
            u.Remark = user.Notes;
            u.IsUser = user.IsUser;
            u.ContactType = (Foresight.Fleet.Services.User.ContactTypes)user.ContactType;
            u.ManagerIID = user.ManagerIID;
            u.AssignedWorkOrders = user.AssignedWorkOrders;
            u.EmailOptOut = user.EmailOptOut;
            u.InspectEmailList = user.InspectEmailList;
            u.TeamIntelligenceUser = user.TeamIntelligenceUser;
            u.FOB = user.FOB;
            u.HourlyRate = user.HourlyRate;
            u.AllowLoginIntoPC = user.AllowLoginIntoPC;
            u.AllowLoginIntoFleetMobile = user.AllowLoginIntoFleetMobile;
            u.AllowLoginIntoInspectMobile = user.AllowLoginIntoInspectMobile;
            u.AllowMobileBarcodeScanning = user.AllowMobileBarcodeScanning;
            u.PreferredLanguage = user.PreferredLanguage;
            u.LoginVerifyType = user.LoginVerifyType;
            u.TimeZone = user.TimeZone;
            return u;
        }

        public static UserInfo[] GetUnmanagementUsers()
        {
            var users = FleetServiceClientHelper.CreateClient<UserQueryClient>(SystemParams.CompanyID).GetUsersByCustomerID(SystemParams.CompanyID, "");
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                if (user.IsUser && user.UserType < Foresight.Fleet.Services.User.UserTypes.Admin)
                {
                    list.Add(ConvertUserItem(user));
                }
            }
            return list.ToArray();
        }

        /// <summary>
        /// local+dealer+foresight
        /// </summary>
        /// <returns></returns>
        public static UserInfo[] GetAllAvailableUsers()
        {
            List<UserInfo> ls = new List<UserInfo>();
            ls.AddRange(GetUsers());
            ls.AddRange(GetForesightUsers());
            if (!SystemParams.IsDealer)
            {
                var dealer = SystemParams.GetFirstDealerInfo();
                if (dealer != null)
                {
                    var dealerusers = GetUsers(dealer.ID);
                    ls.AddRange(dealerusers);
                }
            }
            return ls.ToArray();
        }

        public static UserInfo[] GetForesightUsers()
        {
            var users = FleetServiceClientHelper.CreateClient<UserQueryClient>().GetUsersByCustomerID("Foresight", "");
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                list.Add(ConvertUserItem(user));
            }
            return list.ToArray();
        }

        private static UserInfo ConvertToUserInfo(DataRow dr)
        {
            UserInfo ui = new UserInfo();
            ui.IID = FIDbAccess.GetFieldString(dr["USERIID"], string.Empty);
            ui.ID = FIDbAccess.GetFieldString(dr["USERID"], string.Empty);
            ui.DisplayName = FIDbAccess.GetFieldString(dr["USERNAME"], string.Empty);
            ui.UserType = (UserTypes)FIDbAccess.GetFieldInt(dr["USERTYPE"], 0);
            ui.Active = FIDbAccess.GetFieldInt(dr["ACTIVE"], 0) == 1;
            ui.Mobile = FIDbAccess.GetFieldString(dr["MOBILE"], string.Empty);
            ui.BusinessPhone = FIDbAccess.GetFieldString(dr["BUSINESSPHONE"], string.Empty);
            ui.Notes = FIDbAccess.GetFieldString(dr["NOTES"], string.Empty);

            return ui;
        }

        public static UserInfo GetUserBySessionID(string sessionid)
        {
            var ls = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid).GetLoginSession(sessionid);
            if (ls == null)
            {
                return null;
            }
            if (ls.User.IsForesightUser)
            {
                UserInfo ui = new UserInfo();
                ui.IID = ls.User.UID;
                ui.ID = ls.User.ID;
                ui.DisplayName = ls.User.Name;
                ui.Active = true;
                ui.UserType = UserTypes.SupperAdmin;
                ui.TimeZone = ls.User.TimeZone;
                return ui;
            }
            else
            {
                return ConvertUserItem(ls.User);
            }
        }

        public static UserInfo GetUserByIID(string iid)
        {
            var user = FleetServiceClientHelper.CreateClient<UserQueryClient>().GetUserByIID(iid);
            return ConvertUserItem(user);
        }

        public static UserInfo GetUserByID(string userid)
        {
            var user = FleetServiceClientHelper.CreateClient<UserQueryClient>().GetUserByUserID(userid);
            return ConvertUserItem(user);
        }

        public static string AddUser(UserInfo ui, string password, string addby, string sessionid, string clienthost, byte[] avadarBytes)
        {
            try
            {
                var user = ConvertUserItem(ui);
                user.CompanyID = SystemParams.CompanyID;

                var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid);
                client.SessionID = sessionid;
                client.ClientHost = clienthost;
                user = client.AddNewUser(user, password, addby);
                if (avadarBytes != null)
                {
                    avadarBytes = Helper.GetThumbImg(avadarBytes, 300, 300);
                    client.SetUserAvatar(user.UID, avadarBytes);
                }

                return user.UID;
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("Error", typeof(UserManagement).FullName + ".AddUser", "Add new user failed: " + ui.ID, ex.ToString());
                throw;
            }
        }


        public static void UpdateUserInfo(UserInfo ui, string updatedby, string sessionid, string clienthost, byte[] avadarBytes)
        {
            try
            {
                var user = ConvertUserItem(ui);
                user.CompanyID = SystemParams.CompanyID;

                var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid);
                client.SessionID = sessionid;
                client.ClientHost = clienthost;
                client.UpdateUser(user, updatedby);
                if (avadarBytes != null)
                {
                    avadarBytes = Helper.GetThumbImg(avadarBytes, 300, 300);
                    client.SetUserAvatar(user.UID, avadarBytes);
                }
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("Error", typeof(UserManagement).FullName + ".UpdateUserInfo", "Update user failed: " + ui.IID, ex.ToString());
                throw;
            }
        }
        public static void SetUserAvatar(string sessionid, string uid, byte[] avadarBytes)
        {
            try
            {
                var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid);
                client.SetUserAvatar(uid, avadarBytes);
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("Error", typeof(UserManagement).FullName + ".SetUserAvatar", "Set user Avatar failed: " + uid, ex.ToString());
                throw;
            }
        }

        public static void ResetPassword(string useriid, string password, string resetby, string sessionid, string clienthost)
        {
            var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid);
            client.SessionID = sessionid;
            client.ClientHost = clienthost;
            client.ResetPassword(useriid, password, true, resetby);
        }

        public static bool CanDeleteUser(string useriid)
        {
            //TODO
            return true;
        }

        public static byte[] GetUserAvatar(string sessionid, string useriid)
        {

            var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid);
            return client.GetUserAvatar(useriid);
        }


        #region user group

        public static UserGroupInfo[] GetGroups()
        {
            const string SQL = @"select GROUPID,GROUPNAME,NOTES from USERGROUPS order by GROUPNAME ASC";
            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL);
            List<UserGroupInfo> list = new List<UserGroupInfo>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(ConvertToUserGroupInfo(dr));
            }
            return list.ToArray();
        }
        public static UserGroupInfo[] GetGroupsByUser(string useriid)
        {
            const string SQL = @"select GROUPID,GROUPNAME,NOTES from USERGROUPS where GROUPID in (select GroupID from USERGROUPMAP where UserIID={0}) order by GROUPNAME ASC";
            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL, useriid);
            List<UserGroupInfo> list = new List<UserGroupInfo>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(ConvertToUserGroupInfo(dr));
            }
            return list.ToArray();
        }

        public static UserGroupInfo GetGroup(string groupid)
        {
            const string SQL = @"select GROUPID,GROUPNAME,NOTES from USERGROUPS where GROUPID={0}";
            FIDbAccess db = SystemParams.GetDbInstance();
            UserGroupInfo ui = null;
            DataTable dt = db.GetDataTableBySQL(SQL, groupid);
            if (dt.Rows.Count > 0)
            {
                ui = ConvertToUserGroupInfo(dt.Rows[0]);
                ui.Users = GetUserInfoByGoupid(groupid);
            }
            return ui;
        }

        public static List<string> GetUserGroupIDByUserIID(string userIID)
        {
            const string SQL = "select GroupID from [USERGROUPMAP] where UserIID={0}";
            var db = SystemParams.GetDbInstance();
            var dt = db.GetDataTableBySQL(SQL, userIID);
            var result = new List<string>();
            foreach (DataRow row in dt.Rows)
            {
                result.Add(FIDbAccess.GetFieldString(row["GroupID"], Guid.Empty.ToString()));
            }
            if (result.Count == 0)
            {
                result.Add(Guid.Empty.ToString());
            }
            return result;
        }

        public static void AddGroup(UserGroupInfo gi)
        {
            const string SQL_group = "insert into USERGROUPS(GROUPID,GROUPNAME,NOTES) values({0},{1},{2})";
            const string SQL_map = "insert into USERGROUPMAP(GROUPID,USERIID) values({0},{1})";
            if (CheckGroupnameRepeat(gi.Name, gi.ID))
            {
                throw new Exception("The User Group name must be unique.");
            }
            using (FISqlTransaction tran = new FISqlTransaction(SystemParams.DataDbConnectionString))
            {
                tran.ExecSQL(SQL_group, gi.ID, gi.Name, gi.Notes);
                if (gi.Users.Count() > 0)
                {
                    foreach (UserInfo ui in gi.Users)
                    {
                        tran.ExecSQL(SQL_map, gi.ID, ui.IID);
                    }
                }
                tran.Commit();
            }
        }

        public static void UpdateGroup(UserGroupInfo gi)
        {
            const string SQL_group = "update USERGROUPS set GROUPNAME={1},NOTES={2} where GROUPID={0}";
            const string SQL_map = "insert into USERGROUPMAP(GROUPID,USERIID) values({0},{1})";
            const string SQL_del = "delete from USERGROUPMAP where GROUPID={0}";
            if (CheckGroupnameRepeat(gi.Name, gi.ID))
            {
                throw new Exception("The User Group name must be unique");
            }
            using (FISqlTransaction tran = new FISqlTransaction(SystemParams.DataDbConnectionString))
            {
                tran.ExecSQL(SQL_group, gi.ID, gi.Name, gi.Notes);
                tran.ExecSQL(SQL_del, gi.ID);
                if (gi.Users.Count() > 0)
                {
                    foreach (UserInfo ui in gi.Users)
                    {
                        tran.ExecSQL(SQL_map, gi.ID, ui.IID);
                    }
                }
                tran.Commit();
            }
        }

        public static void DeleteGroup(string groupid)
        {
            const string SQL = "delete from USERGROUPS where GROUPID={0}"
                            + " delete from USERGROUPMAP where GROUPID={0}"
                            + " delete from USERTOCONTRACTOR where USERIID ={0}";
            if (CheckGroupHasUser(groupid))
            {
                throw new Exception("There are one or more users in this user group,so it cannot be deleted.");
            }
            FIDbAccess db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL, groupid);
        }


        public static UserInfo[] GetUserInfoByGoupid(string groupid)
        {
            const string SQL = @"select a.USERIID,a.USERID,a.USERNAME,a.USERTYPE,a.EMAIL,a.ACTIVE,a.MOBILE,a.BUSINESSPHONE,a.NOTES
                            from USERS a, USERGROUPMAP b where a.USERIID = b.USERIID and b.GROUPID ={0}";
            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL, groupid);
            List<UserInfo> list = new List<UserInfo>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(ConvertToUserInfo(dr));
            }
            return list.ToArray();
        }

        private static bool CheckGroupnameRepeat(string groupname, string groupid)
        {
            const string SQL = "select count(1) from USERGROUPS where GROUPNAME={0} and GROUPID!={1}";
            FIDbAccess db = SystemParams.GetDbInstance();
            object obj = db.GetRC1BySQL(SQL, groupname, groupid);
            if (Convert.ToInt32(obj) > 0)
            {
                return true;
            }
            return false;
        }
        private static bool CheckGroupHasUser(string groupid)
        {
            const string SQL = "select COUNT(1) from USERGROUPMAP where GROUPID={0}";
            FIDbAccess db = SystemParams.GetDbInstance();
            object obj = db.GetRC1BySQL(SQL, groupid);
            if (Convert.ToInt32(obj) > 0)
            {
                return true;
            }
            return false;
        }

        private static UserGroupInfo ConvertToUserGroupInfo(DataRow dr)
        {
            UserGroupInfo gi = new UserGroupInfo();
            gi.ID = FIDbAccess.GetFieldString(dr["GROUPID"], string.Empty);
            gi.Name = FIDbAccess.GetFieldString(dr["GROUPNAME"], string.Empty);
            gi.Notes = FIDbAccess.GetFieldString(dr["NOTES"], string.Empty);
            return gi;
        }
        #endregion

        #region User Machines/Jobsite/MachineType/Department/Location

        public static UserInfo[] GetUsersByAssetID(string sessionid, long assetid, string companyid)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetUsersAvailableForAsset(companyid, assetid);
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                list.Add(ConvertUserItem(user));
            }
            return list.ToArray();
        }

        public static UserInfo[] GetWorkOrderAssignToUsers(string sessionid, string companyid, long assetid, int locid, int depid)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetUsersAvailableForAsset(companyid, assetid);
            var cusers = FleetServiceClientHelper.CreateClient<AssetDataAdjustClient>(companyid, sessionid).GetAssetContacts(companyid, assetid);

            List<Foresight.Fleet.Services.User.UserInfo> allusers = new List<Foresight.Fleet.Services.User.UserInfo>();
            if (users != null && users.Length > 0)
                allusers.AddRange(users);
            if (cusers != null && cusers.Length > 0)
                allusers.AddRange(cusers);

            string[] depandlocusers = null;
            if (locid > 0 || depid > 0)
                depandlocusers = FleetServiceClientHelper.CreateClient<UserProfileProvider>(companyid, sessionid).GetUsersByLocAndDep(companyid, locid, depid);
            List<UserInfo> list = new List<UserInfo>();
            List<string> uids = new List<string>();
            foreach (var user in allusers)
            {
                if (uids.Contains(user.UID))
                    continue;

                if (!user.AssignedWorkOrders && user.ContactType != Foresight.Fleet.Services.User.ContactTypes.Advisor) continue;
                if (depandlocusers == null || depandlocusers.Contains(user.UID, StringComparer.OrdinalIgnoreCase))
                {
                    list.Add(ConvertUserItem(user));
                    uids.Add(user.UID);
                }
            }
            return list.OrderBy(u => u.DisplayName).ToArray();
        }

        public static UserInfo[] GetUsersByAssets(string sessionid, long[] assetids, string companyid)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetUsersAvailableForAssets(companyid, assetids);
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                list.Add(ConvertUserItem(user));
            }
            return list.ToArray();
        }

        public static UserInfo[] GetUsersByJobsiteID(string sessionid, long jsid, string companyid)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;
            var users = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid).GetUsersAvailableForJobsite(companyid, jsid);
            List<UserInfo> list = new List<UserInfo>();
            foreach (var user in users)
            {
                list.Add(ConvertUserItem(user));
            }
            return list.ToArray();
        }

        /// <summary>
        /// 获取机器对应的ContactID
        /// </summary>
        /// <returns></returns>
        public static string[] GetAssignedUsersByAssetID(FISqlConnection db, long machineid)
        {
            const string SQL_C = "select USERIID from USERMACHINEMAP where MACHINEID={0}";

            Dictionary<int, List<string>> result = new Dictionary<int, List<string>>();
            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable tb = db.GetDataTableBySQL(SQL_C, machineid);
            if (tb.Rows.Count <= 0)
                return new string[0];

            List<string> list = new List<string>();
            foreach (DataRow dr in tb.Rows)
            {
                string contactid = FIDbAccess.GetFieldString(dr["USERIID"], "");
                list.Add(contactid);
            }
            return list.ToArray();
        }
        #endregion


        #region user to contractor

        public static void AddUserToContractor(string iid, string[] contractorids)
        {
            const string DelSQL = "delete from USERTOCONTRACTOR where USERIID ={0}";
            const string SQL = "insert into USERTOCONTRACTOR(CONTRACTORID,USERIID) values({0},{1})";
            using (FISqlTransaction tran = new FISqlTransaction(SystemParams.DataDbConnectionString))
            {
                tran.ExecSQL(DelSQL, iid);
                foreach (string cid in contractorids)
                {
                    tran.ExecSQL(SQL, cid, iid);
                }
                tran.Commit();
            }
        }

        public static void DeleteUserToContractor(string iid, string[] contractorids)
        {
            const string SQL = "delete from USERTOCONTRACTOR where CONTRACTORID={0} and USERIID ={1}";
            FIDbAccess db = SystemParams.GetDbInstance();
            using (FISqlTransaction tran = new FISqlTransaction(SystemParams.DataDbConnectionString))
            {
                foreach (string cid in contractorids)
                {
                    tran.ExecSQL(SQL, cid, iid);
                }
                tran.Commit();
            }
        }

        public static UserToContractorInfo[] GetContractorsByIId(string iid, int seltype)//seltype 1、用户   2、用户组
        {
            CustomerInfo[] cps = SystemParams.GetContractors();

            List<UserToContractorInfo> list = new List<UserToContractorInfo>();
            string[] str = GetContractorById(iid, seltype);
            foreach (CustomerInfo cp in cps)
            {
                UserToContractorInfo ui = new UserToContractorInfo();
                ui.ID = cp.ID;
                ui.Name = cp.Name;
                if (seltype == 1)
                {
                    ui.AuthorizedIngroup = CheckAuthorizedIngroup(iid, cp.ID);
                }
                foreach (string s in str)
                {
                    if (string.Compare(cp.ID, s, true) == 0)
                    {
                        ui.IsChecked = true;
                        break;
                    }
                }
                list.Add(ui);
            }

            return list.ToArray();
        }

        private static string[] GetContractorById(string iid, int seltype)
        {
            const string SQL_user = @"select distinct CONTRACTORID from USERTOCONTRACTOR where USERIID={0}
                                 or USERIID in(select GROUPID from USERGROUPMAP where USERIID ={0})";
            const string SQL_group = @"select distinct CONTRACTORID from USERTOCONTRACTOR where USERIID={0}";
            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = null;
            if (seltype == 1)
            {
                dt = db.GetDataTableBySQL(SQL_user, iid);
            }
            else
            {
                dt = db.GetDataTableBySQL(SQL_group, iid);
            }
            List<string> list = new List<string>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(FIDbAccess.GetFieldString(dr["CONTRACTORID"], string.Empty));
            }
            return list.ToArray();
        }

        private static bool CheckAuthorizedIngroup(string useriid, string contractorid)
        {
            const string SQL = @"select Count(*) from USERTOCONTRACTOR where CONTRACTORID={0} and USERIID in(select GROUPID from USERGROUPMAP where USERIID ={1})";
            FIDbAccess db = SystemParams.GetDbInstance();
            object obj = db.GetRC1BySQL(SQL, contractorid, useriid);
            if (Convert.ToInt32(obj) > 0)
            {
                return true;
            }
            return false;
        }


        #endregion


        #region Host

        public static bool ChangePassword(string uid, string oldpwd, string newpwd, string sessionid, string clienthost)
        {
            try
            {
                var client = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid);
                client.SessionID = sessionid;
                client.ClientHost = clienthost;
                client.ChangePassword(uid, oldpwd, newpwd, sessionid);
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public static List<UserGroupSimple> SearchLocalGroups(string prefix)
        {
            const string SQL = @"select GROUPID as IID,GROUPNAME as GroupName,NOTES as Description,0 as GroupMode from USERGROUPS where GROUPNAME like {0} order by GroupName";
            var db = SystemParams.GetDbInstance();
            var table = db.GetDataTableBySQL(SQL, "%" + prefix + "%");

            var list = new List<UserGroupSimple>();
            foreach (DataRow dr in table.Rows)
            {
                list.Add(new UserGroupSimple
                {
                    UserGroupID = FIDbAccess.GetFieldString(dr["IID"], null),
                    UserGroupName = FIDbAccess.GetFieldString(dr["GroupName"], null),
                    Description = FIDbAccess.GetFieldString(dr["Description"], null),
                    GroupMode = FIDbAccess.GetFieldInt(dr["GroupMode"], 0)
                });
            }

            return list;
        }
        internal static UserInfoItem[] GetPermissionUsers1()
        {
            List<UserInfoItem> users = new List<UserInfoItem>();

            DataTable authenDt = SystemParams.GetDbInstance().GetDataTableBySQL("select * from Users where isnull(DELETED,0)=0");

            string str = "";
            for (int i = authenDt.Rows.Count - 1; i >= 0; i--)
            {
                str = authenDt.Rows[i]["USERID"].ToString();
                if (string.Compare(str, "admin", true) == 0 || FIDbAccess.GetFieldInt(authenDt.Rows[i]["USERTYPE"], 1) != 1) //EMUserType.Common
                {
                    authenDt.Rows.RemoveAt(i);
                }
                else
                {
                    UserInfoItem user = new UserInfoItem();
                    user.IID = FIDbAccess.GetFieldString(authenDt.Rows[i]["USERIID"], string.Empty);
                    user.ID = FIDbAccess.GetFieldString(authenDt.Rows[i]["USERID"], string.Empty);
                    user.DisplayName = FIDbAccess.GetFieldString(authenDt.Rows[i]["USERNAME"], string.Empty);
                    users.Add(user);
                }
            }
            return users.ToArray();
        }

        internal static UserInfoItem[] GetPermissionUsers()
        {
            List<UserInfoItem> ls = new List<UserInfoItem>();

            var users = FleetServiceClientHelper.CreateClient<UserQueryClient>(SystemParams.CompanyID, string.Empty).GetUsersByCustomerID(SystemParams.CompanyID, "");
            if (users == null || users.Length == 0)
                return new UserInfoItem[0];

            foreach (var u in users)
            {
                if (string.Compare(u.ID, "admin", true) == 0 || (int)u.UserType != 1) //EMUserType.Common
                    continue;

                UserInfoItem user = new UserInfoItem();
                user.IID = u.UID;
                user.ID = u.ID;
                user.DisplayName = u.Name;
                ls.Add(user);
            }

            return ls.ToArray();
        }

        internal static UserPermissionData[] GetUserOrGroupPermission(string UserOrGroup, string objIID, string userIID, string lang)
        {
            List<UserPermissionData> UserOrGroupPermissionDatas = new List<UserPermissionData>();

            DataTable UserGroupPermissionList = null;
            if (UserOrGroup == "Group")
            {
                UserGroupPermissionList = GetUserGroupOperationPermissions(objIID);
            }
            else
            {
                UserGroupPermissionList = GetUserOperationPermissions(objIID);
            }

            List<Operations> allPermissionList = GetOperationPermissions();
            foreach (var opr in allPermissionList)
            {
                UserPermissionData upmd = new UserPermissionData();
                upmd.FunctionIID = opr.IID;
                upmd.IsAllowed = false;
                upmd.ManagementFunction = ResManager.GetLanguage(lang, ResManager.GetResourceString(opr.FunctionName));
                upmd.Description = ResManager.GetLanguage(lang, ResManager.GetResourceString(opr.Description));
                upmd.IsNotPermissionInGroup = true;

                UserOrGroupPermissionDatas.Add(upmd);
            }

            foreach (DataRow row in UserGroupPermissionList.Rows)
            {
                var iid = FIDbAccess.GetFieldString(row["FunctionID"], Guid.Empty.ToString());

                int pos = GetPermissionFunctionIndex(iid, allPermissionList);
                if (pos < 0) continue;

                if (FIDbAccess.GetFieldInt(row["RightValue"], 0) > 0)
                {
                    UserOrGroupPermissionDatas[pos].IsAllowed = true;
                }
                else
                {
                    UserOrGroupPermissionDatas[pos].IsAllowed = false;
                }
            }

            List<string> permissionOfUserInGroup = null;
            if (UserOrGroup == "User")
                permissionOfUserInGroup = GetMaxUserGroupOperationPermissionsOfUser(objIID);
            if (permissionOfUserInGroup != null)
            {
                for (int i = 0; i < permissionOfUserInGroup.Count; i++)
                {
                    int pos = GetPermissionFunctionIndex(permissionOfUserInGroup[i], allPermissionList);
                    if (pos < 0) continue;

                    UserOrGroupPermissionDatas[pos].IsAllowed = true;
                    UserOrGroupPermissionDatas[pos].IsNotPermissionInGroup = false;
                }
            }

            #region  当前用户若是user并且没有被授权可以修改指定权限，则该用户只能查看该权限。20100715.
            string AllowOperationDataConnection = UserParametersInfo.GetUserSystemParameter(EMUserDefaultInfoType.AllowOperationDataConnection, userIID);
            bool CanCurrentUserAllowed = false;
            if (string.Equals(AllowOperationDataConnection, "1", StringComparison.OrdinalIgnoreCase))
            {
                CanCurrentUserAllowed = true;
            }
            else
            {
                CanCurrentUserAllowed = false;
            }
            if (!CanCurrentUserAllowed)
            {
                for (int i = 0; i < allPermissionList.Count; i++)
                {
                    bool CanThisPermissionSet = true;
                    CanThisPermissionSet = CanThisPermissionAllowed(allPermissionList[i].IID, true);
                    if (!CanThisPermissionSet)
                    {
                        UserOrGroupPermissionDatas[i].IsAllowed = false;
                        UserOrGroupPermissionDatas[i].IsNotPermissionInGroup = CanThisPermissionSet;
                    }
                    else
                    {
                        UserOrGroupPermissionDatas[i].IsNotPermissionInGroup = UserOrGroupPermissionDatas[i].IsNotPermissionInGroup && CanThisPermissionSet;
                    }
                }
            }
            #endregion

            return UserOrGroupPermissionDatas.ToArray();
        }







        /// <summary>
        /// 当前用户若是user并且没有被授权可以修改指定权限，则该用户只能查看该权限，主要是与创建DC相关的权限。
        /// </summary>
        /// <param name="iid"></param>
        /// <param name="isFiltered"></param>
        /// <returns></returns>
        private static bool CanThisPermissionAllowed(string iid, bool isFiltered)
        {
            if (!isFiltered) return true;

            bool result = false;
            switch (iid.ToUpper())
            {
                case "67519B95-DED6-4213-B99B-000143A26608":///Import Packages
                    break;
                case "041CA49F-2843-475F-9951-1680CBC720C6":///Export Data Connections
                    break;
                case "C5749051-C325-47C6-BEB7-A764BBA45B52":///Create Packages
                    break;
                case "F80DAC30-63C0-4F69-AE36-AA2C4B65ED56":///Import Data Connections
                    break;
                case "0DA897EE-396C-465E-AE1C-B1EF69D40DE6":///Connection Types
                    break;
                case "D5D2EC1D-96DB-4500-A6CA-E4952C72D500":///Data Connections
                    break;
                case "C76328E2-20B3-4ECB-B787-7221DFB3BC34":///Purge Packages
                    break;
                case "C96E16A3-B93A-40F4-BCA7-535EFC600970":///Generate License Keys
                    break;
                default:
                    result = true;
                    break;
            }

            return result;
        }
        private static List<string> GetMaxUserGroupOperationPermissionsOfUser(string userIID)
        {
            try
            {
                List<string> result = new List<string>();
                var db = SystemParams.FICDBInstance;
                //const string sql = @"select * from OperationRight where ObjectType={0} 
                //                 and ObjectID in (select GroupID from UserGroupRelation where UserID={1})";
                string sql = @"select * from OperationRight where ObjectType={0} 
                                and ObjectID in ({GIDS})";

                List<string> gidList = GetUserGroupIDByUserIID(userIID);
                string gids = "'" + string.Join("','", gidList) + "'";
                sql = sql.Replace("{GIDS}", gids);
                var dt = db.GetDataTableBySQL(sql, (int)DBObjectType.otGroup, userIID);

                foreach (DataRow row in dt.Rows)
                {
                    if (FIDbAccess.GetFieldString(row["RightValue"], string.Empty) == "1")
                    {
                        if (!result.Contains(FIDbAccess.GetFieldString(row["FunctionID"], Guid.Empty.ToString())))
                            result.Add(FIDbAccess.GetFieldString(row["FunctionID"], Guid.Empty.ToString()));
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                throw FIError.Exception(0x65027029, ex);
            }
        }

        private static int GetPermissionFunctionIndex(string iid, List<Operations> allPermissionList)
        {
            int i = -1;
            if (allPermissionList == null) return i;

            for (int ind = 0; ind < allPermissionList.Count; ind++)
            {
                if (allPermissionList[ind].IID.ToUpper() == iid.ToUpper())
                {
                    i = ind;
                    break;
                }
            }

            return i;
        }

        private static DataTable GetUserGroupOperationPermissions(string groupIID)
        {
            const string sql = "select * from OperationRight where ObjectID={0} and ObjectType={1}";
            try
            {
                var db = SystemParams.FICDBInstance;
                return db.GetDataTableBySQL(sql, groupIID, (int)DBObjectType.otGroup);
            }
            catch (Exception ex)
            {
                throw FIError.Exception(0x65027025, ex);
            }
        }

        private static DataTable GetUserOperationPermissions(string userIID)
        {
            const string sql = "select * from OperationRight where ObjectID={0} and ObjectType={1}";
            try
            {
                var db = SystemParams.FICDBInstance;
                return db.GetDataTableBySQL(sql, userIID, (int)DBObjectType.otUser);
            }
            catch (Exception ex)
            {
                throw FIError.Exception(0x65027024, ex);
            }
        }

        private static List<Operations> GetOperationPermissions()
        {
            List<Operations> oprtions = new List<Operations>();
            const string sql = "select * from Operations order by OrderIndex,FunctionName";
            try
            {
                var db = SystemParams.FICDBInstance;
                DataTable dt = db.GetDataTableBySQL(sql);
                foreach (DataRow row in dt.Rows)
                {
                    Operations opr = new Operations();
                    opr.IID = FIDbAccess.GetFieldString(row["IID"], Guid.Empty.ToString());
                    opr.FunctionName = FIDbAccess.GetFieldString(row["FunctionName"], string.Empty);
                    opr.Description = FIDbAccess.GetFieldString(row["Description"], string.Empty);
                    opr.OrderIndex = FIDbAccess.GetFieldInt(row["OrderIndex"], 0);

                    oprtions.Add(opr);
                }

                return oprtions;
            }
            catch (Exception ex)
            {
                throw FIError.Exception(0x65027026, ex);
            }
        }
        #endregion

        #region Site Header Style
        public static StringKeyValue GetSiteHederStyleLogo(string sessionid)
        {
            const string SQL = "select STYLEID,LEN(s.CONTRACTORLOGO) CONTRACTORLOGO,LEN(s.DEALERLOGO) DEALERLOGO,LEN(s.DEFAULTLOCATIONLOGO) DEFAULTLOCATIONLOGO from USERS u left join SITETITLESTYLE s on u.SITETITLESTYLEID=s.STYLEID where USERIID={0}";

            var session = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid).GetLoginSession(sessionid);
            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL, session.User.UID);
            if (dt.Rows.Count == 0)
                return null;

            StringKeyValue kv = new StringKeyValue();
            kv.Key = FIDbAccess.GetFieldInt(dt.Rows[0]["STYLEID"], 0).ToString();
            kv.Tag1 = (FIDbAccess.GetFieldInt64(dt.Rows[0]["CONTRACTORLOGO"], 0) > 0).ToString();
            kv.Tag2 = (FIDbAccess.GetFieldInt64(dt.Rows[0]["DEALERLOGO"], 0) > 0).ToString();
            return kv;
        }

        public static int GetUserSiteTitleStyleID(string sessionid)
        {
            const string SQL = @"select SITETITLESTYLEID from USERS where USERIID={0}";

            var session = FleetServiceClientHelper.CreateClient<UserQueryClient>(sessionid).GetLoginSession(sessionid);
            FIDbAccess db = SystemParams.GetDbInstance();
            return FIDbAccess.GetFieldInt(db.GetRC1BySQL(SQL, session.User.UID), 0);
        }

        public static string GetSiteHeaderNote(string useriid)
        {
            const string SQL = "select s.SITEHEADERNOTE from SITETITLESTYLE s,USERS u where s.STYLEID=u.SITETITLESTYLEID and USERIID={0}";

            FIDbAccess db = SystemParams.GetDbInstance();
            return FIDbAccess.GetFieldString(db.GetRC1BySQL(SQL, useriid), string.Empty);
        }

        public static byte[] GetSiteHederStyleLogo(int styleid, int logotype)
        {
            const string SQL = "SELECT CONTRACTORLOGO,DEALERLOGO,DEFAULTLOCATIONLOGO FROM SITETITLESTYLE where STYLEID={0}";

            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL, styleid);
            if (dt.Rows.Count == 0)
                return null;

            DataRow dr = dt.Rows[0];

            byte[] buffer = null;
            if (logotype == 1)
                buffer = FIDbAccess.GetFieldBytes(dr["CONTRACTORLOGO"]);
            else if (logotype == 2)
                buffer = FIDbAccess.GetFieldBytes(dr["DEALERLOGO"]);
            else if (logotype == 3)
                buffer = FIDbAccess.GetFieldBytes(dr["DEFAULTLOCATIONLOGO"]);
            return buffer;
        }


        #endregion

        #region User Permission
        public static bool CheckUserPermission(string sessionid, string useriid, int permissionid)
        {
            bool isallowed = false;
            PermissionItem[] permissions = FleetServiceClientHelper.CreateClient<ContactClient>(sessionid).GetUserPermissions(SystemParams.CompanyID, useriid);
            if (permissions != null)
            {
                PermissionItem pi = permissions.FirstOrDefault(m => m.ID == permissionid);
                isallowed = pi == null ? false : pi.IsAllowed;
            }
            return isallowed;
        }
        #endregion
    }

}
