using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using InABox.Core;

namespace InABox.Core
{
    
    public class Profiler : IDisposable
    {
        private Stopwatch _stopwatch;
        protected string MethodName { get; set; }
        public string? ClassName { get; set; }
        private bool _logOnDispose = false;

        public Profiler(bool logOnDispose, [CallerMemberName] string methodName = "") : base()
        {
            _logOnDispose = logOnDispose;
            MethodName = methodName;
            _stopwatch = new Stopwatch();
            _stopwatch.Start();
        }

        public long GetElapsedMilliseconds() => _stopwatch.ElapsedMilliseconds;
        public void Pause() => _stopwatch.Stop();
        public void Resume() => _stopwatch.Start();
        public long Restart()
        {
            var ms = _stopwatch.ElapsedMilliseconds;
            _stopwatch.Restart();
            return ms;
        }

        public void Log()
        {
            _stopwatch.Stop();
            Logger.Send(LogType.Information, "", $"- {MethodName}{ClassName}() returned in {_stopwatch.ElapsedMilliseconds}ms");
            _stopwatch.Restart();
        }

        public void Log(int count)
        {
            _stopwatch.Stop();
            Logger.Send(LogType.Information, "", $"- {MethodName}{ClassName}() returned {count} items in {_stopwatch.ElapsedMilliseconds}ms");
            _stopwatch.Restart();
        }

        public void Log(string name)
        {
            _stopwatch.Stop();
            Logger.Send(LogType.Information, "", $"- {MethodName}{ClassName}() [{name}] returned in {_stopwatch.ElapsedMilliseconds}ms");
            _stopwatch.Restart();
        }

        public void Log(string format, params object[] values)
        {
            _stopwatch.Stop();
            Logger.Send(LogType.Information, "", $"- [{String.Format(format,values)}] returned in {_stopwatch.ElapsedMilliseconds}ms");
            _stopwatch.Restart();
            
        }

        public void Dispose()
        {
            if (_logOnDispose)
                Log();
            _stopwatch?.Stop();
            _stopwatch = null;
        }

        public void Dispose(int count)
        {
            if (_logOnDispose)
                Log(count);
            _stopwatch?.Stop();
            _stopwatch = null;
        }
    }
    
    public class Profiler<T> : Profiler
    {
        public Profiler(bool logOnDispose, [CallerMemberName] string methodName = "") : base(logOnDispose, methodName)
        {
            ClassName = typeof(T).Name.Split('.').Last();
        }
    }
}