using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.IO;
using System.Diagnostics;

#if NET461
using System.Runtime.Caching;
#endif

#if NETFX || NETCORE
using System.Windows.Forms;
#endif


namespace Apewer
{

    /// <summary>核心方法。</summary>
    public class KernelUtility
    {

        /// <summary>强制对所有代进行即时垃圾回收。</summary>
        public static void Collect()
        {
            GC.Collect();
        }

        /// <summary>当前进程为 64 位。</summary>
        public static bool IsInX64
        {
#if NET20
            get { return IntPtr.Size == 8; }
#else
            get { return Environment.Is64BitProcess && IntPtr.Size == 8; }
#endif
        }

        #region Collect | Dispose

        /// <summary>开始自动释放内存,默认间隔为 1000 毫秒。</summary>
        public static void StartAutoFree()
        {
            KernelHelper.StartFree(1000);
        }

        /// <summary>开始自动释放内存,间隔以毫秒为单位。</summary>
        public static void StartAutoFree(int milliseconds)
        {
            KernelHelper.StartFree(milliseconds);
        }

        /// <summary>停止自动释放内存。</summary>
        public static void StopAutoFree()
        {
            KernelHelper.StopFree();
        }

        /// <summary>释放。</summary>
        public static void Dispose(object target, bool flush = false)
        {
            if (target == null) return;

            var stream = target as Stream;
            if (stream != null)
            {
                if (flush)
                {
                    try { stream.Flush(); } catch { }
                }
                try { stream.Close(); } catch { }
            }

            var disposable = target as IDisposable;
            if (disposable != null)
            {
                try
                {
                    disposable.Dispose();
                }
                catch { }
            }
        }

        /// <summary>释放。</summary>
        public static void Dispose<T>(IEnumerable<T> objects, bool flush = false)
        {
            if (objects != null)
            {
                foreach (var i in objects) Dispose(i, flush);
            }
        }

        #endregion

        #region Thread

        /// <summary>停止线程。</summary>
        public static void Abort(Thread thread)
        {
            if (thread == null) return;
            try
            {
                if (thread.IsAlive) thread.Abort();
            }
            catch { }
        }

        /// <summary>阻塞当前线程,时长以毫秒为单位。</summary>
        public static void Sleep(int milliseconds)
        {
            if (milliseconds > 0) Thread.Sleep(milliseconds);
        }

        /// <summary></summary>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public static Thread InBackground(Action action)
        {
            if (action == null) return null;
            var thread = new Thread(delegate (object v) { ((Action)v)(); });
            thread.IsBackground = true;
            thread.Start(action);
            return thread;
        }

        /// <summary>启动线程。</summary>
        public static Thread StartThread(Action action, bool background = true)
        {
            if (action == null) return null;
            var thread = new Thread(new ThreadStart(action));
            thread.IsBackground = background;
            thread.Start();
            return thread;
        }

        #endregion

        #region Assembly

        /// <summary>获取当前进程程序集的资源。</summary>
        public static byte[] GetAssemblyResource(string name)
        {
            var assembly = Assembly.GetExecutingAssembly();
            return GetAssemblyResource(assembly, name);
        }

        /// <summary>获取指定程序集的资源。</summary>
        public static byte[] GetAssemblyResource(Assembly assembly, string name)
        {
            var result = Constant.EmptyBytes;
            if (assembly == null) return null;
            try
            {
                var source = assembly.GetManifestResourceStream(name);
                result = StreamHelper.Read(source);
                Dispose(source);
            }
            finally { }
            return result;
        }

        /// <summary>获取已加载的程序集。</summary>
        public static Assembly[] GetLoadedAssemblies()
        {
            return AppDomain.CurrentDomain.GetAssemblies();
        }

        #endregion

        #region Cache

#if NET461

        /// <summary>设置缓存项。</summary>
        public static bool CacheSet(string key, object value, int minutes = 60)
        {

            if (TextUtility.IsEmpty(key)) return false;
            if (minutes < 1) return false;

            var policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes((double)NumberUtility.RestrictValue(minutes, 0, 525600));

            var instance = MemoryCache.Default;
            instance.Set(key, value, policy, null);
            return true;
        }

        /// <summary></summary>
        public static object CacheGet(string key)
        {
            if (TextUtility.IsEmpty(key)) return null;

            var instance = MemoryCache.Default;
            var entity = instance.Get(key, null);
            return entity;
        }

        /// <summary></summary>
        public static object CacheRemove(string key)
        {
            if (TextUtility.IsEmpty(key)) return null;

            var instance = MemoryCache.Default;
            var entity = instance.Remove(key, null);
            return entity;
        }

#endif

        #endregion

        #region Application

#if NETFX || NETCORE

        /// <summary>
        /// <para>System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase</para>
        /// <para>D:\Website\</para>
        /// </summary>
        public static string ApplicationBasePath
        {
            get { return AppDomain.CurrentDomain.SetupInformation.ApplicationBase; }
        }

        /// <summary>
        /// <para>System.Windows.Forms.Application.StartupPath</para>
        /// <para>c:\windows\system32\inetsrv</para>
        /// </summary>
        private static string StartupPath
        {
            get { return Application.StartupPath; }
        }

        /// <summary>
        /// <para>System.Windows.Forms.Application.ExecutablePath</para>
        /// <para>c:\windows\system32\inetsrv\w3wp.exe</para>
        /// </summary>
        public static string ExecutablePath
        {
            get { return Application.ExecutablePath; }
        }

#endif

        /// <summary>
        /// <para>System.AppDomain.CurrentDomain.BaseDirectory</para>
        /// <para>D:\Website\</para>
        /// </summary>
        private static string CurrentDomainPath
        {
            get { return AppDomain.CurrentDomain.BaseDirectory; }
        }

        /// <summary>
        /// <para>System.IO.Directory.GetCurrentDirectory()</para>
        /// <para>c:\windows\system32\inetsrv</para>
        /// </summary>
        private static string CurrentDirectory
        {
            get { return Directory.GetCurrentDirectory(); } // System.Environment.CurrentDirectory
        }

        /// <summary>
        /// <para>System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName</para>
        /// <para>c:\windows\system32\inetsrv\w3wp.exe</para>
        /// </summary>
        private static string ProcessMainModule
        {
            get { return Process.GetCurrentProcess().MainModule.FileName; }
        }

        #endregion

    }

}