using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace NetTunnelApp;

public partial class MainForm : Form
{
    private List<NetCard> _curNetCard = new List<NetCard>();
    private List<FilePath> _curFilePaths = new List<FilePath>();
    private UserClientCfg _userConfig = new UserClientCfg();

    private string _wireguardPath = string.Empty;

    public void GetCurrentNetCard()
    {
        IntPtr pt = new IntPtr(); //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NetCard)) * 32);
        int size = 0;

        var v = NetTunnelLib.GetAllNICInfo(out pt, ref size);

        _curNetCard.Clear();

        if (v == 0)
        {
            for (int i = 0; i < size; i++)
            {
                IntPtr ptr = new IntPtr(pt.ToInt64() + Marshal.SizeOf(typeof(NetCard)) * i);
                NetCard card = (NetCard)Marshal.PtrToStructure(ptr, typeof(NetCard));
                _curNetCard.Add(card);
            }
        }

        Marshal.FreeCoTaskMem(pt);
    }


    public MainForm()
    {
        InitializeComponent();

        var path = Environment.CurrentDirectory + "\\tunnelsdk_" +
                   string.Format("{0:yyyyMMdd}", DateTime.Now) + ".log";
        //NetTunnelLib.InitTunnelSDKLog(path, LogLevel.LOG_DEBUG);
        NetTunnelLib.TunnelSDKInitEnv(Environment.CurrentDirectory, "http://172.21.40.39:32549", path, LogLevel.LOG_TRACE, menuSetModeServer.Checked);
        //NetTunnelLib.EnableSCGProxy(true, "efc.xajhuang.com", 10001);
        GetCurrentNetCard();

        NetCardMenuItems menuItems = new NetCardMenuItems(_curNetCard);
        NetCardMenuItems ctxMenu = new NetCardMenuItems(_curNetCard);

        foreach (var item in menuItems.GetMenuItems())
        {
            menuSetModeShareNet.DropDownItems.Add(item);
        }

        foreach (var item in ctxMenu.GetMenuItems())
        {
            trapMenuSysInterface.DropDownItems.Add(item);
        }
    }

    private void test_get_network_info()
    {
        IntPtr pt = new IntPtr(); //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NetCard)) * 32);
        int size = 0;

        var v = NetTunnelLib.GetAllNICInfo(out pt, ref size);

        Console.WriteLine("Result {0}, total {1}", v, size);

        for (int i = 0; i < size; i++)
        {
            IntPtr ptr = new IntPtr(pt.ToInt64() + Marshal.SizeOf(typeof(NetCard)) * i);
            NetCard card = (NetCard)Marshal.PtrToStructure(ptr, typeof(NetCard));

            Console.WriteLine("UUID:{0}", card.UUID);
            Console.WriteLine("Name:{0}", card.Name);
            Console.WriteLine("Description:{0}", card.Description);
            Console.WriteLine("Index:{0}", card.IfIndex);
            Console.WriteLine("Ip:{0}", card.IpAddr);
            Console.WriteLine("NetMask:{0}", card.NetMask);
            Console.WriteLine("MacAddr:{0}", card.MacAddr);
        }

        Marshal.FreeCoTaskMem(pt);
    }
    private void button1_Click(object sender, EventArgs e)
    {
        //var buffer = new StringBuilder(256 + 1);
        //NetTunnelLib.TunnelSDKInitEnv();
        //var v = NetTunnelLib.FindWireguardExe(buffer, 256);
        //MessageBox.Show(buffer.ToString() + "----" + v.ToString());

        //test_install_wg_server();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        //test_uninstall_wg_server();

        test_get_network_info();
        //IntPtr pt = new IntPtr();
        //int size = 0;
        //var v = NetTunnelLib.GetUserConfigure2("admin", out pt, ref size);

        //for (int i = 0; i < size; i++)
        //{
        //    IntPtr ptr = new IntPtr(pt.ToInt64() + Marshal.SizeOf(typeof(FilePath)) * i);
        //    FilePath path = (FilePath)Marshal.PtrToStructure(ptr, typeof(FilePath));
        //    Console.WriteLine("{0}: {1} status {2}", i, path.CfgPath, path.curUsed);
        //    _curFilePaths.Add(path);
        //}

        //MessageBox.Show(v.ToString());

        //Marshal.FreeCoTaskMem(pt);
    }

    private void menuControlRefInterface_Click(object sender, EventArgs e)
    {
        GetCurrentNetCard();

        NetCardMenuItems menuItems = new NetCardMenuItems(_curNetCard);
        NetCardMenuItems ctxMenu = new NetCardMenuItems(_curNetCard);

        menuSetModeShareNet.DropDownItems.Clear();
        trapMenuSysInterface.DropDownItems.Clear();

        foreach (var item in menuItems.GetMenuItems())
        {
            menuSetModeShareNet.DropDownItems.Add(item);
        }

        foreach (var item in ctxMenu.GetMenuItems())
        {
            trapMenuSysInterface.DropDownItems.Add(item);
        }
    }

    private void menuSetVPNPath_Click(object sender, EventArgs e)
    {
        //DialogResult result = ofDlgWireGuard.ShowDialog();

        //if (result == DialogResult.OK)
        //{
        //    _wireguardPath = ofDlgWireGuard.FileName;
        //    NetTunnelLib.SetWireguardPath(_wireguardPath);
        //}
        MessageBox.Show("Not Support");
    }

    private void menuSetModeClient_Click(object sender, EventArgs e)
    {
        menuSetModeClient.Checked = true;
        menuSetModeServer.Checked = false;
    }

    private void menuSetModeServer_Click(object sender, EventArgs e)
    {
        menuSetModeServer.Checked = true;
        menuSetModeClient.Checked = false;
    }

    private void MainForm_SizeChanged(object sender, EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            this.notifyIconMain.Visible = true;
            this.Hide();
            this.ShowInTaskbar = false;
        }
        else
        {
            this.notifyIconMain.Visible = false;
            this.ShowInTaskbar = true;
        }
    }

    private void menuFileLogin_Click(object sender, EventArgs e)
    {
        LoginForm f = new LoginForm();

        f.onLoginServer += (o, args) =>
        {
            IntPtr pt = new IntPtr();

            if (NetTunnelLib.GetUserClientConfigure(args.HashArgs["UserName"] as string,
                    "1689189114026041344",
                    out pt) == 0)
            {
                IntPtr p = new IntPtr(pt.ToInt64());
                UserClientConfig cfg = (UserClientConfig)Marshal.PtrToStructure(p, typeof(UserClientConfig));

                //Console.WriteLine("scgCtrlAppId:{0}", cfg.scgCtrlAppId);
                //Console.WriteLine("scgTunnelAppId:{0}", cfg.scgTunnelAppId);
                //Console.WriteLine("ClientPrivateKey:{0}", cfg.cliPrivateKey);
                //Console.WriteLine("ClientPublicKey:{0}", cfg.cliPublicKey);
                //Console.WriteLine("ClientAddress:{0}", cfg.cliAddress);

                _userConfig.scgCtrlAppId = cfg.scgCtrlAppId;
                _userConfig.scgTunnelAppId = cfg.scgTunnelAppId;
                _userConfig.cliPrivateKey = cfg.cliPrivateKey;
                _userConfig.cliPublicKey = cfg.cliPublicKey;
                _userConfig.cliAddress = cfg.cliAddress;
                _userConfig.vmList.Clear();

                for (int i = 0; i < cfg.tolVM; i++)
                {
                    IntPtr ptr = new IntPtr(cfg.pVMConfig.ToInt64() + Marshal.SizeOf(typeof(VirtualMathineConfig)) * i);
                    VirtualMathineConfig vm =
                        (VirtualMathineConfig)Marshal.PtrToStructure(ptr, typeof(VirtualMathineConfig));

                    //Console.WriteLine("[{1}]:id: {0}", vm.vmId, i);
                    //Console.WriteLine("[{1}]:Name:{0}", vm.vmName, i);
                    //Console.WriteLine("[{1}]:ServerPublicKey:{0}", vm.svrPublicKey, i);
                    //Console.WriteLine("[{1}]:Network:{0}", vm.vmNetwork, i);
                    //Console.WriteLine("[{1}]:EndPoint:{0}", vm.scgGateWay, i);
                    _userConfig.vmList.Add(vm);
                }

                // Don't free any memory
                //Marshal.FreeCoTaskMem(cfg.pVMConfig);
                //Marshal.FreeCoTaskMem(pt);

                //GetCurrentWgCfgs(args.HashArgs["UserName"] as string);

                ServerMenuItems svrMenu = new ServerMenuItems(_userConfig.vmList);

                menuSetModeShareServer.DropDownItems.Clear();

                foreach (var item in svrMenu.GetMenuItems())
                {
                    menuSetModeShareServer.DropDownItems.Add(item);
                }
            }
            else
            {
                //this.DialogResult = DialogResult.Cancel;
                MessageBox.Show("Login Error");
            }
        };

        f.ShowDialog();
    }

    private void trapMenuShowMainWnd_Click(object sender, EventArgs e)
    {
        this.Show();
        this.WindowState = FormWindowState.Normal;
        this.Activate();
    }

    private void trapMenuHideMain_Click(object sender, EventArgs e)
    {
        this.Hide();
    }

    private void trapMenuExit_Click(object sender, EventArgs e)
    {
        System.Environment.Exit(0);
    }

    private void menuControlSetCliParams_Click(object sender, EventArgs e)
    {
        int ret;
        var v = ServerMenuItems.GetSelectItemData();
        var c = NetCardMenuItems.GetSelectItemData();

        //Console.WriteLine(v?.scgGateWay);
        //Console.WriteLine(c?.Name);

        if (v?.scgGateWay.Length == 0)
        {
            MessageBox.Show("未选择需要连接的用户虚拟机");
            return;
        }

        if (c?.UUID.Length == 0)
        {
            MessageBox.Show("未选择需要共享的本地网络");
            return;
        }

        IPNetwork ipnetwork = IPNetwork.Parse("172.18.2.152", "255.255.255.0");
        //IPNetwork cliNetwork = IPNetwork.Parse(_userConfig.cliAddress);

        //MessageBox.Show(ipnetwork.Value);

        //NetTunnelLib.ConnectServerControlService("http://" + v?.scgGateWay);

        ret = NetTunnelLib.RemoteCtrlSvrCfgUserTunnel(Int32.Parse(v?.vmId.ToString()), ipnetwork.Value);

        //ret = NetTunnelLib.SetUserClientConfige(_userConfig.cliPublicKey, ipnetwork.Value,
        //    cliNetwork.Network.ToString());

        if (ret != 0)
        {
            MessageBox.Show("SetTunnelConfigure Error: " + ret.ToString());
            return;
        }

        //ret = NetTunnelLib.SetTunnelConfigure(_userConfig.cliPrivateKey, v?.svrPublicKey, v?.vmNetwork,
        //    _userConfig.cliAddress, v?.scgGateWay);

        //if (ret != 0)
        //{
        //    MessageBox.Show("SetTunnelConfigure Error: " + ret.ToString());
        //    return;
        //}
    }

    private void menuControlSvrStart_Click(object sender, EventArgs e)
    {
        var ret = NetTunnelLib.RemoteWireGuardControl(true);

        if (ret != 0)
        {
            MessageBox.Show("RemoteWireGuardControl Error: " + ret.ToString());
            return;
        }

        ret = NetTunnelLib.LocalWireGuardControl(true, true);

        if (ret != 0)
        {
            MessageBox.Show("LocalWireGuardControl Error: " + ret.ToString());
            return;
        }
    }

    private void menuControlSvrStop_Click(object sender, EventArgs e)
    {
        var ret = NetTunnelLib.LocalWireGuardControl(false);

        if (ret != 0)
        {
            MessageBox.Show("LocalWireGuardControl Error: " + ret.ToString());
            return;
        }

        ret = NetTunnelLib.RemoteWireGuardControl(false);


        if (ret != 0)
        {
            MessageBox.Show("RemoteWireGuardControl Error: " + ret.ToString());
            return;
        }
    }

    private void menuControlHeartStart_Click(object sender, EventArgs e)
    {
        HeartCallBack cb = new HeartCallBack((string msg, uint tm) => { Console.WriteLine(msg + tm.ToString()); });

        var ret = NetTunnelLib.RemoteHeartControl(true, cb);

        if (ret != 0)
        {
            MessageBox.Show("Error: " + ret.ToString());
        }
    }

    private void menuControlHeartStop_Click(object sender, EventArgs e)
    {
        var ret = NetTunnelLib.RemoteHeartControl(false, null);

        if (ret != 0)
        {
            MessageBox.Show("Error: " + ret.ToString());
        }
    }

    private void menuSetShareModeICS_Click(object sender, EventArgs e)
    {
        menuSetShareModeNAT.Checked = false;
        menuSetShareModeICS.Checked = true;
        NetTunnelLib.SetCurrentNetShareMode(NET_SHARE_MODE.ICS_SHARE_MODE);
    }

    private void menuSetShareModeNAT_Click(object sender, EventArgs e)
    {
        menuSetShareModeICS.Checked = false;
        menuSetShareModeNAT.Checked = true;
        NetTunnelLib.SetCurrentNetShareMode(NET_SHARE_MODE.NAT_SHARE_MODE);
    }
}