using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Runtime.CompilerServices;

using C4IT.Logging;
using C4IT.MsGraph;
using static C4IT.Logging.cLogManager;
using C4IT.Matrix42.ServerInfo;
using static C4IT.MsGraph.cMsGraphSharepoint;

namespace C4IT.LIAM
{
    public static class LiamInitializer
    {
        public static Guid msTeamsModuleId = new Guid("2591832a-1b25-ec11-6985-00155d300101");
        static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
        {
            return new cLiamProviderMsTeams(LiamConfiguration, ProviderData);
        }
    }

    public class cLiamProviderMsTeams : cLiamProviderBase
    {
        public readonly cMsGraphSharepoint MsSharepoint = new cMsGraphSharepoint(new cMsGraphBase());
        public const string allowedMailNickNameCharacter = @"[^A-Za-z0-9!#$%&'*+\-/=?^_`{|}~]";

        public readonly bool WithoutPrivateChannels = true;

        public cLiamProviderMsTeams(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
            base(LiamConfiguration, ProviderData)
        {
            WithoutPrivateChannels = AdditionalConfiguration.ContainsKey("WithoutPrivateChannels") ? AdditionalConfiguration["WithoutPrivateChannels"].ToLower() == "true" || AdditionalConfiguration["WithoutPrivateChannels"] == "1" : false;
        }

        public override async Task<bool> LogonAsync()
        {
            return await LogonAsync(true);
        }

        public async Task<bool> LogonAsync(bool force = false)
        {
            if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
            {
                LogEntry($"Error: License not valid", LogLevels.Error);
                return false;
            }
            if (!force && this.MsSharepoint.Base.IsOnline)
                return true;

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                var LI = new cMsGraphLogonInfo() {
                    Tenant = this.Domain,
                    ClientID = this.Credential?.Identification,
                    ClientSecret = this.Credential?.Secret
                };
                var RetVal = await MsSharepoint.Base.LogonAsync(LI);
                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return false;
        }

        public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int Depth = -1)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!await LogonAsync())
                    return null;

                var DataAreas = new List<cLiamDataAreaBase>();

                var DAL = await MsSharepoint.RequestTeamsListAsync();
                if (DAL == null)
                    return null;

                foreach (var Entry in DAL)
                {
                    if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(Entry.Key, this.DataAreaRegEx).Success)
                        continue;

                    var MsTeam = await MsSharepoint.RequestGroupInfoAsync(Entry.Value);
                    if (MsTeam == null)
                        continue;

                    var Team = new cLiamMsTeamsTeam(this, MsTeam);
                    DataAreas.Add(Team);
                }

                if (Depth > 0)
                {
                    var allChilds = new List<cLiamDataAreaBase>();
                    foreach (var Entry in DataAreas)
                    {
                        var entryChilds = await (Entry as cLiamMsTeamsTeam).getChannels(true);
                        if (entryChilds != null && entryChilds.Count > 0)
                            allChilds.AddRange(entryChilds);
                    }
                    DataAreas.AddRange(allChilds);
                }

                return DataAreas;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return null;
        }

        public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                var lstIds = UID.Split('|');

                switch (lstIds.Length)
                {
                    case 4:
                        var FO = await cLiamMsTeamsFolder.Load(this, UID);
                        return FO;
                    case 2:
                        var CH = await cLiamMsTeamsChannel.Load(this, UID);
                        return CH;
                    case 1:
                        var TM = await cLiamMsTeamsTeam.Load(this, UID);
                        return TM;
                }
                
                return null;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }

        }

        public static string getUidItem(ref string UID)
        {
            try
            {
                var p = UID.IndexOf('|');
                if (p >= 0)
                {
                    var Item = UID.Substring(0, p);
                    UID = UID.Remove(0, p + 1);
                    UID = UID.TrimStart();
                    return Item.Trim();
                }


            }
            catch { };

            var h2 = UID;
            UID = "";
            return h2;
        }

        public static cMsGraphResultPermission.ePermissionRole getMsGraphRole(eLiamAccessRoles LiamRole)
        {
            switch (LiamRole)
            {
                case eLiamAccessRoles.Owner:
                    return cMsGraphResultPermission.ePermissionRole.owner;
                case eLiamAccessRoles.Write:
                    return cMsGraphResultPermission.ePermissionRole.write;
                default:
                    return cMsGraphResultPermission.ePermissionRole.read;
            }
        }

        public static eLiamAccessRoles getLiamRole(cMsGraphResultPermission.ePermissionRole MsGraphRole)
        {
            switch (MsGraphRole)
            {
                case cMsGraphResultPermission.ePermissionRole.owner:
                    return eLiamAccessRoles.Owner;
                case cMsGraphResultPermission.ePermissionRole.write:
                    return eLiamAccessRoles.Write;
                default:
                    return eLiamAccessRoles.Read;
            }
        }

        public override Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
        {
            throw new NotImplementedException();
        }

        public override string GetLastErrorMessage()
        {
            throw new NotImplementedException();
        }

        public async Task<cMsGraphResultBase> cloneTeam(string teamId, string name, string description, int visibility, int partsToClone, string additionalMembers, string additionalOwners)
        {
            var request = new CloneTeamRequest()
            {
                DisplayName = name,
                Visibility = (CloneTeamRequest.TeamVisibilityType)visibility,
                MailNickname = Regex.Replace(name, allowedMailNickNameCharacter, ""),
                Description = description
            };
            request.SetClonableParts((CloneTeamRequest.ClonableTeamParts)partsToClone);
            var res = await MsSharepoint.CloneTeam(teamId, request);
            return res;
        }
    }

    public class cLiamMsTeamsTeam : cLiamDataAreaBase
    {
        public new readonly cLiamProviderMsTeams Provider = null;

        private readonly cMsGraphResultGroup MsTeam = null;

        public cLiamMsTeamsTeam(cLiamProviderMsTeams Provider, cMsGraphResultGroup MsTeam) :
            base(Provider)
        {
            this.Provider = Provider;
            this.MsTeam = MsTeam;

            this.TechnicalName = getUID(MsTeam.ID);
            this.DisplayName = MsTeam.DisplayName;
            this.Level = 0;
            this.UID = getUID(MsTeam.ID);
            this.ParentUID = "";
            this.DataType = eLiamDataAreaTypes.MsTeamsTeam;
            this.SupportsOwners = true;
            this.SupportsPermissions = true;
        }

        internal static string getUID(string TeamID)
        {
            return $"{TeamID}";
        }

        internal async Task<List<cLiamDataAreaBase>> getChannels(bool OnlyPrivate)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (MsTeam == null)
                    return null;

                var RegExFilter = this.Provider?.DataAreaRegEx;
                var SP = this.Provider?.MsSharepoint;
                var WithoutPrivateChannels = this.Provider?.WithoutPrivateChannels ?? false;

                if (MsTeam.Channels == null)
                    if (SP == null || !await MsTeam.ResolveChannels(SP, OnlyPrivate))
                        return null;

                var RetVal = new List<cLiamDataAreaBase>(MsTeam.Channels.Count);
                foreach (var Entry in MsTeam.Channels.Values)
                {
                    if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
                        continue;
                    if (WithoutPrivateChannels && !string.IsNullOrEmpty(Entry.MembershipType) && Entry.MembershipType == "private")
                        continue;

                    var DA = new cLiamMsTeamsChannel(Provider, this, Entry);
                    RetVal.Add(DA);
                }

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                var RetVal = await getChannels(false);
                if (RetVal != null)
                    RetVal.AddRange(await getChildrenFromListAsync(RetVal, Depth));

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        public static async Task<cLiamMsTeamsTeam> Load(cLiamProviderMsTeams Provider, string UID)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                var arrIDs = UID.Split('|');
                if (arrIDs.Length != 1)
                    return null;

                var TeamID = cLiamProviderMsTeams.getUidItem(ref UID);

                var T = await Provider.MsSharepoint.RequestGroupInfoAsync(TeamID);
                if (T == null)
                    return null;

                var RetVal = new cLiamMsTeamsTeam(Provider, T);

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }


        }

        public override async Task<List<cLiamUserInfo>> GetOwnersAsync()
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                return await GetMembersAsync(true);
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private async Task<List<cLiamUserInfo>> GetMembersAsync(bool owners)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                var SP = this.Provider?.MsSharepoint;
                if (SP == null)
                {
                    LogEntry($"Could not get Sharepoint class from Provider for Team '{this.TechnicalName}'", LogLevels.Warning);
                    return null;
                }

                cMsGraphCollectionUsers lstMembers;
                if(owners)
                    lstMembers = await MsTeam.GetOwnersAsync(SP);
                else
                    lstMembers = await MsTeam.GetMembersAsync(SP);
                if (lstMembers == null)
                {
                    LogEntry($"Could not get owner list for Team '{this.TechnicalName}'", LogLevels.Warning);
                    return null;
                }

                var RetVal = new List<cLiamUserInfo>(lstMembers.Count);
                LogEntry($"Owners for Team found: {lstMembers.Count}", LogLevels.Debug);
                foreach (var MemberEntry in lstMembers.Values)
                {
                    var User = new cLiamUserInfo()
                    {
                        DisplayName = MemberEntry.DisplayName,
                        GivenName = MemberEntry.GivenName,
                        SurName = MemberEntry.SurName,
                        UserPrincipalName = MemberEntry.UserPrincipalName,
                        EMail = MemberEntry.EMail,
                        SID = null
                    };
                    RetVal.Add(User);
                }

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        public override async Task<List<cLiamPermissionInfo>> GetPermissionsAsync(bool force = false)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                var RetVal = new List<cLiamPermissionInfo>();
                var owners = await GetOwnersAsync();
                foreach ( var owner in owners)
                {
                    var permission = new cLiamPermissionInfo()
                    {
                        User = owner,
                        AccessRole = eLiamAccessRoles.Owner
                    };
                    RetVal.Add(permission);
                }
                var members = await GetMembersAsync(false);
                foreach (var member in members)
                {
                    var permission = new cLiamPermissionInfo()
                    {
                        User = member,
                        AccessRole = eLiamAccessRoles.Write
                    };
                    RetVal.Add(permission);
                }
                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return null;
        }
        public override async Task<cLiamPermissionResult> GrantPermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
            {
                LogEntry($"Error: License not valid", LogLevels.Error);
                return null;
            }
            var result = new cLiamPermissionResult();

            if (Role == eLiamAccessRoles.Read)
            {
                return result;
            }
            try
            {
                var Roles = new List<cMsGraphResultPermission.ePermissionRole>()
                {
                    cLiamProviderMsTeams.getMsGraphRole(Role)
                };
               
                var UserInfo = await Provider.MsSharepoint.RequestUserInfoAsync(User.UserPrincipalName);
                if(string.IsNullOrEmpty(UserInfo?.ID))
                {
                    LogEntry($"Could not find user {User.UserPrincipalName}", LogLevels.Error);
                    return null;
                }
                var retVal = await Provider.MsSharepoint.AddGroupMembership(MsTeam, false, UserInfo);
                if(Role == eLiamAccessRoles.Owner)
                    retVal = await Provider.MsSharepoint.AddGroupMembership(MsTeam, true, UserInfo);
                result.Valid = retVal;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
            return result;
        }

        public override async Task<bool> RevokePermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
            {
                LogEntry($"Error: License not valid", LogLevels.Error);
                return false;
            }
            if (Role == eLiamAccessRoles.Read)
            {
                return false;
            }
            try
            {
                var Roles = new List<cMsGraphResultPermission.ePermissionRole>()
                {
                    cLiamProviderMsTeams.getMsGraphRole(Role)
                };

                var UserInfo = await Provider.MsSharepoint.RequestUserInfoAsync(User.UserPrincipalName);
                if (string.IsNullOrEmpty(UserInfo?.ODataId))
                {
                    LogEntry($"Could not find user {User.UserPrincipalName}", LogLevels.Error);
                    return false;
                }
                bool retVal = false;
                if (Role == eLiamAccessRoles.Owner)
                {
                    retVal = await Provider.MsSharepoint.DeleteGroupMembership(MsTeam, true, UserInfo);
                    retVal &= await Provider.MsSharepoint.DeleteGroupMembership(MsTeam, false, UserInfo);
                }
                if (Role == eLiamAccessRoles.Write)
                {
                    var members = await Provider.MsSharepoint.RequestGroupOwnersAsync(MsTeam.ID, UserInfo.ID);
                    if(members == null || members.Count == 0)
                    {
                        retVal = await Provider.MsSharepoint.DeleteGroupMembership(MsTeam, false, UserInfo);
                    }
                }
                return retVal;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
            return false;
        }

    }

    public class cLiamMsTeamsChannel : cLiamDataAreaBase
    {
        public new readonly cLiamProviderMsTeams Provider = null;
        public readonly cMsGraphResultChannel MsChannel = null;

        public cLiamMsTeamsChannel(cLiamProviderMsTeams Provider, cLiamMsTeamsTeam Team, cMsGraphResultChannel MsChannel, string TeamUID = null) : base(Provider)
        {
            this.Provider = Provider;
            this.MsChannel = MsChannel;

            this.TechnicalName = getUID(MsChannel.ID, TeamUID ?? Team?.UID ?? "*");
            this.DisplayName = MsChannel.DisplayName;
            this.Level = 1;
            this.UID = getUID(MsChannel.ID, TeamUID ?? Team?.UID ?? "*");
            if (Team != null)
                this.ParentUID = Team.UID;
            this.DataType = eLiamDataAreaTypes.MsTeamsChannel;
        }

        internal static string getUID(string ChannelID, string TeamUID)
        {
            return $"{ChannelID} | {TeamUID}";
        }

        public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                if (MsChannel == null)
                    return null;

                var RegExFilter = this.Provider?.DataAreaRegEx;
                var SP = this.Provider?.MsSharepoint;

                if (MsChannel.RootFolder == null)
                    if (SP == null || !await MsChannel.ResolveRootFolder(SP))
                        return null;

                if (MsChannel.RootFolder.Folders == null)
                    if (SP == null || !await MsChannel.RootFolder.ResolveFolders(SP))
                        return null;

                var DataAreas = new List<cLiamDataAreaBase>();
                foreach (var Entry in MsChannel.RootFolder.Folders.Values)
                {
                    if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
                        continue;

                    var DA = new cLiamMsTeamsFolder(this, Entry);
                    DataAreas.Add(DA);
                }
                DataAreas.AddRange(await getChildrenFromListAsync(DataAreas, Depth));

                return DataAreas;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        public static async Task<cLiamMsTeamsChannel> Load(cLiamProviderMsTeams Provider, string UID)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                var arrIDs = UID.Split('|');
                if (arrIDs.Length != 2)
                    return null;

                var ChannelID = cLiamProviderMsTeams.getUidItem(ref UID);
                var TeamID = cLiamProviderMsTeams.getUidItem(ref UID);

                var C = await Provider.MsSharepoint.RequestChannelInfo(TeamID, ChannelID);
                if (C == null)
                    return null;

                var RetVal = new cLiamMsTeamsChannel(Provider, null, C, TeamID);

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }


        }
    }

    public class cLiamMsTeamsFolder : cLiamDataAreaBase
    {
        public new readonly cLiamProviderMsTeams Provider = null;
        public readonly cLiamMsTeamsChannel Channel = null;
        public readonly string ChannelUID = null;
        public readonly cMsGraphResultFileObject MsFolder = null;


        public cLiamMsTeamsFolder(cLiamMsTeamsChannel Channel, cMsGraphResultFileObject MsFolder) : this(Channel.Provider, Channel, Channel, MsFolder) { }

        public cLiamMsTeamsFolder(cLiamMsTeamsFolder ParentFolder, cMsGraphResultFileObject MsFolder) : this(ParentFolder.Channel.Provider, ParentFolder.Channel, ParentFolder, MsFolder) { }

        private cLiamMsTeamsFolder(cLiamProviderMsTeams Provider, cLiamMsTeamsChannel Channel, cLiamDataAreaBase ParentFolder, cMsGraphResultFileObject MsFolder, string ChannelUID = null) : base(Provider)
        {
            this.Channel = Channel;
            if (Channel == null)
                this.ChannelUID = ChannelUID;
            else
                this.ChannelUID = Channel.UID;
            this.Provider = Provider;
            this.MsFolder = MsFolder;

            this.TechnicalName = MsFolder.DisplayName;
            this.DisplayName = MsFolder.DisplayName;
            if (ParentFolder != null)
            {
                this.Level = ParentFolder.Level + 1;
                this.ParentUID = ParentFolder.UID;
            }
            this.UID = getUID(MsFolder.ID, MsFolder.DriveID, ChannelUID ?? Channel?.UID ?? "*|*");
            this.DataType = eLiamDataAreaTypes.MsTeamsFolder;
            this.SupportsPermissions = true;
        }

        internal static string getUID(string FolderID, string DriveID, string ChannelUID)
        {
            return $"{FolderID} | {DriveID} | {ChannelUID}";
        }

        public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                if (MsFolder == null)
                    return null;

                var RegExFilter = this.Provider?.DataAreaRegEx;
                var SP = this.Provider?.MsSharepoint;

                if (MsFolder.Folders == null)
                    if (SP == null || !await MsFolder.ResolveFolders(SP))
                        return null;

                var DataAreas = new List<cLiamDataAreaBase>();
                foreach (var Entry in MsFolder.Folders.Values)
                {
                    if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
                        continue;

                    var DA = new cLiamMsTeamsFolder(this.Provider, this.Channel, this, Entry, this.ChannelUID);
                    DataAreas.Add(DA);
                }
                var CL = await getChildrenFromListAsync(DataAreas, Depth);
                if (CL != null)
                    DataAreas.AddRange(CL);

                return DataAreas;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
       }

        public static async Task<cLiamMsTeamsFolder> Load(cLiamProviderMsTeams Provider, string UID)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                var arrIDs = UID.Split('|');
                if (arrIDs.Length != 4)
                    return null;

                var FolderID = cLiamProviderMsTeams.getUidItem(ref UID);
                var DriveID = cLiamProviderMsTeams.getUidItem(ref UID);

                var F = await Provider.MsSharepoint.RequestFileObjectInfo(DriveID, FolderID);
                if (F == null)
                    return null;

                var RetVal = new cLiamMsTeamsFolder(Provider, null, null, F, UID);

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }


        }

        public override async Task<List<cLiamPermissionInfo>> GetPermissionsAsync(bool force = false)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                var RetVal = new List<cLiamPermissionInfo>();
                if (this.MsFolder.Permissions == null || force)
                    if (!await this.MsFolder.ResolvePermissions(Provider.MsSharepoint))
                        return null;

                if (this.MsFolder.Permissions == null)
                    return null;

                foreach (var Perm in this.MsFolder.Permissions)
                {
                    if (!(Perm is cMsGraphResultPermission.PermissionDirect) && !(Perm is cMsGraphResultPermission.PermissionLink))
                        continue;

                    if (Perm.isInherited)
                        continue;



                    if (Perm.Identities != null)
                    {
                        foreach (var Role in Perm.Roles)
                        {
                            var AccessRole = cLiamProviderMsTeams.getLiamRole(Role);

                            foreach (var Ident in Perm.Identities)
                            {
                                if (Ident.IdentityType != cMsGraphResultPermission.cMsGraphPermissionIdentity.eIdentityType.user)
                                    continue;

                                if (string.IsNullOrEmpty(Ident.EMail))
                                    continue;

                                if (!string.IsNullOrEmpty(Ident.ID))
                                {
                                    var GroupInfo = await Provider.MsSharepoint.RequestGroupInfoAsync(Ident.ID);
                                    if (GroupInfo != null)
                                        continue;
                                }

                                var Usr = Ident.EMail.ToLowerInvariant();
                                var alreadyFound = false;
                                foreach (var Entry in RetVal)
                                {
                                    if (Usr == Entry.User.EMail.ToLowerInvariant())
                                        if (AccessRole == Entry.AccessRole)
                                        {
                                            alreadyFound = true;
                                            break;
                                        }

                                }

                                if (!alreadyFound)
                                {
                                    var UsrInfo = new cLiamUserInfo()
                                    {
                                        DisplayName = Ident.DisplayName,
                                        EMail = Ident.EMail,
                                        UserPrincipalName = Ident.EMail
                                    };
                                    var PermInfo = new cLiamPermissionInfo()
                                    {
                                        User = UsrInfo,
                                        AccessRole = AccessRole
                                    };
                                    RetVal.Add(PermInfo);
                                }
                            }
                        }
                    }
                }

                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return null;
        }

        public override async Task<cLiamPermissionResult> GrantPermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return null;
                }
                var Roles = new List<cMsGraphResultPermission.ePermissionRole>()
                {
                    cLiamProviderMsTeams.getMsGraphRole(Role)
                };
                var RetVal = await this.MsFolder.AddPermission(Provider.MsSharepoint, Roles, cMsGraphResultPermission.eDriveReceipientType.email, User.EMail);
                if (RetVal == null)
                    return null;

                var RetVal2 = new cLiamPermissionResult();
                if (RetVal.Count>= 0)
                {
                    RetVal2.Valid = true;
                    var Perm = RetVal[0];
                    if (Perm is cMsGraphResultPermission.PermissionLink Link)
                    {
                        RetVal2.UserReference = Link.WebUrl;
                    }
                    else
                        RetVal2.UserReference = this.MsFolder.WebUrl;
                }
                
                return RetVal2;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }

        }

        public override async Task<bool> RevokePermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.msTeamsModuleId))
                {
                    LogEntry($"Error: License not valid", LogLevels.Error);
                    return false;
                }
                var myRole = cLiamProviderMsTeams.getMsGraphRole(Role);
                var RetVal = await this.MsFolder.RemovePermission(Provider.MsSharepoint, myRole, User.EMail);
                return RetVal;
            }
            catch (Exception E)
            {
                LogException(E);
                return false;
            }
            finally
            {
                LogMethodEnd(CM);
            }

        }

    }
}
