using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Reflection;
using System.Collections.ObjectModel;
using System.Web.Caching;

namespace CommunicationSupport
{
    public static class ServiceRequestProcessor
    {

        #region Public Methods

        public static void ProcessRequest(HttpContext context, Type serviceType, string methodName)
        {
            try
            {
                // sprawdza dostępność informacji o usłudze w pamięci podręcznej
                ServiceInfo serviceInfo = context.Cache.Get(serviceType.Name) as ServiceInfo;
                if (serviceInfo == null)
                {
                    serviceInfo = new ServiceInfo(serviceType);
                    // zapisuje usługę w pamięci podręcznej
                    context.Cache.Add(serviceType.Name, serviceInfo, null, DateTime.Now.AddYears(5), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null);
                }

                // uzyskuje referencję do metody
                ServiceMethodInfo serviceMethodInfo;
                if (serviceInfo.Methods.TryGetValue(methodName, out serviceMethodInfo) == false)
                    throw new InvalidOperationException("Metoda nie jest obsługiwana");

                // sprawdza, czy dla danej metody istnieje powiązany obiekt klasy JsonMessageBodyClass
                Type jsonMessageBodyClassType;
                if (serviceInfo.JsonMessageClasses.TryGetValue(methodName, out jsonMessageBodyClassType) == false)
                    throw new ArgumentOutOfRangeException("Metoda " + methodName + " nie dysponuje powiązanym obiektem klasy JsonMessageClass");

                // przypisuje wartości parametrów
                object[] methodParameters = ServiceUtility.AssignParameters(context, jsonMessageBodyClassType, serviceMethodInfo.Parameters, serviceInfo.KnownTypes);

                // tworzy obiekt
                object service = Activator.CreateInstance(serviceType);

                // wywołuje metodę
                object returnValue = serviceMethodInfo.Method.Invoke(service, methodParameters);

                // odsyła dane do klienta
                ServiceUtility.WriteJsonToResponseStream(context, returnValue, serviceMethodInfo.Method.ReturnParameter.ParameterType, serviceInfo.KnownTypes);
            }
            catch(Exception ex)
            {
                ServiceUtility.WriteException(context, ex, 500);
            }
        }

        #endregion

    }
}