using Avalonia.Threading; 
using MES.Utility.Core;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using 常用工具集.Base;

namespace 常用工具集.ViewModel._02网络相关
{
    public class 端口占用扫描ViewModel : ViewModelBase
    {
        public bool Enabled1 { get; set; } = true;
        public bool Enabled2 { get; set; } = false;

        public int SelectedIndex { get; set; } = -1;

        public ObservableCollection<ScanResult> DataList { get; set; } = new ObservableCollection<ScanResult>();

        public int ProgressValue { get; set; } = 0;
        public int ProgressMax { get; set; } = 100;

        public DelegateCommand StartScanCmd { get; set; }
        public DelegateCommand CloseProcessCmd { get; set; }

        public 端口占用扫描ViewModel()
        {
            StartScanCmd = new DelegateCommand(StartScanCmdFunc);
            CloseProcessCmd = new DelegateCommand(CloseProcessCmdFunc);
        }

        private void CloseProcessCmdFunc(object obj)
        {
            if (SelectedIndex < 0)
            {
                return;
            }
            int pid = DataList[SelectedIndex].PID;
            Process process = Process.GetProcessById(pid);
            if (process == null)
            {
                GlobalValues.Error("获取进程相关信息失败,请尝试重新操作");
                return;
            }
            try
            {
                process.Kill();
                process.WaitForExit();
                process.Close();
                DataList.RemoveAt(SelectedIndex);
                GlobalValues.Success("操作成功");
            }
            catch (Exception ex)
            {
                GlobalValues.Error($"结束进程失败:{ex.Message}");
            }
        }

        private void StartScanCmdFunc(object obj)
        {
            Enabled1 = false;
            Enabled2 = false;
            ProgressValue = 0;
            DataList.Clear();
            new Thread(() =>
            {
                ProcessStartInfo startInfo = new ProcessStartInfo("netstat", "-ano")
                {
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };
                string result = "";
                using (Process process = Process.Start(startInfo))
                {
                    using (StreamReader reader = process.StandardOutput)
                    {
                        result = reader.ReadToEnd();
                    }
                }
                List<string> lines = result.Split('\n').Select(it => it.Trim('\r').Trim()).Where(it => !it.IsNullOrEmpty()).ToList();
                List<ScanResult> results = new List<ScanResult>();
                foreach (string line in lines)
                {
                    string[] splitArray = line.Split(' ').Where(it => !it.IsNullOrEmpty()).ToArray();
                    if (!line.StartsWith("TCP") && !line.StartsWith("UDP"))
                        continue;
                    if (splitArray.Length == 5)
                    {
                        int pid;
                        bool flag = int.TryParse(splitArray[4], out pid);
                        if (!flag)
                            continue;
                        if (!splitArray[1].Contains(":"))
                        {
                            continue;
                        }
                        string[] splitArray2 = splitArray[1].Split(':');
                        int port;
                        flag = int.TryParse(splitArray2[1], out port);
                        if (!flag)
                            continue;
                        results.Add(new ScanResult
                        {
                            Protocol = splitArray[0],
                            LocalAddress = splitArray[1],
                            Port = port,
                            RemoteAddress = splitArray[2],
                            State = splitArray[3],
                            PID = pid,
                            ProcessName = ""
                        });
                    }
                    else if (splitArray.Length == 4)
                    {
                        int pid;
                        bool flag = int.TryParse(splitArray[3], out pid);
                        if (!flag)
                            continue;
                        if (!splitArray[1].Contains(":"))
                        {
                            continue;
                        }
                        string[] splitArray2 = splitArray[1].Split(':');
                        int port;
                        flag = int.TryParse(splitArray2[1], out port);
                        if (!flag)
                            continue;
                        results.Add(new ScanResult
                        {
                            Protocol = splitArray[0],
                            LocalAddress = splitArray[1],
                            Port = port,
                            RemoteAddress = splitArray[2],
                            State = "",
                            PID = pid,
                            ProcessName = ""
                        });
                    }
                }

                results = results.OrderBy(it => it.Port).ToList();

                Dictionary<int, string> pidName = new Dictionary<int, string>();
                foreach (ScanResult scan in results)
                {
                    try
                    {
                        if (pidName.ContainsKey(scan.PID))
                        {
                            scan.ProcessName = pidName[scan.PID];
                        }
                        else
                        {
                            Process process = Process.GetProcessById(scan.PID);
                            if (process != null)
                            {
                                pidName.Add(scan.PID, process.ProcessName);
                                scan.ProcessName = process.ProcessName;
                            }
                        }

                        Dispatcher.UIThread.Invoke(new Action(() =>
                        {
                            DataList.Add(scan);
                        }));
                    }
                    catch
                    {
                        Dispatcher.UIThread.Invoke(new Action(() =>
                        {
                            DataList.Add(scan);
                        }));
                    }
                }
                Dispatcher.UIThread.Invoke(new Action(() =>
                {
                    Enabled1 = true;
                    Enabled2 = true;
                }));
            }).Start();
        }
    }


    public class ScanResult
    {
        public string Protocol { get; set; }
        public string LocalAddress { get; set; }

        public int Port { get; set; }
        public string RemoteAddress { get; set; }
        public string State { get; set; }
        public int PID { get; set; }
        public string ProcessName { get; set; }
    }
}
