﻿using Snail.Reptile.KKVideo.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Titanium.Web.Proxy;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;

namespace Snail.Reptile.KKVideo
{
    public partial class FrmMain : Form
    {
        private ProxyServer _proxy;
        private int[] _portRange = new int[] { 9000, 10000 };
        public FrmMain()
        {
            InitializeComponent();
            Load += FrmMain_Load;
            Application.ApplicationExit += Application_ApplicationExit;
        }      
        private async void FrmMain_Load(object sender, EventArgs e)
        {
            await StartHttpProxy();
        }
        private void Application_ApplicationExit(object sender, EventArgs e)
        {
            StopHttpProxy();
        }

        #region ProxyServer
        private async Task StartHttpProxy()
        {
            await Task.Run(() =>
            {
                int port = 0;
                for (port = _portRange[0]; port <= _portRange[1]; port++)
                {
                    if (!PortInUse(port))
                    {
                        break;
                    }
                }
                _proxy = new ProxyServer();
                _proxy.CertificateManager.TrustRootCertificate(true);
                _proxy.BeforeRequest += OnRequest;
                _proxy.BeforeResponse += OnResponse;
                _proxy.AfterResponse += AfterResponse; ;
                _proxy.ServerCertificateValidationCallback += OnCertificateValidation;
                _proxy.ClientCertificateSelectionCallback += OnCertificateSelection;
                var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, port, true);
                _proxy.AddEndPoint(explicitEndPoint);
                _proxy.Start();
                _proxy.SetAsSystemHttpProxy(explicitEndPoint);
                _proxy.SetAsSystemHttpsProxy(explicitEndPoint);
                SetAppStatus($"正在监听：{port}");
            });
        }
        private void StopHttpProxy()
        {
            if (_proxy != null)
            {
                try
                {
                    _proxy.BeforeRequest -= OnRequest;
                    _proxy.BeforeResponse -= OnResponse;
                    _proxy.ServerCertificateValidationCallback -= OnCertificateValidation;
                    _proxy.ClientCertificateSelectionCallback -= OnCertificateSelection;
                    _proxy.Stop();
                }
                catch (Exception ex)
                {

                }
            }
        }
        private async Task AfterResponse(object sender, SessionEventArgs e)
        {
            await Task.CompletedTask;
        }
        private async Task OnRequest(object sender, SessionEventArgs e)
        {
          
        }
        private async Task OnResponse(object sender, SessionEventArgs e)
        {
            var source = SourceFactory.CreateSource(e.HttpClient.Request.Url,
                e.HttpClient.Request.Headers.Select(header
                => new KeyValuePair<string, string>(header.Name, header.Value)));
            if (source != null && source.SourceType == SourceType.图片)
            {
                var action = new Action<SourceInfo>((refSource) => {                   
                    var row = gvUrls.Rows[gvUrls.Rows.Add()];
                    row.Cells["Url"].Value = refSource.Url;
                    row.Cells["Type"].Value = refSource.SourceType;
                    row.Cells["Ext"].Value = refSource.SourceExt;
                    row.Tag = refSource;
                });
                BeginInvoke(action, source);
            }
        }
        private async Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
        {
            //set IsValid to true/false based on Certificate Errors
            if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
                e.IsValid = true;

            await Task.FromResult(0);
        }
        /// Allows overriding default client certificate selection logic during mutual authentication
        private async Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
        {
            //set e.clientCertificate to override
            await Task.FromResult(0);
        }
        public bool PortInUse(int port)
        {
            bool inUse = false;
            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
            foreach (IPEndPoint endPoint in ipEndPoints)
            {
                if (endPoint.Port == port)
                {
                    inUse = true;
                    break;
                }
            }
            return inUse;
        }
        #endregion

        #region Utils
        private void SetAppStatus(string status)
        {
            status = status ?? string.Empty;
            var action = new Action<string>(objStatus => {
                appStatus.Text = objStatus.ToString();
            });
            this.BeginInvoke(action, status);
        }
        #endregion
    }
}
