/// <summary>
        /// Checks if this PaymentCommand is a special command that is a cached command
        /// </summary>
        /// <param name="command">PaymentCommand</param>
        /// <param name="serverStores">The itemObject pointer, to verify that it is not null</param>
        /// <returns>true of it is a cached message, otherwise false</returns>
        public bool IsCachedMessage(PaymentCommand command, object itemObject)
        {
            bool isCachedMessage = false;
            Dictionary <string, string> specialCommands = new Dictionary <string, string>();

            specialCommands.Add("GetStoreInventory", "HangoutStore");
            string value = SpecialCommand(command.Noun, command.Verb, specialCommands);

            switch (value)
            {
            case "GetStoreInventory":
                if (itemObject != null)
                {
                    string       storeName    = GetStringValueFromArgs(command.Parameters, "storeName", "");
                    ServerStores serverStores = (ServerStores)itemObject;
                    if (serverStores.IsCachedStore(storeName))
                    {
                        isCachedMessage = true;
                    }
                }
                break;
            }


            return(isCachedMessage);
        }
        /// <summary>
        /// Method used to start a ProcessMessage blocking method call
        /// If this is a cached message then retreive the data from the response data from the cache
        /// <param name="xmlClientMessage">PaymentItem client message</param>
        /// <param name="xmlClientMessage"></param>
        /// <returns>PaymentItems xml string response</returns>
        public string ProcessMessageBlocking(string xmlClientMessage, ServerStores serverStores, getUserIdDelegate getUserIdCall)
        {
            string response = "";

            try
            {
                PaymentItemsProcessClientMessage clientMessage = new PaymentItemsProcessClientMessage();
                ServiceCommand serviceCommand = (ServiceCommand)clientMessage.ProcessMessage(xmlClientMessage, getUserIdCall);
                if (clientMessage.IsCachedMessage((PaymentCommand)serviceCommand, serverStores))
                {
                    response = clientMessage.GetCachedStoreData((PaymentCommand)serviceCommand, serverStores);
                }
                else
                {
                    response = InvokeServiceBlocking(serviceCommand);
                }
            }

            catch (Exception ex)
            {
                response = String.Format("<Error><Message>{0}</Message></Error>", ex);
                mLogger.Error(String.Format("Error ProcessMessageBlocking: {0}", response));
            }

            return(response);
        }
        /// <summary>
        /// Retreive the Cached data from the store data cache
        /// Then filter it, sorted it and apply any paging.
        /// </summary>
        /// <param name="command">PaymentCommand</param>
        /// <param name="serverStores">serverStores object</param>
        /// <returns>The cached store response filtered, sorted and paged</returns>
        public string GetCachedStoreData(PaymentCommand command, ServerStores serverStores)
        {
            string response = "";

            if (serverStores != null)
            {
                string storeName = GetStringValueFromArgs(command.Parameters, "storeName", "");

                XmlDocument xmlResponse     = serverStores.GetStoreResponseXML(storeName);
                Object      dataSetResponse = serverStores.GetStoreResponseDataSet(storeName);

                response = FilterSortStoreInventoryResponse(xmlResponse, dataSetResponse, command);
            }

            return(response);
        }
        /// <summary>
        /// For each item purchased, add the asset info from the asset database
        /// </summary>
        /// <param name="response"></param>
        /// <param name="serverStores"></param>
        /// <returns></returns>
        public static XmlDocument AddAssetsToPurchaseResponse(XmlDocument response, ServerStores serverStores)
        {
            XmlNodeList itemNodes = response.SelectNodes("Response/purchaseResults/purchaseResult/offer/item");

            foreach (XmlElement itemNode in itemNodes)
            {
                string      itemId    = itemNode.GetAttribute("name");
                string      assetData = "<Assets>" + serverStores.PaymentItemsManager.GetAssetDataSetDna(itemId) + "</Assets>";
                XmlDocument assetXml  = new XmlDocument();
                assetXml.LoadXml(assetData);
                XmlNode assetNode = assetXml.SelectSingleNode("Assets");

                XmlNode newChildNode = response.ImportNode(assetNode, true);
                itemNode.AppendChild(newChildNode);
            }

            return(response);
        }
        /// <summary>
        /// PaymentItemManager constuctor
        /// </summary>
        /// <param name="serverStateMachine">A pointer to the server state machine</param>
        /// <param name="sendMessageToReflectorCallback">A pointer to send a message to the reflector</param>
        public PaymentItemsManager(ServerStateMachine serverStateMachine) : base(serverStateMachine)
        {
            mServerStores             = new ServerStores(this);
            mMoneyPaymentNotifyClient = new MoneyPaymentNotifyClient(SendMessageToClient);

            // Initialize the remoting interface
            try
            {
                mCallToService = new RemoteCallToService();
                mCallToService.RemoteConnect();
                mCallToService.ActivateTheInterface();
                mPaymentItems = new PaymentItemsProcess();
                mPaymentItems.ActivateTheInterface();
            }
            catch
            {
                mLogger.Warn("Error in activating the payment items interface");
            }
        }
        /// <summary>
        /// Add Items node to the user inventory itemInstance node
        /// </summary>
        /// <param name="response">The Hangout user inventory xml response</param>
        /// <param name="handler">The ServerStores object, containing the item inventory information</param>
        /// <returns>The Hangout user inventory xml response with the user inventory node added to the itemInstance nodes</returns>
        public static XmlDocument AddItemsToUserInventory(XmlDocument response, ServerStores serverStores)
        {
            XmlDocument inventoryResponse = new XmlDocument();

            try
            {
                if (response == null)
                {
                    inventoryResponse = CreateErrorDoc("Error: Cached Response for PaymentItems User Inventory Response is not available");
                }
                else
                {
                    XmlNode itemInstancesNode = response.SelectSingleNode("/");

                    string itemTypeNames = itemInstancesNode.SelectSingleNode("/Response/itemInstances").Attributes["itemTypeNames"].InnerText.Trim();

                    //<itemInstances startIndex="5" blockSize="10" total="55">
                    int startIndex = serverStores.ConvertToInt(itemInstancesNode.SelectSingleNode("/Response/itemInstances").Attributes["startIndex"].InnerText, -1);
                    int blockSize  = serverStores.ConvertToInt(itemInstancesNode.SelectSingleNode("/Response/itemInstances").Attributes["blockSize"].InnerText, -1);

                    int startPosition = 0;
                    int endPosition   = itemInstancesNode.SelectNodes("Response/itemInstances/itemInstance").Count;

                    if (UseBlockSize(startIndex, blockSize, endPosition, itemTypeNames.Length))
                    {
                        startPosition = startIndex;
                        int maxEndPosition = blockSize + startIndex;
                        if (maxEndPosition < endPosition)
                        {
                            endPosition = maxEndPosition;
                        }
                    }

                    ServerPaymentItemsDataSets dataSets = new ServerPaymentItemsDataSets();
                    DataSet dsUserInventoryCreated      = dataSets.CreateUserInventoryDataSet("InstanceDataSet");
                    // DataSet dsInstance = serverStores.LoadXMLInToDataSet(itemInstancesNode, dsUserInventoryCreated);

                    DataSet dsInstance = dataSets.LoadUserInventoryXMLIntoDataSet(itemInstancesNode, dsUserInventoryCreated, startPosition, endPosition);

                    //MemoryStream schema = serverStores.LoadSchemaFile("UserInventoryImportSchema.xsd");
                    //DataSet dsInstance = serverStores.LoadXMLInToDataSet(itemInstancesNode, schema, "InstanceDataSet");

                    DataTable dtInstance = dsInstance.Tables["itemInstance"];
                    DataTable dtItem     = dsInstance.Tables["item"];

                    foreach (DataRow instanceRow in dtInstance.Rows)
                    {
                        string  itemId  = instanceRow["itemId"].ToString();
                        DataRow itemRow = serverStores.FindItemInStore(itemId);
                        if (itemRow != null)
                        {
                            string hangoutItemId = instanceRow["itemName"].ToString();
                            itemRow["itemInstance_Id"] = instanceRow["itemInstance_Id"];
                            dtItem.ImportRow(itemRow);
                        }
                    }

                    StringWriter sw = new StringWriter();
                    dsInstance.WriteXml(sw);

                    XmlDocument responseTemp = new XmlDocument();
                    responseTemp.LoadXml(UnEscapeXml(sw.ToString()));

                    if (itemTypeNames.Length > 0)
                    {
                        responseTemp = FilterUserInventoryByItemTypes(responseTemp, itemTypeNames, startIndex, blockSize);
                    }

                    inventoryResponse.LoadXml(responseTemp.SelectSingleNode("/InstanceDataSet").InnerXml);
                }
            }

            catch (Exception ex)
            {
                mLogger.Error("Inventory response Error: ", ex);
                inventoryResponse = CreateErrorDoc(ex.ToString());
            }

            return(inventoryResponse);
        }
        /// <summary>
        /// Check if this is a special response
        /// If a special response then call the special response handler to modify the response xml
        /// </summary>
        /// <param name="responseData">The PaymentItems response string xml data</param>
        /// <returns>The response string xml data, modified if a special response else the inputed xml data</returns>
        public XmlDocument SpecialResponse(XmlDocument response, string noun, string verb, ServerStores serverStores)
        {
            MoneyTransactionLogging moneyLog = new MoneyTransactionLogging();

            Dictionary <string, string> specialResponses = new Dictionary <string, string>();

            specialResponses.Add("GetUserInventory", "HangoutUsers");
            specialResponses.Add("PurchaseGameCurrencyPayPal", "HangoutPurchase");
            specialResponses.Add("PurchaseGameCurrencyCreditCard", "HangoutPurchase");
            specialResponses.Add("PurchaseItems", "HangoutUsers");

            string value = SpecialCommand(noun, verb, specialResponses);

            switch (value)
            {
            case "GetUserInventory":
                response = PaymentItemsSortFilter.AddItemsToUserInventory(response, serverStores);
                break;

            case "PurchaseItems":
                response = PaymentItemsSortFilter.AddAssetsToPurchaseResponse(response, serverStores);
                break;

            case "PurchaseGameCurrencyPayPal":
                moneyLog.PayPalLogResponse(response, "InProgress");
                break;

            case "PurchaseGameCurrencyCreditCard":
                moneyLog.CreditCardLogResponse(response);
                break;
            }

            return(response);
        }
        /// <summary>
        /// Method used to start a ProcessMessage async method call
        /// This method processes PaymentItems messages
        /// If this is a cached message then retreive the data from the response data from the cache
        /// </summary>
        /// <param name="xmlClientMessage">PaymentItem client message</param>
        /// <param name="sender">List of session GUID's to send the response to</param>
        /// <param name="callback">Callback that is called on response from service</param>
        /// <returns>blank if no error else the error message</returns>
        public string ProcessMessageAsync(string xmlClientMessage, System.Action <string> callback, ServerStores serverStores, getUserIdDelegate getUserIdCall)
        {
            string response = "";

            try
            {
                PaymentItemsProcessClientMessage clientMessage = new PaymentItemsProcessClientMessage();
                ServiceCommand serviceCommand = (ServiceCommand)clientMessage.ProcessMessage(xmlClientMessage, getUserIdCall);
                if (clientMessage.IsCachedMessage((PaymentCommand)serviceCommand, serverStores))
                {
                    response = clientMessage.GetCachedStoreData((PaymentCommand)serviceCommand, serverStores);
                    clientMessage.PaymentItemsReturn(response, callback);
                }
                else if (clientMessage.IsDoNothing((PaymentCommand)serviceCommand))
                {
                    response = clientMessage.createDoNothingResponse((PaymentCommand)serviceCommand);
                    clientMessage.PaymentItemsReturn(response, callback);
                }
                else
                {
                    InvokeServiceAsync(serviceCommand, callback);
                }
            }

            catch (Exception ex)
            {
                response = String.Format("<Error><Message>{0}</Message></Error>", ex);
                mLogger.Error(String.Format("Error ProcessMessageAsync: {0}", response));
            }

            return(response);
        }