using System; namespace BestHTTP.Examples { /// /// The html code for all the samples. These are used only in the WebPlayer demo. /// public static class CodeBlocks { #region TextureDownloadSample public static string TextureDownloadSample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP;

public sealed class TextureDownloadSample : MonoBehaviour
{
    /// <summary>
    /// The URL of the server that will serve the image resources
    /// </summary>
    const string BaseURL = "http://besthttp.azurewebsites.net/Content/";

    #region Private Fields

    /// <summary>
    /// The downloadable images
    /// </summary>
    string[] Images = new string[9] { "One.png""Two.png""Three.png""Four.png""Five.png""Six.png""Seven.png""Eight.png""Nine.png" };

    /// <summary>
    /// The downloaded images will be stored as textures in this array
    /// </summary>
    Texture2D[] Textures = new Texture2D[9];

    /// <summary>
    /// True if all images are loaded from the local cache instead of the server
    /// </summary>
    bool allDownloadedFromLocalCache;

    /// <summary>
    /// How many sent requests are finished
    /// </summary>
    int finishedCount;

    /// <summary>
    /// GUI scroll position
    /// </summary>
    Vector2 scrollPos;

    #endregion

    #region Unity Events

    void Awake()
    {
        // SaveLocal a well observable value
        // This is how many concurrent requests can be made to a server
        HTTPManager.MaxConnectionPerServer = 1;

        // Create placeholder textures
        for (int i = 0; i < Images.Length; ++i)
            Textures[i] = new Texture2D(100, 150);
    }

    void OnDestroy()
    {
        // SaveLocal back to its defualt value.
        HTTPManager.MaxConnectionPerServer = 4;
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                scrollPos = GUILayout.BeginScrollView(scrollPos);

                    // Draw out the textures
                    GUILayout.SelectionGrid(0, Textures, 3);

                    if (finishedCount == Images.Length && allDownloadedFromLocalCache)
                        GUIHelper.DrawCenteredText("All images loaded from the local cache!");

                    GUILayout.FlexibleSpace();

                    GUILayout.BeginHorizontal();
                        GUILayout.Label("Max Connection/Server: "GUILayout.Width(150));
                        GUILayout.Label(HTTPManager.MaxConnectionPerServer.ToString(), GUILayout.Width(20));
                        HTTPManager.MaxConnectionPerServer = (byte)GUILayout.HorizontalSlider(HTTPManager.MaxConnectionPerServer, 1, 10);
                    GUILayout.EndHorizontal();

                    if (GUILayout.Button("Start Download"))
                        DownloadImages();

                GUILayout.EndScrollView();
            });
    }

    #endregion

    #region Private Helper Functions

    void DownloadImages()
    {
        // SaveLocal these metadatas to its initial values
        allDownloadedFromLocalCache = true;
        finishedCount = 0;

        for (int i = 0; i < Images.Length; ++i)
        {
            // SaveLocal a blank placeholder texture, overriding previously downloaded texture
            Textures[i] = new Texture2D(100, 150);

            // Construct the request
            var request = new HTTPRequest(new Uri(BaseURL + Images[i]), ImageDownloaded);

            // SaveLocal the Tag property, we can use it as a general storage bound to the request
            request.Tag = Textures[i];

            // Send out the request
            request.Send();
        }
    }

    /// <summary>
    /// Callback function of the image download http requests
    /// </summary>
    void ImageDownloaded(HTTPRequest req, HTTPResponse resp)
    {
        // Increase the finished count regardless of the state of our request
        finishedCount++;

        switch (req.State)
        {
            // The request finished without any problem.
            case HTTPRequestStates.Finished:
                if (resp.IsSuccess)
                {
                    // Get the Texture from the Tag property
                    Texture2D tex = req.Tag as Texture2D;

                    // Load the texture
                    tex.LoadImage(resp.Data);

                    // Update the cache-info variable
                    allDownloadedFromLocalCache = allDownloadedFromLocalCache && resp.IsFromCache;
                }
                else
                {
                    Debug.LogWarning(string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
                                                    resp.StatusCode,
                                                    resp.Message,
                                                    resp.DataAsText));
                }
                break;

            // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
            case HTTPRequestStates.Error:
                Debug.LogError("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
                break;

            // The request aborted, initiated by the user.
            case HTTPRequestStates.Aborted:
                Debug.LogWarning("Request Aborted!");
                break;

            // Ceonnecting to the server is timed out.
            case HTTPRequestStates.ConnectionTimedOut:
                Debug.LogError("Connection Timed Out!");
                break;

            // The request didn't finished in the given time.
            case HTTPRequestStates.TimedOut:
                Debug.LogError("Processing the request Timed Out!");
                break;
        }
    }

    #endregion
}
"; #endregion #region WebSocketSample public static string WebSocketSample = @"
using System;
using UnityEngine;
using BestHTTP;
using BestHTTP.WebSocket;

public class WebSocketSample : MonoBehaviour
{
    #region Private Fields

    /// <summary>
    /// The WebSocket address to connect
    /// </summary>
    string address = "ws://echo.websocket.org";

    /// <summary>
    /// Default text to send
    /// </summary>
    string msgToSend = "Hello World!";

    /// <summary>
    /// Debug text to draw on the gui
    /// </summary>
    string Text = string.Empty;

    /// <summary>
    /// Saved WebSocket instance
    /// </summary>
    WebSocket webSocket;

    /// <summary>
    /// GUI scroll position
    /// </summary>
    Vector2 scrollPos;

    #endregion

    #region Unity Events

    void OnDestroy()
    {
        if (webSocket != null)
            webSocket.Close();
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                scrollPos = GUILayout.BeginScrollView(scrollPos);
                    GUILayout.Label(Text);
                GUILayout.EndScrollView();

                GUILayout.Space(5);

                GUILayout.FlexibleSpace();

                address = GUILayout.TextField(address);

                if (webSocket == null && GUILayout.Button("Open Web Socket"))
                {
                    // Create the WebSocket instance
                    webSocket = new WebSocket(new Uri(address));

                    if (HTTPManager.Proxy != null)
                        webSocket.InternalRequest.Proxy = new HTTPProxy(HTTPManager.Proxy.Address, HTTPManager.Proxy.Credentials, false);

                    // Subscribe to the WS events
                    webSocket.OnOpen += OnOpen;
                    webSocket.OnMessage += OnMessageReceived;
                    webSocket.OnClosed += OnClosed;
                    webSocket.OnError += OnError;

                    // Start connecting to the server
                    webSocket.Open();

                    Text += "Opening Web Socket...\n";
                }

                if (webSocket != null && webSocket.IsOpen)
                {
                    GUILayout.Space(10);

                    GUILayout.BeginHorizontal();
                        msgToSend = GUILayout.TextField(msgToSend);

                        if (GUILayout.Button("Send"GUILayout.MaxWidth(70)))
                        {
                            Text += "Sending message...\n";

                            // Send message to the server
                            webSocket.Send(msgToSend);
                        }
                    GUILayout.EndHorizontal();

                    GUILayout.Space(10);

                    if (GUILayout.Button("Close"))
                    {
                        // Close the connection
                        webSocket.Close(1000, "Bye!");
                    }
                }
            });
    }

    #endregion

    #region WebSocket Event Handlers

    /// <summary>
    /// Called when the web socket is open, and we are ready to send and receive data
    /// </summary>
    void OnOpen(WebSocket ws)
    {
        Text += string.Format("-WebSocket Open!\n");
    }

    /// <summary>
    /// Called when we received a text message from the server
    /// </summary>
    void OnMessageReceived(WebSocket ws, string message)
    {
        Text += string.Format("-Message received: {0}\n", message);
    }

    /// <summary>
    /// Called when the web socket closed
    /// </summary>
    void OnClosed(WebSocket ws, UInt16 code, string message)
    {
        Text += string.Format("-WebSocket closed! Code: {0} Message: {1}\n", code, message);
        webSocket = null;
    }

    /// <summary>
    /// Called when an error occured on client side
    /// </summary>
    void OnError(WebSocket ws, Exception ex)
    {
        string errorMsg = string.Empty;
        if (ws.InternalRequest.Response != null)
            errorMsg = string.Format("Status Code from Server: {0} and Message: {1}", ws.InternalRequest.Response.StatusCode, ws.InternalRequest.Response.Message);

        Text += string.Format("-An error occured: {0}\n", (ex != null ? ex.Message : "Unknown Error " + errorMsg));

        webSocket = null;
    }

    #endregion
}
"; #endregion #region AssetBundleSample public static string AssetBundleSample = @"
using System;
using System.Collections;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP;

public sealed class AssetBundleSample : MonoBehaviour
{
    /// <summary>
    /// The url of the resource to download
    /// </summary>
    const string URL = "http://besthttp.azurewebsites.net/Content/AssetBundle.html";

    #region Private Fields

    /// <summary>
    /// Debug status text
    /// </summary>
    string status = "Waiting for user interaction";

    /// <summary>
    /// The downloaded and cached AssetBundle
    /// </summary>
    AssetBundle cachedBundle;

    /// <summary>
    /// The loaded texture from the AssetBundle
    /// </summary>
    Texture2D texture;

    /// <summary>
    /// A flag that indicates that we are processing the request/bundle to hide the "Start Download" button.
    /// </summary>
    bool downloading;

    #endregion

    #region Unity Events

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                GUILayout.Label("Status: " + status);

                // Draw the texture from the downloaded bundle
                if (texture != null)
                    GUILayout.Box(texture, GUILayout.MaxHeight(256));

                if (!downloading && GUILayout.Button("Start Download"))
                {
                    UnloadBundle();

                    StartCoroutine(DownloadAssetBundle());
                }
            });
    }

    void OnDestroy()
    {
        UnloadBundle();
    }

    #endregion

    #region Private Helper Functions

    IEnumerator DownloadAssetBundle()
    {
        downloading = true;

        // Create and send our request
        var request = new HTTPRequest(new Uri(URL)).Send();

        status = "Download started";

        // Wait while it's finishes and add some fancy dots to display something while the user waits for it.
        // A simple "yield return StartCoroutine(request);" would do the job too.
        while(request.State < HTTPRequestStates.Finished)
        {
            yield return new WaitForSeconds(0.1f);

            status += ".";
        }

        // Check the outcome of our request.
        switch (request.State)
        {
            // The request finished without any problem.
            case HTTPRequestStates.Finished:

                if (request.Response.IsSuccess)
                {
                    status = string.Format("AssetBundle downloaded! Loaded from local cache: {0}", request.Response.IsFromCache.ToString());

                    // Start creating the downloaded asset bundle
                    AssetBundleCreateRequest async = AssetBundle.CreateFromMemory(request.Response.Data);

                    // wait for it
                    yield return async;

                    // And process the bundle
                    yield return StartCoroutine(ProcessAssetBundle(async.assetBundle));
                }
                else
                {
                    status = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
                                                    request.Response.StatusCode,
                                                    request.Response.Message,
                                                    request.Response.DataAsText);
                    Debug.LogWarning(status);
                }

                break;

            // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
            case HTTPRequestStates.Error:
                status = "Request Finished with Error! " + (request.Exception != null ? (request.Exception.Message + "\n" + request.Exception.StackTrace) : "No Exception");
                Debug.LogError(status);
                break;

            // The request aborted, initiated by the user.
            case HTTPRequestStates.Aborted:
                status = "Request Aborted!";
                Debug.LogWarning(status);
                break;

            // Ceonnecting to the server is timed out.
            case HTTPRequestStates.ConnectionTimedOut:
                status = "Connection Timed Out!";
                Debug.LogError(status);
                break;

            // The request didn't finished in the given time.
            case HTTPRequestStates.TimedOut:
                status = "Processing the request Timed Out!";
                Debug.LogError(status);
                break;
        }

        downloading = false;
    }

    /// <summary>
    /// In this function we can do whatever we want with the freshly downloaded bundle.
    /// In this example we will cache it for later use, and we will load a texture from it.
    /// </summary>
    IEnumerator ProcessAssetBundle(AssetBundle bundle)
    {
        if (bundle == null)
            yield break;

        // Save the bundle for future use
        cachedBundle = bundle;

        // Start loading the asset from the bundle
        var asyncAsset = cachedBundle.LoadAsync("9443182_orig"typeof(Texture2D));

        // wait til load
        yield return asyncAsset;

        // get the texture
        texture = asyncAsset.asset as Texture2D;
    }

    void UnloadBundle()
    {
        if (cachedBundle != null)
        {
            cachedBundle.Unload(true);
            cachedBundle = null;
        }
    }

    #endregion
}
"; #endregion #region LargeFileDownloadSample public static string LargeFileDownloadSample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP;

public sealed class LargeFileDownloadSample : MonoBehaviour
{
    /// <summary>
    /// The url of the resource to download
    /// </summary>
    const string URL = "http://ipv4.download.thinkbroadband.com/100MB.zip";

    #region Private Fields

    /// <summary>
    /// Cached request to be able to abort it
    /// </summary>
    HTTPRequest request;

    /// <summary>
    /// Debug status of the request
    /// </summary>
    string status = string.Empty;

    /// <summary>
    /// Download(processing) progress. Its range is between [0..1]
    /// </summary>
    float progress;

    /// <summary>
    /// The fragment size that we will set to the request
    /// </summary>
    int fragmentSize = HTTPResponse.MinBufferSize;

    #endregion

    #region Unity Events

    void Awake()
    {
        // If we have a non-finished download, set the progress to the value where we left it
        if (PlayerPrefs.HasKey("DownloadLength"))
            progress = PlayerPrefs.GetInt("DownloadProgress") / (float)PlayerPrefs.GetInt("DownloadLength");
    }

    void OnDestroy()
    {
        // Stop the download if we are leaving this example
        if (request != null && request.State < HTTPRequestStates.Finished)
        {
            request.OnProgress = null;
            request.Callback = null;
            request.Abort();
        }
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                // Draw the current status
                GUILayout.Label("Request status: " + status);

                GUILayout.Space(5);

                // Draw the current progress
                GUILayout.Label(string.Format("Progress: {0:P2} of {1:N0}Mb", progress, PlayerPrefs.GetInt("DownloadLength") / 1048576 /*1 Mb*/));
                GUILayout.HorizontalSlider(progress, 0, 1);

                GUILayout.Space(50);

                if (request == null)
                {
                    // Draw a slider to be able to change the fragment size
                    GUILayout.Label(string.Format("Desired Fragment Size: {0:N} KBytes", fragmentSize / 1024f));
                    fragmentSize = (int)GUILayout.HorizontalSlider(fragmentSize, HTTPResponse.MinBufferSize, 10 * 1024 * 1024);

                    GUILayout.Space(5);

                    string buttonStr = PlayerPrefs.HasKey("DownloadProgress") ? "Continue Download" : "Start Download";
                    if (GUILayout.Button(buttonStr))
                        StreamLargeFileTest();
                }
                else if (request.State == HTTPRequestStates.Processing && GUILayout.Button("Abort Download"))
                {
                    // Simulate a connection lost
                    request.Abort();
                }
            });
    }

    #endregion

    #region Private Helper Functions

    // Calling this function again when the "DownloadProgress" key in the PlayerPrefs present will 
    //	continue the download
    void StreamLargeFileTest()
    {
        request = new HTTPRequest(new Uri(URL), (req, resp) =>
        {
            switch (req.State)
            {
                // The request is currently processed. With UseStreaming == true, we can get the streamed fragments here
                case HTTPRequestStates.Processing:

                    // SaveLocal the DownloadLength, so we can display the progress
                    if (!PlayerPrefs.HasKey("DownloadLength"))
                    {
                        string value = resp.GetFirstHeaderValue("content-length");
                        if (!string.IsNullOrEmpty(value))
                            PlayerPrefs.SetInt("DownloadLength"int.Parse(value));
                    }

                    // Get the fragments, and save them
                    ProcessFragments(resp.GetStreamedFragments());

                    status = "Processing";
                    break;

                // The request finished without any problem.
                case HTTPRequestStates.Finished:
                    if (resp.IsSuccess)
                    {
                        // Save any remaining fragments
                        ProcessFragments(resp.GetStreamedFragments());

                        // Completly finished
                        if (resp.IsStreamingFinished)
                        {
                            status = "Streaming finished!";

                            // We are done, delete the progress key
                            PlayerPrefs.DeleteKey("DownloadProgress");
                            PlayerPrefs.Save();

                            request = null;
                        }
                        else
                            status = "Processing";
                    }
                    else
                    {
                        status = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
                                                        resp.StatusCode,
                                                        resp.Message,
                                                        resp.DataAsText);
                        Debug.LogWarning(status);

                        request = null;
                    }
                    break;

                // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
                case HTTPRequestStates.Error:
                    status = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception");
                    Debug.LogError(status);

                    request = null;
                    break;

                // The request aborted, initiated by the user.
                case HTTPRequestStates.Aborted:
                    status = "Request Aborted!";
                    Debug.LogWarning(status);

                    request = null;
                    break;

                // Ceonnecting to the server is timed out.
                case HTTPRequestStates.ConnectionTimedOut:
                    status = "Connection Timed Out!";
                    Debug.LogError(status);

                    request = null;
                    break;

                // The request didn't finished in the given time.
                case HTTPRequestStates.TimedOut:
                    status = "Processing the request Timed Out!";
                    Debug.LogError(status);

                    request = null;
                    break;
            }
        });

        // Are there any progress, that we can continue?
        if (PlayerPrefs.HasKey("DownloadProgress"))
            // SaveLocal the range header
            request.SetRangeHeader(PlayerPrefs.GetInt("DownloadProgress"));
        else
            // This is a new request
            PlayerPrefs.SetInt("DownloadProgress", 0);

        // If we are writing our own file set it true(disable), so don't duplicate it on the filesystem
        request.DisableCache = true;

        // We want to access the downloaded bytes while we are still downloading
        request.UseStreaming = true;

        // SaveLocal a reasonable high fragment size. Here it is 5 megabytes.
        request.StreamFragmentSize = fragmentSize;

        // Start Processing the request
        request.Send();
    }

    /// <summary>
    /// In this function we can do whatever we want with the downloaded bytes. In this sample we will do nothing, just set the metadata to display progress.
    /// </summary>
    void ProcessFragments(List<byte[]> fragments)
    {
        if (fragments != null && fragments.Count > 0)
        {
            /*string dir = "TODO!";
            string filename = "TODO!";

            using (System.IO.FileStream fs = new System.IO.FileStream(System.IO.Path.Combine(dir, filename), System.IO.FileMode.Append))
                for (int i = 0; i < fragments.Count; ++i)
                    fs.Write(fragments[i], 0, fragments[i].Length);*/

            for (int i = 0; i < fragments.Count; ++i)
            {
                // Save how many bytes we wrote successfully
                int downloaded = PlayerPrefs.GetInt("DownloadProgress") + fragments[i].Length;
                PlayerPrefs.SetInt("DownloadProgress", downloaded);
            }

            PlayerPrefs.Save();

            // SaveLocal the progress to the actually processed bytes
            progress = PlayerPrefs.GetInt("DownloadProgress") / (float)PlayerPrefs.GetInt("DownloadLength");
        }
    }

    #endregion
}
"; #endregion #region SocketIOChatSample public static string SocketIOChatSample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP;
using BestHTTP.SocketIO;
using BestHTTP.JSON;
using BestHTTP.SocketIO.Events;

public sealed class SocketIOChatSample : MonoBehaviour
{
    private readonly TimeSpan TYPING_TIMER_LENGTH = TimeSpan.FromMilliseconds(700);

    private enum ChatStates
    {
        Login,
        Chat
    }

    #region Fields

    /// <summary>
    /// The Socket.IO manager instance.
    /// </summary>
    private SocketManager Manager;

    /// <summary>
    /// Current state of the chat demo.
    /// </summary>
    private ChatStates State;

    /// <summary>
    /// The selected nickname
    /// </summary>
    private string userName = string.Empty;

    /// <summary>
    /// Currently typing message
    /// </summary>
    private string message = string.Empty;

    /// <summary>
    /// Sent and received messages.
    /// </summary>
    private string chatLog = string.Empty;

    /// <summary>
    /// Position of the scroller
    /// </summary>
    private Vector2 scrollPos;

    /// <summary>
    /// True if the user is currently typing
    /// </summary>
    private bool typing;

    /// <summary>
    /// When the message changed.
    /// </summary>
    private DateTime lastTypingTime = DateTime.MinValue;

    /// <summary>
    /// Users that typing.
    /// </summary>
    private List<string> typingUsers = new List<string>();

    #endregion

    #region Unity Events
        
    void Start()
    {
        // The current state is Login
        State = ChatStates.Login;

        // Change an option to show how it should be done
        SocketOptions options = new SocketOptions();
        options.AutoConnect = false;
        
        // Create the Socket.IO manager
        Manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"), options);

        // SaveLocal up custom chat events
        Manager.Socket.On("login", OnLogin);
        Manager.Socket.On("new message", OnNewMessage);
        Manager.Socket.On("user joined", OnUserJoined);
        Manager.Socket.On("user left", OnUserLeft);
        Manager.Socket.On("typing", OnTyping);
        Manager.Socket.On("stop typing", OnStopTyping);

        // The argument will be an Error object.
        Manager.Socket.On(SocketIOEventTypes.Error, (socket, packet, args) => Debug.LogError(string.Format("Error: {0}", args[0].ToString())));

        // We set SocketOptions' AutoConnect to false, so we have to call it manually.
        Manager.Open();
    }

    void OnDestroy()
    {
        // Leaving this sample, close the socket
        Manager.Close();
    }

    void Update()
    {
        // Go back to the demo selector
        if (Input.GetKeyDown(KeyCode.Escape))
            SampleSelector.SelectedSample.DestroyUnityObject();

        // Stop typing if some time passed without typing
        if (typing)
        {
            var typingTimer = DateTime.UtcNow;
            var timeDiff = typingTimer - lastTypingTime;
            if (timeDiff >= TYPING_TIMER_LENGTH)
            {
                Manager.Socket.Emit("stop typing");
                typing = false;
            }
        }
    }

    void OnGUI()
    {
        switch(State)
        {
            case ChatStates.Login: DrawLoginScreen(); break;
            case ChatStates.Chat: DrawChatScreen(); break;
        }
    }

    #endregion

    #region Chat Logic

    /// <summary>
    /// Called from an OnGUI event to draw the Login Screen.
    /// </summary>
    void DrawLoginScreen()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                GUILayout.BeginVertical();
                    GUILayout.FlexibleSpace();

                    GUIHelper.DrawCenteredText("What's your nickname?");
                    userName = GUILayout.TextField(userName);

                    if (GUILayout.Button("Join"))
                        SetUserName();

                    GUILayout.FlexibleSpace();
                GUILayout.EndVertical();
            });
    }

    /// <summary>
    /// Called from an OnGUI event to draw the Chat Screen.
    /// </summary>
    void DrawChatScreen()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                GUILayout.BeginVertical();
                    scrollPos = GUILayout.BeginScrollView(scrollPos);
                        GUILayout.Label(chatLog, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
                    GUILayout.EndScrollView();

                    string typing = string.Empty;

                    if (typingUsers.Count > 0)
                    {
                        typing += string.Format("{0}", typingUsers[0]);

                        for (int i = 1; i < typingUsers.Count; ++i)
                            typing += string.Format(", {0}", typingUsers[i]);

                        if (typingUsers.Count == 1)
                            typing += " is typing!";
                        else
                            typing += " are typing!";
                    }

                    GUILayout.Label(typing);

                    GUILayout.Label("Type here:");

                    GUILayout.BeginHorizontal();
                    message = GUILayout.TextField(message);

                    if (GUILayout.Button("Send"GUILayout.MaxWidth(100)))
                        SendMessage();
                    GUILayout.EndHorizontal();

                    if (GUI.changed)
                        UpdateTyping();

                GUILayout.EndVertical();
            });
    }

    void SetUserName()
    {
        if (string.IsNullOrEmpty(userName))
            return;

        State = ChatStates.Chat;

        Manager.Socket.Emit("add user", userName);
    }

    void SendMessage()
    {
        if (string.IsNullOrEmpty(message))
            return;

        Manager.Socket.Emit("new message", message);

        chatLog += string.Format("{0}: {1}\n", userName, message);
        message = string.Empty;
    }

    void UpdateTyping()
    {
        if (!typing)
        {
            typing = true;
            Manager.Socket.Emit("typing");
        }

        lastTypingTime = DateTime.UtcNow;
    }

    void addParticipantsMessage(Dictionary<stringobject> data)
    {
        int numUsers = Convert.ToInt32(data["numUsers"]);

        if (numUsers == 1)
            chatLog += "there's 1 participant\n";
        else
            chatLog += "there are " + numUsers + " participants\n";
    }

    void addChatMessage(Dictionary<stringobject> data)
    {
        var username = data["username"as string;
        var msg = data["message"as string;

        chatLog += string.Format("{0}: {1}\n", username, msg);
    }

    void AddChatTyping(Dictionary<stringobject> data)
    {
        var username = data["username"as string;

        typingUsers.Add(username);
    }

    void RemoveChatTyping(Dictionary<stringobject> data)
    {
        var username = data["username"as string;

        int idx = typingUsers.FindIndex((name) => name.Equals(username));
        if (idx != -1)
            typingUsers.RemoveAt(idx);
    }

    #endregion

    #region Custom SocketIO Events

    void OnLogin(Socket socket, Packet packet, params object[] args)
    {
        chatLog = "Welcome to Socket.IO Chat — \n";

        addParticipantsMessage(args[0] as Dictionary<stringobject>);
    }

    void OnNewMessage(Socket socket, Packet packet, params object[] args)
    {
        addChatMessage(args[0] as Dictionary<stringobject>);
    }

    void OnUserJoined(Socket socket, Packet packet, params object[] args)
    {
        var data = args[0] as Dictionary<stringobject>;

        var username = data["username"as string;

        chatLog += string.Format("{0} joined\n", username);

        addParticipantsMessage(data);
    }

    void OnUserLeft(Socket socket, Packet packet, params object[] args)
    {
        var data = args[0] as Dictionary<stringobject>;

        var username = data["username"as string;

        chatLog += string.Format("{0} left\n", username);

        addParticipantsMessage(data);
    }

    void OnTyping(Socket socket, Packet packet, params object[] args)
    {
        AddChatTyping(args[0] as Dictionary<stringobject>);
    }

    void OnStopTyping(Socket socket, Packet packet, params object[] args)
    {
        RemoveChatTyping(args[0] as Dictionary<stringobject>);
    }

    #endregion
}
"; #endregion #region SocketIOWePlaySample public static string SocketIOWePlaySample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP.SocketIO;
using BestHTTP.SocketIO.Events;

public sealed class SocketIOWePlaySample : MonoBehaviour
{
    /// <summary>
    /// Possible states of the game.
    /// </summary>
    enum States
    {
        Connecting,
        WaitForNick,
        Joined
    }

    /// <summary>
    /// Controls that the server understands as a parameter in the move event.
    /// </summary>
    private string[] controls = new string[] { "left""right""a""b""up""down""select""start" };

    /// <summary>
    /// Ratio of the drawn GUI texture from the screen
    /// </summary>
    private const float ratio = 1.5f;

    /// <summary>
    /// How many messages to keep.
    /// </summary>
    private int MaxMessages = 50;
    
    /// <summary>
    /// Current state of the game.
    /// </summary>
    private States State;

    /// <summary>
    /// The root("/") Socket instance.
    /// </summary>
    private Socket Socket;

    /// <summary>
    /// The user-selected nickname.
    /// </summary>
    private string Nick = string.Empty;

    /// <summary>
    /// The message that the user want to send to the chat.
    /// </summary>
    private string messageToSend = string.Empty;

    /// <summary>
    /// How many user connected to the server.
    /// </summary>
    private int connections;

    /// <summary>
    /// Local and server sent messages.
    /// </summary>
    private List<string> messages = new List<string>();
    
    /// <summary>
    /// The chat scroll position.
    /// </summary>
    private Vector2 scrollPos;

    /// <summary>
    /// The decoded texture from the server sent binary data
    /// </summary>
    private Texture2D FrameTexture;

    #region Unity Events

    void Start()
    {
        // Change an option to show how it should be done
        SocketOptions options = new SocketOptions();
        options.AutoConnect = false;

        // Create the SocketManager instance
        var manager = new SocketManager(new Uri("http://io.weplay.io/socket.io/"), options);

        // Keep a reference to the root namespace
        Socket = manager.Socket;

        // SaveLocal up our event handlers.
        Socket.On(SocketIOEventTypes.Connect, OnConnected);
        Socket.On("joined", OnJoined);
        Socket.On("connections", OnConnections);
        Socket.On("join", OnJoin);
        Socket.On("move", OnMove);
        Socket.On("message", OnMessage);
        Socket.On("reload", OnReload);

        // Don't waste cpu cycles on decoding the payload, we are expecting only binary data with this event,
        //  and we can access it through the packet's Attachments property.
        Socket.On("frame", OnFrame, /*autoDecodePayload:*/ false);

        // Add error handler, so we can display it
        Socket.On(SocketIOEventTypes.Error, OnError);

        // We set SocketOptions' AutoConnect to false, so we have to call it manually.
        manager.Open();

        // We are connecting to the server.
        State = States.Connecting;
    }

    void OnDestroy()
    {
        // Leaving this sample, close the socket
        Socket.Manager.Close();
    }

    void Update()
    {
        // Go back to the demo selector
        if (Input.GetKeyDown(KeyCode.Escape))
            SampleSelector.SelectedSample.DestroyUnityObject();
    }

    void OnGUI()
    {
        switch(State)
        {
            case States.Connecting:
                GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
                    {
                        GUILayout.BeginVertical();
                            GUILayout.FlexibleSpace();
                            GUIHelper.DrawCenteredText("Connecting to the server...");
                            GUILayout.FlexibleSpace();
                        GUILayout.EndVertical();
                    });
                break;
                
            case States.WaitForNick:
                GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
                    {
                        DrawLoginScreen();
                    });
                break;

            case States.Joined:
                GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
                    {
                        // Draw Texture
                        if (FrameTexture != null)
                            GUILayout.Box(FrameTexture);

                        DrawControls();
                        DrawChat();
                    });
                break;
        }
    }

    #endregion

    #region Helper Functions

    /// <summary>
    /// Called from an OnGUI event to draw the Login Screen.
    /// </summary>
    void DrawLoginScreen()
    {
        GUILayout.BeginVertical();
            GUILayout.FlexibleSpace();

            GUIHelper.DrawCenteredText("What's your nickname?");

            Nick = GUILayout.TextField(Nick);

            if (GUILayout.Button("Join"))
                Join();

            GUILayout.FlexibleSpace();
        GUILayout.EndVertical();
    }

    void DrawControls()
    {
        GUILayout.BeginHorizontal();
            GUILayout.Label("Controls:");

            for (int i = 0; i < controls.Length; ++i)
                if (GUILayout.Button(controls[i]))
                    Socket.Emit("move", controls[i]);

            GUILayout.Label(" Connections: " + connections);

        GUILayout.EndHorizontal();
    }

    void DrawChat(bool withInput = true)
    {
        GUILayout.BeginVertical();

            // Draw the messages
            scrollPos = GUILayout.BeginScrollView(scrollPos, falsefalse);
                for (int i = 0; i < messages.Count; ++i)
                    GUILayout.Label(messages[i], GUILayout.MinWidth(Screen.width));
            GUILayout.EndScrollView();

            if (withInput)
            {
                GUILayout.Label("Your message: ");

                GUILayout.BeginHorizontal();

                    messageToSend = GUILayout.TextField(messageToSend);

                    if (GUILayout.Button("Send"GUILayout.MaxWidth(100)))
                        SendMessage();

                GUILayout.EndHorizontal();
            }

        GUILayout.EndVertical();
    }

    /// <summary>
    /// Add a message to the message log
    /// </summary>
    /// <param name="msg"></param>
    void AddMessage(string msg)
    {
        messages.Insert(0, msg);
        if (messages.Count > MaxMessages)
            messages.RemoveRange(MaxMessages, messages.Count - MaxMessages);
    }

    /// <summary>
    /// Send a chat message. The message must be in the messageToSend field.
    /// </summary>
    void SendMessage()
    {
        if (string.IsNullOrEmpty(messageToSend))
            return;

        Socket.Emit("message", messageToSend);
        AddMessage(string.Format("{0}: {1}", Nick, messageToSend));
        messageToSend = string.Empty;
    }

    /// <summary>
    /// Join to the game with the nickname stored in the Nick field.
    /// </summary>
    void Join()
    {
        PlayerPrefs.SetString("Nick", Nick);

        Socket.Emit("join", Nick);
    }

    /// <summary>
    /// Reload the game.
    /// </summary>
    void Reload()
    {
        FrameTexture = null;

        if (Socket != null)
        {
            Socket.Manager.Close();
            Socket = null;

            Start();
        }
    }

    #endregion

    #region SocketIO Events

    /// <summary>
    /// Socket connected event.
    /// </summary>
    private void OnConnected(Socket socket, Packet packet, params object[] args)
    {
        if (PlayerPrefs.HasKey("Nick"))
        {
            Nick = PlayerPrefs.GetString("Nick""NickName");
            Join();
        }
        else
            State = States.WaitForNick;

        AddMessage("connected");
    }

    /// <summary>
    /// Local player joined after sending a 'join' event
    /// </summary>
    private void OnJoined(Socket socket, Packet packet, params object[] args)
    {
        State = States.Joined;
    }

    /// <summary>
    /// Server sent us a 'reload' event.
    /// </summary>
    private void OnReload(Socket socket, Packet packet, params object[] args)
    {
        Reload();
    }

    /// <summary>
    /// Someone wrote a message to the chat.
    /// </summary>
    private void OnMessage(Socket socket, Packet packet, params object[] args)
    {
        if (args.Length == 1)
            AddMessage(args[0] as string);
        else
            AddMessage(string.Format("{0}: {1}", args[1], args[0]));
    }

    /// <summary>
    /// Someone (including us) pressed a button.
    /// </summary>
    private void OnMove(Socket socket, Packet packet, params object[] args)
    {
        AddMessage(string.Format("{0} pressed {1}", args[1], args[0]));
    }

    /// <summary>
    /// Someone joined to the game
    /// </summary>
    private void OnJoin(Socket socket, Packet packet, params object[] args)
    {
        string loc = args.Length > 1 ? string.Format("({0})", args[1]) : string.Empty;

        AddMessage(string.Format("{0} joined {1}", args[0], loc));
    }

    /// <summary>
    /// How many players are connected to the game.
    /// </summary>
    private void OnConnections(Socket socket, Packet packet, params object[] args)
    {
        connections = Convert.ToInt32(args[0]);
    }

    /// <summary>
    /// The server sent us a new picture to draw the game.
    /// </summary>
    private void OnFrame(Socket socket, Packet packet, params object[] args)
    {
        if (State != States.Joined)
            return;

        if (FrameTexture == null)
        {
            FrameTexture = new Texture2D(0, 0, TextureFormat.RGBA32, false);
            FrameTexture.filterMode = FilterMode.Point;
        }

        // Binary data usage case 1 - using directly the Attachments property:
        byte[] data = packet.Attachments[0];

        // Binary data usage case 2 - using the packet's ReconstructAttachmentAsIndex() function
        /*packet.ReconstructAttachmentAsIndex();
        args = packet.Decode(socket.Manager.Encoder);
        data = packet.Attachments[Convert.ToInt32(args[0])];*/

        // Binary data usage case 3 - using the packet's ReconstructAttachmentAsBase64() function
        /*packet.ReconstructAttachmentAsBase64();
        args = packet.Decode(socket.Manager.Encoder);
        data = Convert.FromBase64String(args[0] as string);*/

        // Load the server sent picture
        FrameTexture.LoadImage(data);
    }

    /// <summary>
    /// Called on local or remote error.
    /// </summary>
    private void OnError(Socket socket, Packet packet, params object[] args)
    {
        AddMessage(string.Format("--ERROR - {0}", args[0].ToString()));
    }

    #endregion
}
"; #endregion #region SignalR SimpleStreamingSample public static string SignalR_SimpleStreamingSample = @"
using System;

using UnityEngine;
using BestHTTP.SignalR;

sealed class SimpleStreamingSample : MonoBehaviour
{
    readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/streaming-connection");

    /// <summary>
    /// Reference to the SignalR Connection
    /// </summary>
    Connection signalRConnection;

    /// <summary>
    /// Helper GUI class to handle and display a string-list
    /// </summary>
    GUIMessageList messages = new GUIMessageList();

    #region Unity Events

    void Start()
    {
        // Create the SignalR connection
        signalRConnection = new Connection(URI);

        // set event handlers
        signalRConnection.OnNonHubMessage += signalRConnection_OnNonHubMessage;
        signalRConnection.OnStateChanged += signalRConnection_OnStateChanged;
        signalRConnection.OnError += signalRConnection_OnError;

        // Start connecting to the server
        signalRConnection.Open();
    }

    void OnDestroy()
    {
        // Close the connection when the sample is closed
        signalRConnection.Close();
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
        {
            GUILayout.Label("Messages");

            GUILayout.BeginHorizontal();
                GUILayout.Space(20);
                messages.Draw(Screen.width - 20, 0);
            GUILayout.EndHorizontal();
        });
    }

    #endregion

    #region SignalR Events

    /// <summary>
    /// Handle Server-sent messages
    /// </summary>
    void signalRConnection_OnNonHubMessage(Connection connection, object data)
    {
        messages.Add("[Server Message] " + data.ToString());
    }

    /// <summary>
    /// Display state changes
    /// </summary>
    void signalRConnection_OnStateChanged(Connection connection, ConnectionStates oldState, ConnectionStates newState)
    {
        messages.Add(string.Format("[State Change] {0} => {1}", oldState, newState));
    }

    /// <summary>
    /// Display errors.
    /// </summary>
    void signalRConnection_OnError(Connection connection, string error)
    {
        messages.Add("[Error] " + error);
    }

    #endregion
}
"; #endregion #region SignalR ConnectionAPISample public static string SignalR_ConnectionAPISample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP.SignalR;
using BestHTTP.Cookies;

public sealed class ConnectionAPISample : MonoBehaviour
{
    readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/");

    /// <summary>
    /// Possible message types that the client can send to the server
    /// </summary>
    enum MessageTypes
    {
        Send,               // 0
        Broadcast,          // 1
        Join,               // 2
        PrivateMessage,     // 3
        AddToGroup,         // 4
        RemoveFromGroup,    // 5
        SendToGroup,        // 6
        BroadcastExceptMe,  // 7
    }

    #region Private Fields

    /// <summary>
    /// Reference to the SignalR Connection
    /// </summary>
    Connection signalRConnection;

    // Input strings
    string ToEveryBodyText = string.Empty;
    string ToMeText = string.Empty;
    string PrivateMessageText = string.Empty;
    string PrivateMessageUserOrGroupName = string.Empty;

    GUIMessageList messages = new GUIMessageList();

    #endregion

    #region Unity Events

    void Start()
    {
        // SaveLocal a "user" cookie if we previously used the 'Enter Name' button.
        // The server will set this username to the new connection.
        if (PlayerPrefs.HasKey("userName"))
            CookieJar.SaveLocal(URI, new Cookie("user"PlayerPrefs.GetString("userName")));

        signalRConnection = new Connection(URI);

        // to serialize the Message class, set a more advanced json encoder
        signalRConnection.JsonEncoder = new BestHTTP.SignalR.JsonEncoders.LitJsonEncoder();

        // set up event handlers
        signalRConnection.OnStateChanged += signalRConnection_OnStateChanged;
        signalRConnection.OnNonHubMessage += signalRConnection_OnGeneralMessage;

        // Start to connect to the server.
        signalRConnection.Open();
    }

    /// <summary>
    /// Draw the gui.
    /// Get input strings.
    /// Handle function calls.
    /// </summary>
    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
        {
            GUILayout.BeginVertical();

                #region To Everybody
                GUILayout.Label("To Everybody");

                GUILayout.BeginHorizontal();
            
                    ToEveryBodyText = GUILayout.TextField(ToEveryBodyText, GUILayout.MinWidth(100));

                    if (GUILayout.Button("Broadcast"))
                        Broadcast(ToEveryBodyText);

                    if (GUILayout.Button("Broadcast (All Except Me)"))
                        BroadcastExceptMe(ToEveryBodyText);

                    if (GUILayout.Button("Enter Name"))
                        EnterName(ToEveryBodyText);

                    if (GUILayout.Button("Join Group"))
                        JoinGroup(ToEveryBodyText);

                    if (GUILayout.Button("Leave Group"))
                        LeaveGroup(ToEveryBodyText);

                GUILayout.EndHorizontal();
                #endregion

                #region To Me
                GUILayout.Label("To Me");

                GUILayout.BeginHorizontal();

                ToMeText = GUILayout.TextField(ToMeText, GUILayout.MinWidth(100));

                if (GUILayout.Button("Send to me"))
                    SendToMe(ToMeText);

                GUILayout.EndHorizontal();
                #endregion

                #region Private Message
                GUILayout.Label("Private Message");

                GUILayout.BeginHorizontal();

                    GUILayout.Label("Message:");
                    PrivateMessageText = GUILayout.TextField(PrivateMessageText, GUILayout.MinWidth(100));

                    GUILayout.Label("User or Group name:");
                    PrivateMessageUserOrGroupName = GUILayout.TextField(PrivateMessageUserOrGroupName, GUILayout.MinWidth(100));

                    if (GUILayout.Button("Send to user"))
                        SendToUser(PrivateMessageUserOrGroupName, PrivateMessageText);

                    if (GUILayout.Button("Send to group"))
                        SendToGroup(PrivateMessageUserOrGroupName, PrivateMessageText);

                GUILayout.EndHorizontal();
                #endregion

                GUILayout.Space(20);

                if (signalRConnection.State == ConnectionStates.Closed)
                {
                    if (GUILayout.Button("Start Connection"))
                        signalRConnection.Open();
                }
                else if (GUILayout.Button("Stop Connection"))
                        signalRConnection.Close();

                GUILayout.Space(20);

                // Draw the messages
                GUILayout.Label("Messages");

                GUILayout.BeginHorizontal();
                    GUILayout.Space(20);
                    messages.Draw(Screen.width - 20, 0);
                GUILayout.EndHorizontal();

            GUILayout.EndVertical();
        });
    }

    void OnDestroy()
    {
        // Close the connection when the sample is closed
        signalRConnection.Close();
    }

    #endregion

    #region SignalR Events

    /// <summary>
    /// Handle non-hub messages
    /// </summary>
    void signalRConnection_OnGeneralMessage(Connection manager, object data)
    {
        // For now, just create a Json string from the sent data again
        string reencoded = BestHTTP.JSON.Json.Encode(data);
        
        // and display it
        messages.Add("[Server Message] " + reencoded);
    }

    void signalRConnection_OnStateChanged(Connection manager, ConnectionStates oldState, ConnectionStates newState)
    {
        // display state changes
        messages.Add(string.Format("[State Change] {0} => {1}", oldState.ToString(), newState.ToString()));
    }

    #endregion

    #region To EveryBody Functions

    /// <summary>
    /// Broadcast a message to all connected clients
    /// </summary>
    private void Broadcast(string text)
    {
        signalRConnection.Send(new { Type = MessageTypes.Broadcast, Value = text });
    }

    /// <summary>
    /// Broadcast a message to all connected clients, except this client
    /// </summary>
    private void BroadcastExceptMe(string text)
    {
        signalRConnection.Send(new { Type = MessageTypes.BroadcastExceptMe, Value = text });
    }

    /// <summary>
    /// SaveLocal a name for this connection.
    /// </summary>
    private void EnterName(string name)
    {
        signalRConnection.Send(new { Type = MessageTypes.Join, Value = name });
    }

    /// <summary>
    /// Join to a group
    /// </summary>
    private void JoinGroup(string groupName)
    {
        signalRConnection.Send(new { Type = MessageTypes.AddToGroup, Value = groupName });
    }

    /// <summary>
    /// Leave a group
    /// </summary>
    private void LeaveGroup(string groupName)
    {
        signalRConnection.Send(new { Type = MessageTypes.RemoveFromGroup, Value = groupName });
    }

    #endregion

    #region To Me Functions

    /// <summary>
    /// Send a message to the very same client through the server
    /// </summary>
    void SendToMe(string text)
    {
        signalRConnection.Send(new { Type = MessageTypes.Send, Value = text });
    }

    #endregion

    #region Private Message Functions

    /// <summary>
    /// Send a private message to a user
    /// </summary>
    void SendToUser(string userOrGroupName, string text)
    {
        signalRConnection.Send(new { Type = MessageTypes.PrivateMessage, Value = string.Format("{0}|{1}", userOrGroupName, text) });
    }

    /// <summary>
    /// Send a message to a group
    /// </summary>
    void SendToGroup(string userOrGroupName, string text)
    {
        signalRConnection.Send(new { Type = MessageTypes.SendToGroup, Value = string.Format("{0}|{1}", userOrGroupName, text) });
    }

    #endregion
}
"; #endregion #region SignalR ConnectionStatusSample public static string SignalR_ConnectionStatusSample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP.SignalR;
using BestHTTP.SignalR.Hubs;

sealed class ConnectionStatusSample : MonoBehaviour
{
    readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/signalr");

    /// <summary>
    /// Reference to the SignalR Connection
    /// </summary>
    Connection signalRConnection;

    GUIMessageList messages = new GUIMessageList();

    #region Unity Events

    void Start()
    {
        // Connect to the StatusHub hub
        signalRConnection = new Connection(URI, "StatusHub");

        // General events
        signalRConnection.OnNonHubMessage += signalRConnection_OnNonHubMessage;
        signalRConnection.OnError += signalRConnection_OnError;
        signalRConnection.OnStateChanged += signalRConnection_OnStateChanged;

        // SaveLocal up a Callback for Hub events
        signalRConnection["StatusHub"].OnMethodCall += statusHub_OnMethodCall;

        // Connect to the server
        signalRConnection.Open();
    }

    void OnDestroy()
    {
        // Close the connection when we are closing the sample
        signalRConnection.Close();
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
        {
            GUILayout.BeginHorizontal();

                if (GUILayout.Button("START") && signalRConnection.State != ConnectionStates.Connected)
                    signalRConnection.Open();

                if (GUILayout.Button("STOP") && signalRConnection.State == ConnectionStates.Connected)
                {
                    signalRConnection.Close();
                    messages.Clear();
                }

                if (GUILayout.Button("PING") && signalRConnection.State == ConnectionStates.Connected)
                {
                    // Call a Hub-method on the server.
                    signalRConnection["StatusHub"].Call("Ping");
                }

            GUILayout.EndHorizontal();

            GUILayout.Space(20);

            GUILayout.Label("Connection Status Messages");

            GUILayout.BeginHorizontal();
                GUILayout.Space(20);
                messages.Draw(Screen.width - 20, 0);
            GUILayout.EndHorizontal();
        });
    }

    #endregion

    #region SignalR Events

    /// <summary>
    /// Called on server-sent non-hub messages.
    /// </summary>
    void signalRConnection_OnNonHubMessage(Connection manager, object data)
    {
        messages.Add("[Server Message] " + data.ToString());
    }

    /// <summary>
    /// Called when the SignalR Connection's state changes.
    /// </summary>
    void signalRConnection_OnStateChanged(Connection manager, ConnectionStates oldState, ConnectionStates newState)
    {
        messages.Add(string.Format("[State Change] {0} => {1}", oldState, newState));
    }

    /// <summary>
    /// Called when an error occures. The plugin may close the connection after this event.
    /// </summary>
    void signalRConnection_OnError(Connection manager, string error)
    {
        messages.Add("[Error] " + error);
    }

    /// <summary>
    /// Called when the "StatusHub" hub wants to call a method on this client.
    /// </summary>
    void statusHub_OnMethodCall(Hub hub, string method, params object[] args)
    {
        string id = args.Length > 0 ? args[0] as string : string.Empty;
        string when = args.Length > 1 ? args[1].ToString() : string.Empty;

        switch (method)
        {
            case "joined":
                messages.Add(string.Format("[{0}] {1} joined at {2}", hub.Name, id, when));
                break;

            case "rejoined":
                messages.Add(string.Format("[{0}] {1} reconnected at {2}", hub.Name, id, when));
                break;

            case "leave":
                messages.Add(string.Format("[{0}] {1} leaved at {2}", hub.Name, id, when));
                break;

            default// pong
                messages.Add(string.Format("[{0}] {1}", hub.Name, method));
                break;
        }
    }

    #endregion
}
"; #endregion #region SignalR DemoHubSample public static string SignalR_DemoHubSample = @"
using System;

using UnityEngine;

using BestHTTP.SignalR;
using BestHTTP.SignalR.Hubs;
using BestHTTP.SignalR.Messages;
using BestHTTP.SignalR.JsonEncoders;

class DemoHubSample : MonoBehaviour
{
    readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/signalr");

    /// <summary>
    /// The SignalR connection instance
    /// </summary>
    Connection signalRConnection;
    
    /// <summary>
    /// DemoHub client side implementation
    /// </summary>
    DemoHub demoHub;

    /// <summary>
    /// TypedDemoHub client side implementation
    /// </summary>
    TypedDemoHub typedDemoHub;

    /// <summary>
    ///  VB .NET Hub
    /// </summary>
    Hub vbDemoHub;

    /// <summary>
    /// Result of the VB demo's ReadStateValue call
    /// </summary>
    string vbReadStateResult = string.Empty;

    Vector2 scrollPos;    

    void Start()
    {
        // Create the hubs
        demoHub = new DemoHub();
        typedDemoHub = new TypedDemoHub();
        vbDemoHub = new Hub("vbdemo");

        // Create the SignalR connection, passing all the three hubs to it
        signalRConnection = new Connection(URI, demoHub, typedDemoHub, vbDemoHub);

        // Switch from the default encoder to the LitJson Encoder becouse it can handle the complex types too.
        signalRConnection.JsonEncoder = new LitJsonEncoder();

        // Call the demo functions when we successfully connect to the server
        signalRConnection.OnConnected += (connection) =>
            {
                var person = new { Name = "Foo", Age = 20, Address = new { Street = "One Microsoft Way", Zip = "98052" } };

                // Call the demo functions

                demoHub.ReportProgress("Long running job!");
                demoHub.AddToGroups();
                demoHub.GetValue();
                demoHub.TaskWithException();
                demoHub.GenericTaskWithException();
                demoHub.SynchronousException();
                demoHub.DynamicTask();
                demoHub.PassingDynamicComplex(person);
                demoHub.SimpleArray(new int[] { 5, 5, 6 });
                demoHub.ComplexType(person);
                demoHub.ComplexArray(new object[] { person, person, person });

                demoHub.Overload();

                // set some state
                demoHub.State["name"] = "Testing state!";
                demoHub.ReadStateValue();

                demoHub.PlainTask();
                demoHub.GenericTaskWithContinueWith();

                typedDemoHub.Echo("Typed echo Callback");

                // vbDemo is not wrapped in a hub class, it would contain only one function
                vbDemoHub.Call("readStateValue", (hub, msg, result) => vbReadStateResult = string.Format("Read some state from VB.NET! => {0}", result.ReturnValue == null ? "undefined" : result.ReturnValue.ToString()));
            };

        // Start opening the signalR connection
        signalRConnection.Open();
    }

    void OnDestroy()
    {
        // Close the connection when we are closing this sample
        signalRConnection.Close();
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
        {
            scrollPos = GUILayout.BeginScrollView(scrollPos, falsefalse);
                GUILayout.BeginVertical();

                    demoHub.Draw();

                    typedDemoHub.Draw();

                    GUILayout.Label("Read State Value");
                    GUILayout.BeginHorizontal();
                        GUILayout.Space(20);
                        GUILayout.Label(vbReadStateResult);
                    GUILayout.EndHorizontal();

                    GUILayout.Space(10);

                GUILayout.EndVertical();
            GUILayout.EndScrollView();
        });

    }
}

/// <summary>
/// Wrapper class of the 'TypedDemoHub' hub
/// </summary>
class TypedDemoHub : Hub
{
    string typedEchoResult = string.Empty;
    string typedEchoClientResult = string.Empty;

    public TypedDemoHub()
        :base("typeddemohub")
    {

    }

    /// <summary>
    /// Called by the Connection class to be able to set up mappings.
    /// </summary>
    public override void Setup()
    {
        // Setup server-called functions
        base.On("Echo", Echo);
    }

    #region Server Called Functions

    /// <summary>
    /// Server-called, client side implementation of the Echo function
    /// </summary>
    private void Echo(Hub hub, MethodCallMessage methodCall)
    {
        typedEchoClientResult = string.Format("{0} #{1} triggered!", methodCall.Arguments[0], methodCall.Arguments[1]);
    }

    #endregion

    #region Client Called Function(s)

    /// <summary>
    /// Client-called, server side implementation of the Echo function.
    /// When the function successfully executed on the server the OnEcho_Done Callback function will be called.
    /// </summary>
    public void Echo(string msg)
    {
        base.Call("echo", OnEcho_Done, msg);
    }

    /// <summary>
    /// When the function successfully executed on the server this Callback function will be called.
    /// </summary>
    private void OnEcho_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        typedEchoResult = "TypedDemoHub.Echo(string message) invoked!";
    }

    #endregion

    public void Draw()
    {
        GUILayout.Label("Typed Callback");

        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.BeginVertical();
                GUILayout.Label(typedEchoResult);
                GUILayout.Label(typedEchoClientResult);
            GUILayout.EndVertical();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);
    }
}

/// <summary>
/// A wrapper class for the 'DemoHub' hub.
/// </summary>
class DemoHub : Hub
{
    #region Private fields

    // These fields are here to store results of the function calls

    float longRunningJobProgress = 0f;
    string longRunningJobStatus = "Not Started!";
    string fromArbitraryCodeResult = string.Empty;
    string groupAddedResult = string.Empty;
    string dynamicTaskResult = string.Empty;
    string genericTaskResult = string.Empty;
    string taskWithExceptionResult = string.Empty;
    string genericTaskWithExceptionResult = string.Empty;
    string synchronousExceptionResult = string.Empty;
    string invokingHubMethodWithDynamicResult = string.Empty;
    string simpleArrayResult = string.Empty;
    string complexTypeResult = string.Empty;
    string complexArrayResult = string.Empty;
    string voidOverloadResult = string.Empty;
    string intOverloadResult = string.Empty;
    string readStateResult = string.Empty;
    string plainTaskResult = string.Empty;
    string genericTaskWithContinueWithResult = string.Empty;
    GUIMessageList invokeResults = new GUIMessageList();

    #endregion

    public DemoHub()
        : base("demo")
    {
    }

    /// <summary>
    /// Called by the Connection class to be able to set up mappings.
    /// </summary>
    public override void Setup()
    {
        // Setup server-called functions
        base.On("invoke", Invoke);
        base.On("signal", Signal);
        base.On("groupAdded", GroupAdded);
        base.On("fromArbitraryCode", FromArbitraryCode);
    }

    #region Client Called Functions

    #region ReportProgress

    public void ReportProgress(string arg)
    {
        Call("reportProgress", OnLongRunningJob_Done, null, OnLongRunningJob_Progress, arg);
    }

    public void OnLongRunningJob_Progress(Hub hub, ClientMessage originialMessage, ProgressMessage progress)
    {
        longRunningJobProgress = (float)progress.Progress;
        longRunningJobStatus = progress.Progress.ToString() + "%";
    }

    public void OnLongRunningJob_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        longRunningJobStatus = result.ReturnValue.ToString();

        MultipleCalls();
    }

    #endregion

    public void MultipleCalls()
    {
        base.Call("multipleCalls");
    }

    #region DynamicTask

    public void DynamicTask()
    {
        base.Call("dynamicTask", OnDynamicTask_Done, OnDynamicTask_Failed);
    }

    private void OnDynamicTask_Failed(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        dynamicTaskResult = string.Format("The dynamic task failed :( {0}", result.ErrorMessage);
    }

    private void OnDynamicTask_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        dynamicTaskResult = string.Format("The dynamic task! {0}", result.ReturnValue);
    }

    #endregion

    public void AddToGroups()
    {
        base.Call("addToGroups");
    }

    public void GetValue()
    {
        base.Call("getValue", (hub, msg, result) => genericTaskResult = string.Format("The value is {0} after 5 seconds", result.ReturnValue));
    }

    public void TaskWithException()
    {
        base.Call("taskWithException"null, (hub, msg, result) => taskWithExceptionResult = string.Format("Error: {0}", result.ErrorMessage));
    }

    public void GenericTaskWithException()
    {
        base.Call("genericTaskWithException"null, (hub, msg, result) => genericTaskWithExceptionResult = string.Format("Error: {0}", result.ErrorMessage));
    }

    public void SynchronousException()
    {
        base.Call("synchronousException"null, (hub, msg, result) => synchronousExceptionResult = string.Format("Error: {0}", result.ErrorMessage));
    }

    public void PassingDynamicComplex(object person)
    {
        base.Call("passingDynamicComplex", (hub, msg, result) => invokingHubMethodWithDynamicResult = string.Format("The person's age is {0}", result.ReturnValue), person);
    }

    public void SimpleArray(int[] array)
    {
        base.Call("simpleArray", (hub, msg, result) => simpleArrayResult = "Simple array works!", array);
    }

    public void ComplexType(object person)
    {
        base.Call("complexType", (hub, msg, result) => complexTypeResult = string.Format("Complex Type -> {0}", (this as IHub).Connection.JsonEncoder.Encode(this.State["person"])), person);
    }

    public void ComplexArray(object[] complexArray)
    {
        // We need to cast the object array to object to keep it as an array
        // http://stackoverflow.com/questions/36350/how-to-pass-a-single-object-to-a-params-object
        base.Call("ComplexArray", (hub, msg, result) => complexArrayResult = "Complex Array Works!", (object)complexArray);
    }

    #region Overloads

    public void Overload()
    {
        base.Call("Overload", OnVoidOverload_Done);
    }

    private void OnVoidOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        voidOverloadResult = "Void Overload called";

        Overload(101);
    }

    public void Overload(int number)
    {
        base.Call("Overload", OnIntOverload_Done, number);
    }

    private void OnIntOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        intOverloadResult = string.Format("Overload with return value called => {0}", result.ReturnValue.ToString());
    }

    #endregion

    public void ReadStateValue()
    {
        base.Call("readStateValue", (hub, msg, result) => readStateResult = string.Format("Read some state! => {0}", result.ReturnValue));
    }

    public void PlainTask()
    {
        base.Call("plainTask", (hub, msg, result) => plainTaskResult = "Plain Task Result");
    }

    public void GenericTaskWithContinueWith()
    {
        base.Call("genericTaskWithContinueWith", (hub, msg, result) => genericTaskWithContinueWithResult = result.ReturnValue.ToString());
    }

    #endregion

    #region Server Called Functions

    private void FromArbitraryCode(Hub hub, MethodCallMessage methodCall)
    {
        fromArbitraryCodeResult = methodCall.Arguments[0] as string;
    }

    private void GroupAdded(Hub hub, MethodCallMessage methodCall)
    {
        if (!string.IsNullOrEmpty(groupAddedResult))
            groupAddedResult = "Group Already Added!";
        else
            groupAddedResult = "Group Added!";
    }

    private void Signal(Hub hub, MethodCallMessage methodCall)
    {
        dynamicTaskResult = string.Format("The dynamic task! {0}", methodCall.Arguments[0]);
    }

    private void Invoke(Hub hub, MethodCallMessage methodCall)
    {
        invokeResults.Add(string.Format("{0} client state index -> {1}", methodCall.Arguments[0], this.State["index"]));
    }

    #endregion

    #region Draw

    /// <summary>
    /// Display the result's of the function calls.
    /// </summary>
    public void Draw()
    {
        GUILayout.Label("Arbitrary Code");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(string.Format("Sending {0} from arbitrary code without the hub itself!", fromArbitraryCodeResult));
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Group Added");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(groupAddedResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Dynamic Task");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(dynamicTaskResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Report Progress");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.BeginVertical();
                GUILayout.Label(longRunningJobStatus);
                GUILayout.HorizontalSlider(longRunningJobProgress, 0, 100);
            GUILayout.EndVertical();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Generic Task");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(genericTaskResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Task With Exception");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(taskWithExceptionResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Generic Task With Exception");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(genericTaskWithExceptionResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Synchronous Exception");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(synchronousExceptionResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Invoking hub method with dynamic");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(invokingHubMethodWithDynamicResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Simple Array");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(simpleArrayResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Complex Type");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(complexTypeResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Complex Array");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(complexArrayResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Overloads");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.BeginVertical();
                GUILayout.Label(voidOverloadResult);
                GUILayout.Label(intOverloadResult);
            GUILayout.EndVertical();
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Read State Value");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(readStateResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Plain Task");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(plainTaskResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Generic Task With ContinueWith");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            GUILayout.Label(genericTaskWithContinueWithResult);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);

        GUILayout.Label("Message Pump");
        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            invokeResults.Draw(Screen.width - 40, 270);
        GUILayout.EndHorizontal();

        GUILayout.Space(10);
    }

    #endregion
}
"; #endregion #region SignalR AuthenticationSample public static string SignalR_AuthenticationSample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP.SignalR;
using BestHTTP.SignalR.Hubs;
using BestHTTP.SignalR.Messages;
using BestHTTP.SignalR.Authentication;

class AuthenticationSample : MonoBehaviour
{
    readonly Uri URI = new Uri("https://besthttpsignalr.azurewebsites.net/signalr");

    #region Private Fields

    /// <summary>
    /// Reference to the SignalR Connection
    /// </summary>
    Connection signalRConnection;

    string userName = string.Empty;
    string role = string.Empty;

    Vector2 scrollPos;

    #endregion

    #region Unity Events

    void Start()
    {
        // Create the SignalR connection, and pass the hubs that we want to connect to
        signalRConnection = new Connection(URI, new BaseHub("noauthhub""Messages"),
                                                new BaseHub("invokeauthhub""Messages Invoked By Admin or Invoker"),
                                                new BaseHub("authhub""Messages Requiring Authentication to Send or Receive"),
                                                new BaseHub("inheritauthhub""Messages Requiring Authentication to Send or Receive Because of Inheritance"),
                                                new BaseHub("incomingauthhub""Messages Requiring Authentication to Send"),
                                                new BaseHub("adminauthhub""Messages Requiring Admin Membership to Send or Receive"),                            
                                                new BaseHub("userandroleauthhub""Messages Requiring Name to be \"User\" and Role to be \"Admin\" to Send or Receive"));
        
        // SaveLocal the authenticator if we have valid fields
        if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(role))
            signalRConnection.AuthenticationProvider = new HeaderAuthenticator(userName, role);

        // SaveLocal up event handler
        signalRConnection.OnConnected += signalRConnection_OnConnected;

        // Start to connect to the server.
        signalRConnection.Open();
    }

    void OnDestroy()
    {
        // Close the connection when we are closing the sample
        signalRConnection.Close();
    }

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
        {
            scrollPos = GUILayout.BeginScrollView(scrollPos, falsefalse);
                GUILayout.BeginVertical();

                if (signalRConnection.AuthenticationProvider == null)
                {
                    GUILayout.BeginHorizontal();
                        GUILayout.Label("Username (Enter 'User'):");
                        userName = GUILayout.TextField(userName, GUILayout.MinWidth(100));
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                        GUILayout.Label("Roles (Enter 'Invoker' or 'Admin'):");
                        role = GUILayout.TextField(role, GUILayout.MinWidth(100));
                    GUILayout.EndHorizontal();

                    if (GUILayout.Button("Log in"))
                        Restart();
                }

                for (int i = 0; i < signalRConnection.Hubs.Length; ++i)
                    (signalRConnection.Hubs[i] as BaseHub).Draw();

                GUILayout.EndVertical();
            GUILayout.EndScrollView();
        });
    }

    #endregion

    /// <summary>
    /// Called when we successfully connected to the server.
    /// </summary>
    void signalRConnection_OnConnected(Connection manager)
    {
        // call 'InvokedFromClient' on all hubs
        for (int i = 0; i < signalRConnection.Hubs.Length; ++i)
            (signalRConnection.Hubs[i] as BaseHub).InvokedFromClient();
    }

    /// <summary>
    /// Helper function to do a hard-restart to the server.
    /// </summary>
    void Restart()
    {
        // Clean up
        signalRConnection.OnConnected -= signalRConnection_OnConnected;

        // Close current connection
        signalRConnection.Close();
        signalRConnection = null;

        // start again, with authentication if we filled in all input fields
        Start();

    }
}

/// <summary>
/// Hub implementation for the authentication demo. All hubs that we connect to has the same server and client side functions.
/// </summary>
class BaseHub : Hub
{
    #region Private Fields

    /// <summary>
    /// Hub specific title
    /// </summary>
    private string Title;

    private GUIMessageList messages = new GUIMessageList();

    #endregion

    public BaseHub(string name, string title)
        : base(name)
    {
        this.Title = title;
    }

    /// <summary>
    /// Called by the Connection class to be able to set up mappings.
    /// </summary>
    public override void Setup()
    {
        // Map the server-callable method names to the real functions.
        On("joined", Joined);
        On("rejoined", Rejoined);
        On("left", Left);
        On("invoked", Invoked);
    }

    #region Server Called Functions

    private void Joined(Hub hub, MethodCallMessage methodCall)
    {
        Dictionary<stringobject> AuthInfo = methodCall.Arguments[2] as Dictionary<stringobject>;
        messages.Add(string.Format("{0} joined at {1}\n\tIsAuthenticated: {2} IsAdmin: {3} UserName: {4}", methodCall.Arguments[0], methodCall.Arguments[1], AuthInfo["IsAuthenticated"], AuthInfo["IsAdmin"], AuthInfo["UserName"]));
    }

    private void Rejoined(Hub hub, MethodCallMessage methodCall)
    {
        messages.Add(string.Format("{0} reconnected at {1}", methodCall.Arguments[0], methodCall.Arguments[1]));
    }

    private void Left(Hub hub, MethodCallMessage methodCall)
    {
        messages.Add(string.Format("{0} left at {1}", methodCall.Arguments[0], methodCall.Arguments[1]));
    }

    private void Invoked(Hub hub, MethodCallMessage methodCall)
    {
        messages.Add(string.Format("{0} invoked hub method at {1}", methodCall.Arguments[0], methodCall.Arguments[1]));
    }

    #endregion

    #region Client callable function implementation

    public void InvokedFromClient()
    {
        base.Call("invokedFromClient", OnInvoked, OnInvokeFailed);
    }

    private void OnInvoked(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        Debug.Log(hub.Name + " invokedFromClient success!");
    }

    /// <summary>
    /// This Callback function will be called every time we try to access a protected API while we are using an non-authenticated connection.
    /// </summary>
    private void OnInvokeFailed(Hub hub, ClientMessage originalMessage, ResultMessage result)
    {
        Debug.LogWarning(hub.Name + " " + result.ErrorMessage);
    }

    #endregion

    public void Draw()
    {
        GUILayout.Label(this.Title);

        GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            messages.Draw(Screen.width - 20, 100);
        GUILayout.EndHorizontal();
    }
}
"; #endregion #region CacheMaintenanceSample public static string CacheMaintenanceSample = @"
using System;
using System.Collections.Generic;

using UnityEngine;
using BestHTTP;
using BestHTTP.Caching;

public sealed class CacheMaintenanceSample : MonoBehaviour
{
    /// <summary>
    /// An enum for better readability
    /// </summary>
    enum DeleteOlderTypes
    {
        Days,
        Hours,
        Mins,
        Secs
    };

    #region Private Fields

    /// <summary>
    /// What methode to call on the TimeSpan
    /// </summary>
    DeleteOlderTypes deleteOlderType = DeleteOlderTypes.Secs;

    /// <summary>
    /// The value for the TimeSpan.
    /// </summary>
    int value = 10;

    /// <summary>
    /// What's our maximum cache size
    /// </summary>
    int maxCacheSize = 5 * 1024 * 1024;

    #endregion

    #region Unity Events

    void OnGUI()
    {
        GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
            {
                GUILayout.BeginHorizontal();
                                                    
                    GUILayout.Label("Delete cached entities older then");

                    GUILayout.Label(value.ToString(), GUILayout.MinWidth(50));
                    value = (int)GUILayout.HorizontalSlider(value, 1, 60, GUILayout.MinWidth(100));

                    GUILayout.Space(10);

                    deleteOlderType = (DeleteOlderTypes)(int)GUILayout.SelectionGrid((int)deleteOlderType, new string[] { "Days""Hours""Mins""Secs" }, 4);
                    GUILayout.FlexibleSpace();
                    GUILayout.EndHorizontal();

                GUILayout.Space(10);

                GUILayout.BeginHorizontal();
                    GUILayout.Label("Max Cache Size (bytes): "GUILayout.Width(150));
                    GUILayout.Label(maxCacheSize.ToString("N0"), GUILayout.Width(70));
                    maxCacheSize = (int)GUILayout.HorizontalSlider(maxCacheSize, 1024, 10 * 1024 * 1024);
                GUILayout.EndHorizontal();

                GUILayout.Space(10);

                if (GUILayout.Button("Maintenance"))
                {
                    TimeSpan deleteOlder = TimeSpan.FromDays(14);

                    switch (deleteOlderType)
                    {
                        case DeleteOlderTypes.Days: deleteOlder = TimeSpan.FromDays(value); break;
                        case DeleteOlderTypes.Hours: deleteOlder = TimeSpan.FromHours(value); break;
                        case DeleteOlderTypes.Mins: deleteOlder = TimeSpan.FromMinutes(value); break;
                        case DeleteOlderTypes.Secs: deleteOlder = TimeSpan.FromSeconds(value); break;
                    }

                    // Call the BeginMaintainence function. It will run on a thread to do not block the main thread.
                    HTTPCacheService.BeginMaintainence(new HTTPCacheMaintananceParams(deleteOlder, (ulong)maxCacheSize));
                }
            });
    }

    #endregion
}
"; #endregion } }