using FinsTcp;
using GeneralData;
using HardwareData;
using ModBusTcp;
using ORM;
using ProtocalGeneral;
using RTCommunicatorBase;
using RTCommunicatorTLV;
using SqlSugarORM;
using Universal;
using Universal.IO;

namespace Test;

internal class Program
{
    static void Main()
    {

        //RingBuffer<int> ring = new(5);

        //for (int i = 1; i <= 19; i++)
        //{
        //    ring.Insert(i);

        //}
        //var t = ring.ReadValues();

        //string DBConnectionString = "Database=postgres;Password=123456;Host=localhost;Username=postgres;Persist Security Info=True";
        //int start = DBConnectionString.IndexOf('=') + 1;
        //int end = DBConnectionString.IndexOf(';');
        //string newDbString1 = DBConnectionString[..start];
        //string newDBString2 = DBConnectionString[end..];

        //string newDBS = $"{newDbString1}{DateTime.Now:yyyy_MM_dd_HH_mm_ss}{newDBString2}";
        //TestClass testClass = new();
        //testClass.SetFile();

        //CreateUser cu = new();
        //cu.Create();

        //TestFins test = new();
        //test.TestFinsP();

        TestClass test = new();
        test.RunOnce();
        Thread.Sleep(-1);
    }
}


public class TestFins : ITcpConnectNority
{
    public void Connect(string ip, int port)
    {
        Console.WriteLine($"Connected {ip}:{port}");
    }

    public void DisConnect(string ip, int port)
    {
        Console.WriteLine($"Disconnected {ip}:{port}");
    }

    public void Test()
    {
        //POmronFinsTCP.Net.EtherNetPLC
        //FinsTCP service = new();
        //var result = service.Link("192.168.250.1", 9600);
        //service.SetData<bool>("D1061.1", true);
        //service.SetData<float>("D14022", 2f);
        //float f = service.GetData<float>("D14022");
    }

    Fins_Tcp fins = new();
    public void TestFinsP()
    {
        fins.Initialize(this);
        fins.Connect("192.168.250.1", 9600, HeartBeatCallBack);
        //fins.StartHeartBeat(HeartBeatCallBack);
        while (true)
        {
            bool b = fins.SetData<bool>("D1061.1", true);
            Console.WriteLine($"Heart beat {b}");

            Thread.Sleep(1000);
        }
        //b = fins.GetData<bool>("D1061.1", out bool re);

        //b = fins.SetData<float>("D14022", 3f);
        //b = fins.GetData<float>("D14022", out float f);

    }

    private bool HeartBeatCallBack()
    {
        return fins.SetData<bool>("D1061.1", true);
    }

}

public class CreateUser
{
    public void Create()
    {
        IORM orm = new SqlSugarCustom();
        orm.Initialize();
        orm.Open("Database=postgres;Password=123456;Host=localhost;Username=postgres;Persist Security Info=True", DbType.PostgreSQL);
        orm.CreateTable<UserInfo>("UserAuthority");

        UserInfo userInfo = new()
        {
            UserName = "Operator",
            Password = "Aa123456".ToBase64(),
            Authority = UserAuthority.Operator
        };
        orm.Insert<UserInfo>("UserAuthority", userInfo);

        userInfo = new()
        {
            UserName = "Engineer",
            Password = "Aa123456".ToBase64(),
            Authority = UserAuthority.Engineer
        };
        orm.Insert<UserInfo>("UserAuthority", userInfo);
    }
}

public class TestClass : IRTMini8Provider
{
    public void Connected(string ip, int port)
    {
        Console.WriteLine($"ConnectedNotify {ip} {port}");
    }

    public void DisConnected(string ip, int port)
    {
        Console.WriteLine($"DisConnectedNotify {ip} {port}");
    }

    //Singleton Mode
    private RTCommunicator_TLV communicator = new();

    public void RunOnce()
    {
        communicator = new();
        communicator.Initialize(this);
        communicator.StartService("127.0.0.1", 50052);
    }

    public void SetFile()
    {
        communicator.SelectConfigFile("Minics Config 1");
    }

    public void End()
    {
        communicator.CloseService();
    }

    void IRTMini8Provider.CurrentTempConfigFile(string fileName)
    {
    }

    void IConnectNotify.Connected(string ip, int port)
    {
        Console.WriteLine($"Connected {ip}:{port}");
    }

    void IConnectNotify.DisConnected(string ip, int port)
    {
        Console.WriteLine($"Disconnected {ip}:{port}");

    }

    public void ChannelAlarmNotify(ST_ALARM_Notify alarm)
    {
        Console.WriteLine($"Alarm Mini8 {alarm.Mini8Index}-{alarm.ChannelIndex:00} {alarm.PV:000.00} {alarm.Caps:000.00} {alarm.Floor:000.00} {alarm.AlarmType} {alarm.HeaterType}");
    }

    public void Mini8ConnectNotify(byte mini8Index)
    {
        Console.WriteLine($"Mini8 Connected {mini8Index}");
    }

    public void Mini8DisconnectNotify(byte mini8)
    {
        Console.WriteLine($"Mini8 Disconnected {mini8}");
    }

    public void ChannelRealtimeNotify(ST_CHANNEL_Notify channel)
    {
        Console.WriteLine($"{DateTime.Now:HH:mm:ss.f} Mini8 {channel.Mini8Index} Channel {channel.ChannelIndex} {channel.PV} {channel.WorkingOutput}");
    }
}

interface ITest
{
    void Run();
}


class TestSerialXML
{
    public static void Test()
    {
        //Mini8Address mini8Address = new()
        //{
        //    Address = "192.168.250.11",
        //    Port = 502
        //};

        ChannelAddress address = new()
        {
            Mini8Index = 1,
            ChannelIndex = 2,
            //TcBorken = new(1, TypeCode.Single, AddressType.Input, RW_Access.Read),
            //CurrentTemp = new(2, TypeCode.Single, AddressType.Input, RW_Access.Read),
            //Target = new(3, TypeCode.Single),
            //Caps = new(4, TypeCode.Single),
            //Floor = new(5, TypeCode.Single),
            //Delay = new(6, TypeCode.Single),
            //P = new(7, TypeCode.Single),
            //I = new(8, TypeCode.Single),
            //D = new(9, TypeCode.Single)
        };

        XmlFileHelper.WriteFile(@"E:\address.xml", address);
        XmlFileHelper.ReadFile(@"E:\address.xml", out ChannelAddress? channel);
        Console.WriteLine(channel);
    }

}

//class TestModbus
//{

//    public static void Tests()
//    {

//        string address = "192.168.250.11";
//        ushort port = 502;

//        Modbus_Nmodbus modbus = new();
//        modbus.Initialize("T");

//        Console.WriteLine($"Open {address}:{port} --{modbus.Open(address, port)}");

//        //await modbus.SetValue<float>(15694, 50);
//        //await modbus.SetValues<float>(15694, [60, 70]);
//        //await modbus.SetValue<float>(15532, 20);

//        modbus.GetFloat(41014, out float? test);

//        Console.WriteLine();
//        Console.WriteLine("Read PVs");
//        modbus.GetFloats(15500, 16, out float[]? fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00") + "℃"));

//        Console.WriteLine();
//        Console.WriteLine("Read Work Out Percentage");
//        modbus.GetFloats(15532, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00") + "%"));

//        Console.WriteLine();
//        Console.WriteLine("Read AT Status");
//        ushort[]? us = modbus.GetUshort(15564, (ushort)16);
//        us!.Foreach(t => Console.WriteLine((AutoTune)t));

//        Console.WriteLine();
//        Console.WriteLine("Read AutoTune P");
//        modbus.GetFloats(15596, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00")));

//        Console.WriteLine();
//        Console.WriteLine("Read AutoTune I");
//        modbus.GetFloats(15628, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00")));

//        Console.WriteLine();
//        Console.WriteLine("Read AutoTune D");
//        modbus.GetFloats(15660, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00")));

//        Console.WriteLine();
//        Console.WriteLine("Read SetPoint");
//        modbus.GetFloats(15694, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00") + "℃"));

//        Console.WriteLine();
//        Console.WriteLine("Read Active TuneSet");
//        us = modbus.GetUshort(15726, (ushort)16);
//        us!.Foreach(t => Console.WriteLine((ActiveTuneSet)t));

//        Console.WriteLine();
//        Console.WriteLine("Read Running P");
//        modbus.GetFloats(15758, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00")));

//        Console.WriteLine();
//        Console.WriteLine("Read Running I");
//        modbus.GetFloats(15780, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00")));

//        Console.WriteLine();
//        Console.WriteLine("Read Running D");
//        modbus.GetFloats(15822, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00")));

//        Console.WriteLine();
//        Console.WriteLine("Read Up Rate");
//        modbus.GetFloats(15860, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00") + "℃/Min"));

//        Console.WriteLine();
//        Console.WriteLine("Read Down Rate");
//        modbus.GetFloats(15892, 16, out fs);
//        fs!.Foreach(t => Console.WriteLine(t.ToString("0.00") + "℃/Min"));

//        Console.WriteLine();
//        Console.WriteLine("Read TC Broken");
//        modbus.GetBits(15692, out byte[]? bits);
//        bits!.For(0, 8, t => Console.WriteLine((TcBorken)t));
//        modbus.GetBits(15693, out bits);
//        bits!.For(0, 8, t => Console.WriteLine((TcBorken)t));

//        Console.WriteLine();
//        Console.WriteLine("Read Inhibit");
//        modbus.SetUshort(15854, 252);
//        modbus.SetUshort(15855, 255);
//        modbus.SetUshort(15855, 255);
//        modbus.GetBits(15854, out bits);
//        bits!.For(0, 8, t => Console.WriteLine((Active)t));
//        modbus.GetBits(15855, out bits);
//        bits!.For(0, 8, t => Console.WriteLine((Active)t));


//        Console.WriteLine();
//        Console.WriteLine("Read Auto Tune Active");
//        modbus.SetUshort(15858, 255);
//        modbus.SetUshort(15859, 255);
//        modbus.GetBits(15858, out bits);
//        bits!.For(0, 8, t => Console.WriteLine((Active)t));

//        modbus.GetBits(15859, out bits);
//        bits!.For(0, 8, t => Console.WriteLine((Active)t));

//    }
//}

class TestModbus_FluentModbus
{
    public static void Test()
    {
        //IPAddress ipAddress = IPAddress.Parse("192.168.250.11");
        //IPEndPoint endPoint = new(ipAddress, 502);

        //ModbusTcpClient client = new();
        //client.Connect(endPoint);



        //Span<byte> t = client.ReadHoldingRegisters(0x00, 15500, 500);
        //Span<byte> t2 = client.ReadHoldingRegisters(0x00, 15564, 1);
        Modbus_Tcp client = new();
        client.Open("192.168.250.11", 502);
        byte[]? buffer = client.GetBuffer(4962, 32);
        //client.SetFloat(4962, 32.1f);
        client.SetUshort(4962, 1);
        buffer = client.GetBuffer(4962, 1);
        ushort s = BufferToUshort(buffer);
    }
    private static unsafe ushort BufferToUshort(byte[]? bytes)
    {
        if (bytes is null)
            return ushort.MaxValue;
        Span<byte> sb = bytes.AsSpan<byte>();
        sb.Reverse();

        fixed (byte* pByte = sb)
        {
            ushort* pResult = (ushort*)pByte;
            return *pResult;
        }
    }

}

enum TcBorken : byte
{
    Normal = 0,
    Error
}

enum Active : byte
{
    On = 0,
    Off = 1,
}

enum ActiveTuneSet : ushort
{
    AutoTune = 0,
    Running
}

enum AutoTune : ushort
{
    Unavailable = 0,
    Ready,
    Triggered,
    Running,
    Complete,
    Aborted,
    Timeout,
    Overflow
}

class YieldTest
{
    public static IEnumerable<int> Test()
    {
        for (int i = 0; i < 10; i++)
        {
            if (i == 1)
                yield return -1;

            yield return i;
        }
    }
}

class ORMTest : IOrmProvider
{
    public int Test1 { get; set; }
    public int Test2 { get; set; }

    public void Log(string log, DateTime dateTime, LogLevel logLevel)
    {
        Console.WriteLine($"{logLevel}-{dateTime:hh:mm:ss} {log}");
    }

    public async Task Test()
    {
        IORM orm = new SqlSugarCustom();
        orm.Initialize(this);
        orm.Open("Database=postgres;Password=123456;Host=localhost;Username=postgres;Persist Security Info=True", DbType.PostgreSQL);
        //orm.CreateDataBase("Minics");
        orm.CreateTable<ORMTest>("OrmTest1");
        //await orm.Insert<ORMTest>("OrmTest1", new() { Test1 = 1, Test2 = 1 });
        await orm.Query<ORMTest>("OrmTest1", Result);
        await orm.Query<ORMTest>("OrmTest1", t => t.Test1 == 1, Result);
    }

    void Result(List<ORMTest> oRMTests)
    {
        Console.WriteLine(oRMTests.Count);
    }
}
