using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Linq;

namespace SSHVPNApplication {
    class SSHVPNWrapper {
        static System.Diagnostics.Process SshuttleProcess = null;
        protected static void Main(string[] args) {
            var sshCommand = args[0];
            var ssh_connection_details = args[1];

            // extract hostname so we can prevent sshuttle from routing traffic to it through the tunnel, which results in the tunnel getting routed through the tunnel
            var ssh_host = ssh_connection_details.Split("@").Last().Split(":")[0];
            //var ssh_host = ssh_connection_parser_temp0[ssh_connection_parser_temp0.Length-1].Split(":")[0];

            //Console.WriteLine(ssh_connection_details);
            //Console.WriteLine(ssh_host);

            /*foreach (var arg in args) {
                Console.WriteLine(arg);
            }*/

            var sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
            var endPoint = new UnixDomainSocketEndPoint("/tmp/com.bangsparks.sshvpnapplication/ipc_socket");
            try {
                sock.Connect(endPoint);
                //sock.Listen(1);
                // must be called, otherwise sock.Receive(); will throw a SocketException (invalid arguments)
                //sock.Accept();
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // inform the GUI that we are alive and ready to accept commands so it can proceed
            sock.Send(Encoding.UTF8.GetBytes("DAEMON_READY"), SocketFlags.None);

            bool should_run = true;
            Int32 n_bytes = 0;
            var recv_buf = new byte[1024];
            var recv_msg = "";
            bool sshuttle_process_running = false;
            while (should_run) {
                n_bytes = sock.Receive(recv_buf, SocketFlags.None);
                recv_msg = Encoding.UTF8.GetString(recv_buf, 0, n_bytes);

                if (recv_msg == "STOP_SSHUTTLE") {
                    SshuttleProcess.CloseMainWindow();
                    sshuttle_process_running = false;
                } else if (recv_msg == "START_SSHUTTLE") {
                    if (sshuttle_process_running) {
                        sock.Send(Encoding.UTF8.GetBytes("SSHUTTLE_ALREADY_RUNNING"), SocketFlags.None);
                    } else {
                        SshuttleProcess = System.Diagnostics.Process.Start("sshuttle", "-vv --dns -r " + ssh_connection_details + " -e \"" + sshCommand + "\" 0.0.0.0/0 -x " + ssh_host);
                        sshuttle_process_running = true;
                        sock.Send(Encoding.UTF8.GetBytes("SSHUTTLE_STARTED"), SocketFlags.None);
                    }
                } else if (recv_msg == "APPLICATION_TERMINATE") {
                    Console.WriteLine("Daemon is terminating.");
                    if (sshuttle_process_running) {
                        // ensure that sshuttle does not stay running indefinitely in the background or something
                        SshuttleProcess.CloseMainWindow();
                        // we do not want sshuttle to potentially restart so no need to mark it as no longer running
                        sock.Send(Encoding.UTF8.GetBytes("DAEMON_OK_TERMINATE_AFTER_DELAY"), SocketFlags.None);
                    } else {
                        sock.Send(Encoding.UTF8.GetBytes("DAEMON_OK_TERMINATE"), SocketFlags.None);
                    }
                    should_run = false;
                }
            }

            //cleanup
            //sock.Shutdown(SocketShutdown.Both);
            sock.Close();
            //needed to properly shut down a unix socket
            System.IO.File.Delete("/tmp/com.bangsparks.sshvpnapplication/ipc_socket");
            Console.WriteLine("Daemon terminated cleanly.");
        }
    }
}