/// <summary>
        /// Get the Software details for the Specified Offer and SKU of the Azure VM Image
        /// </summary>
        /// <param name="offer">Offer of the Azure VM Image</param>
        /// <param name="sku">SKU of the Azure VM Image</param>
        /// <param name="vmImageList">List of VM Image Info with Software Cost</param>
        /// <returns> Returns the details of the VM Image having Software Cost if matched. If no match is found, null is returned</returns>
        private static VMImageHavingSoftwareCost GetVMImageFilteredListbyOfferSKUNames(string offer, string sku, List <VMImageHavingSoftwareCost> vmImageList)
        {
            VMImageHavingSoftwareCost vmImageFilteredList = null;

            foreach (VMImageHavingSoftwareCost vmImage in vmImageList)
            {
                // Check if in Exception list of Offer/SKU, If so continue with next listitem in foreach loop
                if (ListContainsStringIgnoreCase(vmImage.VMImageOfferNamesExceptions, offer) || ListContainsStringIgnoreCase(vmImage.VMImageSKUNamesExceptions, sku))
                {
                    continue;
                }

                // Check if In Offer List, If not continue with next listitem in foreach loop
                bool isInOfferList = false;
                isInOfferList = vmImage.VMImageOfferNames == null ? true : ListContainsStringIgnoreCase(vmImage.VMImageOfferNames, offer);
                if (!isInOfferList)
                {
                    continue;
                }

                // Check if In SKU List
                bool isInSKUList = false;
                isInSKUList = vmImage.VMImageSKUNames == null ? true : ListContainsStringIgnoreCase(vmImage.VMImageSKUNames, sku);

                // If found, set the object to be returned
                if (isInOfferList && isInSKUList)
                {
                    vmImageFilteredList = vmImage;
                    break;
                }
            }

            return(vmImageFilteredList);
        }
        /// <summary>
        /// Gets the Meter SubCategory String for the specified Azure VM Image having Software Cost
        /// </summary>
        /// <param name="cspCreds">CSP Account credentials object. A token will be generated using these credentials and used for making the online ARM API call</param>
        /// <param name="publisher">Publisher of the Azure VM Image</param>
        /// <param name="offer">Offer of the Azure VM Image</param>
        /// <param name="sku">SKU of the Azure VM Image</param>
        /// <param name="vmSize">VM Size String</param>
        /// <param name="location">Azure Location</param>
        /// <returns> Returns the Meter SubCategory for the Software Cost associated with the Azure VM Image</returns>
        public static string GetMeterSubCategoryForVMImageWithSoftwareCost(CSPAccountCreds cspCreds, string publisher, string offer, string sku, string vmSize, string location)
        {
            string meterSubCategory = null;

            try
            {
                // Get Filtered List by Publisher
                List <VMImageHavingSoftwareCost> vmImageFilteredList =
                    vmImageHavingSoftwareCostList.FindAll(x => x.VMImagePublisherName.Equals(publisher, StringComparison.OrdinalIgnoreCase));

                // Get Filtered List by Offer Names, SKU Names
                VMImageHavingSoftwareCost vmImageHavingSoftwareCost = GetVMImageFilteredListbyOfferSKUNames(offer, sku, vmImageHavingSoftwareCostList);

                if (vmImageHavingSoftwareCost != null)
                {
                    int cores = -1, coresListIndex = -1;
                    cores = VMOnlineHelper.GetCoresForVmSize(cspCreds, vmSize, location);
                    if (cores != -1)
                    {
                        coresListIndex = GetLowestIndexForItemInSortedArray(vmImageHavingSoftwareCost.MeterSubCategoryCoresList, cores);
                    }

                    if (coresListIndex == -1)
                    {
                        throw new Exception(ExceptionLogger.GenerateLoggerTextForInternalError("Unsupported number of cores while calculating software cost for the VM Image"));
                    }
                    else
                    {
                        string[] templateParams = null;
                        templateParams = SetValuesForMeterSubCategoryTemplateParams(vmImageHavingSoftwareCost, coresListIndex, sku, cores);

                        if (templateParams != null)
                        {
                            meterSubCategory = coresListIndex == 0 ? string.Format(vmImageHavingSoftwareCost.VMMeterSubCategoryStrTemplateForFirst, templateParams)
                                : string.Format(vmImageHavingSoftwareCost.VMMeterSubCategoryStrTemplate, templateParams);
                        }
                        else
                        {
                            meterSubCategory = coresListIndex == 0 ? vmImageHavingSoftwareCost.VMMeterSubCategoryStrTemplateForFirst
                            : vmImageHavingSoftwareCost.VMMeterSubCategoryStrTemplate;
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }

            return(meterSubCategory);
        }
        /// <summary>
        /// Gets the array of Strings having values for the template variables to form the Meter SubCategory for the Software cost component of the Azure VM Image
        /// </summary>
        /// <param name="vmImageHavingSoftwareCost">Details of the VM Image having software cost</param>
        /// <param name="coresListIndex">Index of the item in the list of Software Cost. This is used to check if its first in the list. </param>
        /// <param name="sku">SKU of the Azure VM Image.</param>
        /// <param name="cores">Number of cores of the Azure VM image. </param>
        /// <returns> Returns the array of Strings having values for the template variables to form the Meter SubCategory</returns>
        private static string[] SetValuesForMeterSubCategoryTemplateParams(VMImageHavingSoftwareCost vmImageHavingSoftwareCost, int coresListIndex, string sku, int cores)
        {
            string[]          templateParams   = null;
            OrderedDictionary strTemplateItems = coresListIndex == 0 ? vmImageHavingSoftwareCost.StrTemplateItemsForFirst : vmImageHavingSoftwareCost.StrTemplateItems;

            if (strTemplateItems != null && strTemplateItems.Count != 0)
            {
                if (strTemplateItems.Contains(StrTemplateItemKeys.Cores.ToString()))
                {
                    strTemplateItems[StrTemplateItemKeys.Cores.ToString()] = cores.ToString();
                }

                if (strTemplateItems.Contains(StrTemplateItemKeys.SKU.ToString()))
                {
                    strTemplateItems[StrTemplateItemKeys.SKU.ToString()] = sku;
                }

                templateParams = new string[strTemplateItems.Count];
                ICollection valueCollection = strTemplateItems.Values;
                valueCollection.CopyTo(templateParams, 0);
            }

            return(templateParams);
        }