using System;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Threading.Tasks;
#if NET3
using Net3_Proxy;
#endif

namespace IPA.Injector
{
    internal static class PermissionFix
    {
        public static Task FixPermissions(DirectoryInfo root)
        {
            if (!root.Exists) return new Task(() => { });

            return Task.Factory.StartNew(() =>
            {
                try
                {
                    var acl = root.GetAccessControl();

                    var rules = acl.GetAccessRules(true, true, typeof(SecurityIdentifier));

                    var requestedRights = FileSystemRights.Modify;
                    var requestedInheritance = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
                    var requestedPropagation = PropagationFlags.InheritOnly;

                    bool hasRule = false;
                    for (var i = 0; i < rules.Count; i++)
                    {
                        var rule = rules[i];

                        if (rule is FileSystemAccessRule fsrule
                            && fsrule.AccessControlType == AccessControlType.Allow
                            && fsrule.InheritanceFlags.HasFlag(requestedInheritance)
                            && fsrule.PropagationFlags == requestedPropagation
                            && fsrule.FileSystemRights.HasFlag(requestedRights))
                        { hasRule = true; break; }
                    }

                    if (!hasRule)
                    { // this is *sooo* fucking slow on first run
                        acl.AddAccessRule(
                            new FileSystemAccessRule(
                                new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                                requestedRights,
                                requestedInheritance,
                                requestedPropagation,
                                AccessControlType.Allow
                            )
                        );
                        root.SetAccessControl(acl);
                    }
                }
                catch (Exception e)
                {
                    Logging.Logger.log.Warn("Error configuring permissions in the game install dir");
                    Logging.Logger.log.Warn(e);
                }
            });
        }
    }
}
