﻿using System;
using System.Collections.Generic;
using Thrift.Server;
using Thrift.Transport;

namespace CSharpTutorial
{
    public class CalculatorHandler : Calculator.Iface
    {
        Dictionary<int, SharedStruct> log;

        public CalculatorHandler()
        {
            log = new Dictionary<int, SharedStruct>();
        }

        public void ping()
        {
            Console.WriteLine("ping()");
        }

        public int add(int n1, int n2)
        {
            Console.WriteLine("add({0},{1})", n1, n2);
            return n1 + n2;
        }

        public int calculate(int logid, Work work)
        {
            Console.WriteLine("calculate({0}, [{1},{2},{3}])", logid, work.op, work.num1, work.num2);
            int val = 0;
            switch (work.op)
            {
                case Operation.ADD:
                    val = work.num1 + work.num2;
                    break;

                case Operation.SUBTRACT:
                    val = work.num1 - work.num2;
                    break;

                case Operation.MULTIPLY:
                    val = work.num1 * work.num2;
                    break;

                case Operation.DIVIDE:
                    if (work.num2 == 0)
                    {
                        InvalidOperation io = new InvalidOperation();
                        io.what = (int)work.op;
                        io.why = "Cannot divide by 0";
                        throw io;
                    }
                    val = work.num1 / work.num2;
                    break;

                default:
                    {
                        InvalidOperation io = new InvalidOperation();
                        io.what = (int)work.op;
                        io.why = "Unknown operation";
                        throw io;
                    }
            }

            SharedStruct entry = new SharedStruct();
            entry.key = logid;
            entry.value = val.ToString();
            log[logid] = entry;

            return val;
        }

        public SharedStruct getStruct(int key)
        {
            Console.WriteLine("getStruct({0})", key);
            return log[key];
        }

        public void zip()
        {
            Console.WriteLine("zip()");
        }
    }

    public class CSharpServer
    {
        public static void Main()
        {
            try
            {
                CalculatorHandler handler = new CalculatorHandler();
                Calculator.Processor processor = new Calculator.Processor(handler);
                TServerTransport serverTransport = new TServerSocket(9090);
                TServer server = new TSimpleServer(processor, serverTransport);

                // Use this for a multithreaded server
                // server = new TThreadPoolServer(processor, serverTransport);

                Console.WriteLine("Starting the server...");
                server.Serve();
            }
            catch (Exception x)
            {
                Console.WriteLine(x.StackTrace);
            }
            Console.WriteLine("done.");
        }
    }
}
