using EVCB_OCPP.WSServer.Service.WsService;
using Microsoft.AspNetCore.Builder;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EVCB_OCPP.WSServer.Service;

public static class MapApiServceExtention
{
    public static void MapApiServce(this WebApplication webApplication)
    {
        var helpFunc = () => {
            return string.Join("\r\n", new[] {
                    "Command help!!",
                    "lcn : List Customer Name",
                    "gc : GC Collect",
                    "lc : List Clients",
                    "silent : silent",
                    "show : show log"
                });
        };
        webApplication.MapGet("/", helpFunc);
        webApplication.MapGet("/help", helpFunc);

        webApplication.MapPost("/stop", (ProtalServer server) => {
            server.Stop();
            return "Command stop";
        });

        webApplication.MapPost("/gc", () => {
            GC.Collect();
            return "Command GC";
        });

        webApplication.MapPost("/lc", (ProtalServer server) => {
            List<string> toReturn = new List<string>() { "Command List Clients" };
            Dictionary<string, WsClientData> clientDic = server.GetClientDic();
            var list = clientDic.Select(c => c.Value).ToList();
            int i = 1;
            foreach (var c in list)
            {
                toReturn.Add(i + ":" + c.ChargeBoxId + " " + c.SessionID);
                i++;
            }
            return string.Join("\r\n", toReturn);
        });

        webApplication.MapPost("/lcn", (ProtalServer server) => {
            List<string> toReturn = new List<string> { "Command List Customer Name" };
            Dictionary<string, WsClientData> clientDic = server.GetClientDic();
            var lcn = clientDic.Select(c => c.Value.CustomerName).Distinct().ToList();
            int iLcn = 1;
            foreach (var c in lcn)
            {
                toReturn.Add(iLcn + ":" + c + ":" + clientDic.Where(z => z.Value.CustomerName == c).Count().ToString());
                iLcn++;
            }
            return string.Join("\r\n", toReturn);
        });

        webApplication.MapPost("/silent", () => {
            foreach (var rule in LogManager.Configuration.LoggingRules)
            {
                if (rule.RuleName != "ConsoleLog")
                {
                    continue;
                }

                var isTargetRule = rule.Targets.Any(x => x.Name.ToLower() == "console");

                if (isTargetRule)
                {
                    rule.SetLoggingLevels(NLog.LogLevel.Warn, NLog.LogLevel.Off);
                }
            }
            return "Command silent";
        });

        webApplication.MapPost("/show", () => {
            foreach (var rule in LogManager.Configuration.LoggingRules)
            {
                if (rule.RuleName != "ConsoleLog")
                {
                    continue;
                }

                var isTargetRule = rule.Targets.Any(x => x.Name.ToLower() == "console");

                if (isTargetRule)
                {
                    rule.SetLoggingLevels(NLog.LogLevel.Trace, NLog.LogLevel.Off);
                }
            }
            return "Command show";
        });

        webApplication.MapGet("/threads", () => {
            ThreadPool.GetMaxThreads(out var maxWorkerThread, out var maxCompletionPortThreads);
            ThreadPool.GetAvailableThreads(out var avaliableWorkerThread, out var avaliableCompletionPortThreads);
            return $"WorkerThread:{avaliableWorkerThread}/{maxWorkerThread} CompletionPortThreads{avaliableCompletionPortThreads}/{maxCompletionPortThreads}";
        });

        webApplication.MapPost("/threads", (int min, int max) => {
            ThreadPool.GetMaxThreads(out var maxWorkerThread, out var maxCompletionPortThreads);
            ThreadPool.GetAvailableThreads(out var avaliableWorkerThread, out var avaliableCompletionPortThreads);
            ThreadPool.SetMinThreads(min, 0);
            ThreadPool.SetMaxThreads(max, maxCompletionPortThreads);
            return $"WorkerThread:{avaliableWorkerThread}/{maxWorkerThread} CompletionPortThreads{avaliableCompletionPortThreads}/{maxCompletionPortThreads}";
        });
    }
}