// beau's notes
// this works with the ajax test http://www.websocket.org/echo.html
// originally an example from http://superwebsocket.codeplex.com/discussions/353151
// add these references from the superwebsocket(0.8) folder after running the batch file:
// SuperWebSocket.dll, SuperSocket.SocketBase.dll, and SuperSocket.SocketEngine.dll
// also add System.Configuration from the assembilies

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web;
using SuperWebSocket;
using SuperSocket;
using SuperSocket.SocketBase;

namespace Beau_sWebsocketServer
{
    public partial class BWS : Form
    {
        SuperWebSocket.WebSocketServer ws;
        private bool useSecureSocket = false;
        private string lastConnectedSessionID;

        private string endl = "\n";

        public BWS()
        {
            InitializeComponent();
            startWSS();
        }

        private void startWSS()
        {
            SuperSocket.SocketBase.Config.RootConfig r = new SuperSocket.SocketBase.Config.RootConfig();
            SuperSocket.SocketBase.Config.ServerConfig s = new SuperSocket.SocketBase.Config.ServerConfig();
            s.Name = "KabuzolWebSocket";
            s.Ip = "Any";
            s.Port = 3000;
            s.Mode = SocketMode.Tcp;

            if (useSecureSocket)
            {
                s.Security = "tls";
                SuperSocket.SocketBase.Config.CertificateConfig cert = new SuperSocket.SocketBase.Config.CertificateConfig();
                cert.FilePath = @"C:\SSL\yourhostname.cer";
                cert.Password = "";
                s.Certificate = cert;
            }

            SuperSocket.SocketEngine.SocketServerFactory f = new SuperSocket.SocketEngine.SocketServerFactory();

            if (ws != null)
            {
                ws.Stop();
                ws = null;
            }

            ws = new WebSocketServer();
            ws.Setup(r, s, f);
            ws.NewSessionConnected += new SessionHandler<WebSocketSession>(ws_NewSessionConnected);
            //ws.SessionClosed += new SessionHandler<WebSocketSession>(ws_SessionClosed);
            ws.NewDataReceived += new SessionHandler<WebSocketSession, byte[]>(ws_NewDataReceived);
            ws.NewMessageReceived += new SessionHandler<WebSocketSession, string>(ws_NewMessageReceived);
            
            cout("Server Starting"+endl);
            ws.Start();
        }
        private void ws_NewSessionConnected(WebSocketSession session)
        {
            lastConnectedSessionID = session.SessionID;
            cout("New Session Connected" + endl);
            cout("Origin: " + session.Origin + endl);
            cout("ID: " + lastConnectedSessionID + endl);
            cout("Time: " + session.StartTime.ToString() + endl);
            cout("Number of open sessions: " + ws.SessionCount + endl);            
            session.Send("Welcome to KWS (Kabuzol Websocket Server)");
        }
        private void ws_SessionClosed(WebSocketSession session)
        {
            // missing a parameter
        } 
        private void ws_NewDataReceived(WebSocketSession session, byte[] e)
        {
            /*
            cout(e.ToString() + endl);
            session.Send(e.ToString());
            */
            session.Send("This server only handles text.");
        }
        private void ws_NewMessageReceived(WebSocketSession session, string e)
        {
            cout(e + endl);
            session.Send("Echo: " + e);
        }
        private void sendToAllSessions(string s)
        {
            // an  enumerator iterates through a collection which is scattered
            // using a list would convert it into order
            IEnumerable<WebSocketSession> ies = ws.GetAllSessions();
            for (int i = 0; i < ws.SessionCount; i++)
            {
                ies.ElementAt(i).Send(s);
            }
        }

        // Beau's WS(websocket) Command
        private void cout(string input)
        {
            richConsole.AppendText(input);
            richConsole.SelectionStart = richConsole.Text.Length;
            richConsole.ScrollToCaret();
        }
        private void cout(string input, Color c)
        {
            richConsole.SelectionColor = c;
            cout(input);
            richConsole.SelectionColor = Color.Green;
        }
        private void evaluateCommand(string input)
        {
            switch (input)
            {
                case "start":
                    startWSS();
                    break;
                case "sendall":
                    sendToAllSessions("message to all");
                    break;
                case "sc":
                    startCaptureDelegate sc = new startCaptureDelegate(startCapture);
                    sc.BeginInvoke(null, null);
                    break;

                default:
                    break;
            }
            cout(input+endl);
        }

        // Windows Object Events
        private void textBoxInput_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode.ToString() == "Return") // there must be a better way but this works
            {
                evaluateCommand(textBoxInput.Text);
                textBoxInput.Text = "";
            }
        }
        private void BWS_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (ws != null)
            {
                ws.Stop();
                ws = null;
            }
            stopCapture();
        }
    }
}