using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FiddlerCore;
using Fiddler;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Runtime.InteropServices;

namespace DolceDL
{
    class Program
    {

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);

        static ConsoleEventDelegate handler;   // Keeps it from getting garbage collected
        private delegate bool ConsoleEventDelegate(int eventType);
        static string UrlFilter;
        static bool ConsoleEventCallback(int eventType)
        {
            if (eventType == 2) // WM_CLOSE
            {
                if(FiddlerApplication.IsStarted())
                {
                    Console.WriteLine("Stopping proxy...");
                    FiddlerApplication.Shutdown();
                }
            }
            return false;
        }

        static void Main(string[] args)
        {

            handler = new ConsoleEventDelegate(ConsoleEventCallback);
            SetConsoleCtrlHandler(handler, true);

            if (File.Exists("privkey.key") && File.Exists("privkey.cert"))
            {
                Console.WriteLine("Reading private key...");

                string privcert = File.ReadAllText("privkey.cert");
                FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.cert", privcert);
                string privkey = File.ReadAllText("privkey.key");
                FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.key", privkey);
                
            }
            else
            {
                Console.WriteLine("Generating root certificate...");
                if (!CertMaker.createRootCert())
                    Console.WriteLine("Failed to create cert..");

                Console.WriteLine("Installing root certificate...");
                X509Store certStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
                certStore.Open(OpenFlags.ReadWrite);

                try
                {
                    certStore.Add(CertMaker.GetRootCertificate());
                }
                catch (Exception)
                {
                    Console.WriteLine("Failed to install cert..");
                }
                finally
                {
                    certStore.Close();
                }

                Console.WriteLine("Saving private key...");
                File.WriteAllText("privkey.cert", FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.cert", null));
                File.WriteAllText("privkey.key", FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.key", null));

            }

            Console.Write("Url must contain: ");
            UrlFilter = Console.ReadLine();

            Console.WriteLine("Starting proxy...");
            FiddlerCoreStartupSettingsBuilder builder = new FiddlerCoreStartupSettingsBuilder();
            builder.DecryptSSL();
            builder.ListenOnPort(8080);
            builder.RegisterAsSystemProxy();
            FiddlerCoreStartupSettings settings = builder.Build();
            FiddlerApplication.BeforeResponse += FiddlerApplication_BeforeResponse;
            FiddlerApplication.Startup(settings);

            while (true) { };
        }

        private static void FiddlerApplication_BeforeResponse(Session oSession)
        {
           
            string path = oSession.fullUrl;
            if(path.Contains(UrlFilter))
            {
                if(oSession.PathAndQuery == "/")
                {
                    path += "index.html";
                }
                oSession.utilDecodeResponse();
                path = path.Replace("&", "&amp;");
                path = path.Replace(":", "&col;");
                path = path.Replace("\\", "&bksl;");
                path = path.Replace("//", "&fwsl;");
                path = path.Replace("|", "&pipe;");
                path = path.Replace("*", "&str;");
                path = path.Replace("?", "&que;");
                path = path.Replace("<", "&lt;");
                path = path.Replace(">", "&gt;");
                path = path.Replace("\"", "&qt;");

                while (File.Exists(path))
                    path += "_";

                oSession.SaveResponseBody(path);
                Console.WriteLine(path);
            }
            

        }
    }
}
