/* Copyright (c) 2008-2011 - Eric P. Mangold
 * Released under the terms of the MIT/X11 license - see LICENSE.txt */
using System;
using System.Net.Sockets;
using System.Threading;

namespace MathClient
{
    class Client
    {
        static void Main(string[] args)
        {
            string hostname = "localhost";
            int port = 1234;

            var client = new TcpClient(hostname, port);
            var protocol = new AMP.Protocol(client.GetStream());
            protocol.StartReading(); // start the async data-reading loop

            // Instantiate the Commands we're going to call
            AMP.Command sum = new MathServer.Sum();
            AMP.Command div = new MathServer.Divide();

            // Make one remote call synchronously. CallRemote() will raise an exception if
            // anything goes wrong making the call.
            AMP.Msg msg = protocol.CallRemote(sum, new AMP.Msg { { "a", 5 }, { "b", 7 } });
            Console.WriteLine("Got sum result: {0}", (int)msg["total"]);
            Thread.Sleep(2000);

            // Now make some asynchronous calls in a loop
            int count = 3;
            while (count-- > 0)
            {
                // pass the AMP.Protocol object though as the `state' parameter since we need it in the callback
                protocol.BeginCallRemote(sum, new AMP.Msg { { "a", 13 }, { "b", 81 } }, CBGotSumResponse, protocol);
                Thread.Sleep(2000);
            }

            // Do a division
            try
            {
                msg = protocol.CallRemote(div, new AMP.Msg { { "numerator", 10 }, { "denominator", 3 } });
            }
            catch (DivideByZeroException)
            {
                System.Console.WriteLine("Shouldn't have caused zero division here!");
                return;
            }
            Console.WriteLine("Got division result: {0}", (decimal)msg["result"]);

            // Now do it again, but this time cause a DivideByZeroException on the remote end,
            // which will result in a DivideByZeroException being raised here, because the 
            // Divide command has been implemented to handle this particular Exception.
            try
            {
                msg = protocol.CallRemote(div, new AMP.Msg { { "numerator", 10 }, { "denominator", 0 } });
            }
            catch (DivideByZeroException)
            {
                System.Console.WriteLine("Got DivideByZeroException as expected.");
            }

            Console.ReadKey(); // Press any key to continue...
        }
        
        // Call-back method for receiving result from server asynchronously
        static void CBGotSumResponse(IAsyncResult ar)
        {
            var protocol = (AMP.Protocol)ar.AsyncState;
            // EndCallRemote() will raise if any error occured during the remote call
            AMP.Msg respMsg = protocol.EndCallRemote(ar);
            Console.WriteLine("Got sum: {0}", (int)respMsg["total"]);
        }
    }
}
