/// <summary>
        /// Checks if the Azure VM SKU supports premium disks
        /// </summary>
        /// <param name="azureVMListItem">Azure VM SKU Item</param>
        /// <returns> A value indicating if theAzure VM SKU supports premium disks or not</returns>
        public static bool CheckIfAzureVMInstanceTypeIsPremiumSupported(AzureVMSizeListItem azureVMListItem)
        {
            bool isPremiumSupported = false;

            Regex r = new Regex(AzureVMHelperConstants.AzureVMSupportSSDRegex, RegexOptions.IgnoreCase);
            Match m = r.Match(azureVMListItem.Name);

            if (m.Success)
            {
                isPremiumSupported = true;
            }

            return(isPremiumSupported);
        }
        /// <summary>
        /// Get the Azure VM SKU cost
        /// </summary>
        /// <param name="vmListItem">The Azure VM SKU</param>
        /// <param name="specs">The input specifications</param>
        /// <returns> Returns the Azure VM SKU cost</returns>
        private static double GetAzureVMCost(AzureVMSizeListItem vmListItem, VMSpecs specs)
        {
            double rate = 0;

            try
            {
                AzureResourceInfo resourceInfo = AzureVMMeterHelper.GetAzureResourceInfoForAzureVM(vmListItem.Name, specs.OperatingSystem, location);
                rate = rateCalc.GetResourceRate(resourceInfo);
            }
            catch (Exception)
            {
                throw;
            }

            return(rate);
        }
        /// <summary>
        /// Maps the instance to an Azure VM SKU
        /// </summary>
        /// <param name="vmRes">The object that will contain the mapping output</param>
        /// <param name="location">The Azure location</param>
        /// <param name="azureVMSizeList">The list of Azure VM SKUs</param>
        /// <param name="rateCalc">The object that can fetch the rates for Azure resources</param>
        /// <param name="listOfOverrideVMSizes">The list of Input Override Azure VM SKUs if provided</param>
        /// <param name="mappingCoefficientCoresSelection">Mapping Coefficient for CPU Cores</param>
        /// <param name="mappingCoefficientMemorySelection">Mapping Coefficient for Memory</param>
        public static void ProjectAzureVM(VMResult vmRes, string location, List <AzureVMSizeListItem> azureVMSizeList, AzureResourceRateCalc rateCalc, List <OverrideVMSpecs> listOfOverrideVMSizes, double mappingCoefficientCoresSelection, double mappingCoefficientMemorySelection)
        {
            AzureVMProjector.rateCalc = rateCalc;
            AzureVMProjector.location = location;

            try
            {
                int dataDiskCount = 0;
                dataDiskCount = GetDataDiskCount(vmRes);

                // Check if Preferred VM Size Exists
                bool isPreferredVMSizeValid = false;
                AzureVMSizeListItem vmListItemForMatchedOverride = null;

                // Override with VM Specific if provided
                if (!string.IsNullOrWhiteSpace(vmRes.Specs.AzureVMOverride))
                {
                    vmListItemForMatchedOverride = azureVMSizeList.Find(x => x.Name.Equals(vmRes.Specs.AzureVMOverride, StringComparison.OrdinalIgnoreCase));
                    if (vmListItemForMatchedOverride != null)
                    {
                        if (vmListItemForMatchedOverride.MaxDataDiskCount >= dataDiskCount)
                        {
                            isPreferredVMSizeValid                    = true;
                            vmRes.ProjAzureVM.ComputeHoursRate        = GetAzureVMCost(vmListItemForMatchedOverride, vmRes.Specs);
                            vmRes.ProjAzureVM.VMSize                  = vmListItemForMatchedOverride;
                            vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsVMMapasperSpecificOverride;
                        }
                        else
                        {
                            vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsSpecificOverrideExceedDiskCount;
                        }
                    }
                    else
                    {
                        vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsSpecificOverrideNotFound;
                    }
                }

                // Override with generic Override file if match found and not already mapped by specific override value
                if (!isPreferredVMSizeValid && listOfOverrideVMSizes != null)
                {
                    OverrideVMSpecs matchedOverrideVMDetails = listOfOverrideVMSizes.Find(x => (x.IsValid && vmRes.Specs.CPUCores == x.CPUCores && vmRes.Specs.MemoryInMB == x.MemoryInMB && vmRes.Specs.OperatingSystem.Equals(x.OperatingSystem, StringComparison.OrdinalIgnoreCase) && ((x.HasSSDStorage && vmRes.Specs.SSDStorageInGB > 0) || (!x.HasSSDStorage && vmRes.Specs.SSDStorageInGB == 0)) && (x.NumberOfDataDisks == dataDiskCount) && !string.IsNullOrWhiteSpace(x.AzureVMOverride)));
                    if (matchedOverrideVMDetails != null)
                    {
                        vmListItemForMatchedOverride = azureVMSizeList.Find(x => x.Name.Equals(matchedOverrideVMDetails.AzureVMOverride, StringComparison.OrdinalIgnoreCase));
                        if (vmListItemForMatchedOverride != null)
                        {
                            if (vmListItemForMatchedOverride.MaxDataDiskCount >= dataDiskCount)
                            {
                                isPreferredVMSizeValid                    = true;
                                vmRes.ProjAzureVM.ComputeHoursRate        = GetAzureVMCost(vmListItemForMatchedOverride, vmRes.Specs);
                                vmRes.ProjAzureVM.VMSize                  = vmListItemForMatchedOverride;
                                vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsVMMappedasperGenericOverride;
                            }
                            else
                            {
                                vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsGenericOverrideExceedDiskCount;
                            }
                        }
                        else
                        {
                            vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsGenericOverrideNotFound;
                        }
                    }
                }

                // If PreferredVMSize does not exist or if PreferredVMSize is not valid, loop thru' the list to project using projection algorithm
                if (!isPreferredVMSizeValid)
                {
                    foreach (AzureVMSizeListItem vmListItem in azureVMSizeList)
                    {
                        bool considerListItem = false;

                        // If Current Azure VM Size does not support Premium Disks and VM contains mapped premium disks - skip the size
                        if (vmRes.ProjAzureVM.PremiumDisks != null && vmRes.ProjAzureVM.PremiumDisks.Count > 0 && !AzureVMMeterHelper.CheckIfAzureVMInstanceTypeIsPremiumSupported(vmListItem))
                        {
                            continue;
                        }

                        // If Current Azure VM Size does is for Premium Disks and VM contains does not contains premium disks - skip the size
                        if ((vmRes.ProjAzureVM.PremiumDisks == null || (vmRes.ProjAzureVM.PremiumDisks != null && vmRes.ProjAzureVM.PremiumDisks.Count == 0)) && AzureVMMeterHelper.CheckIfAzureVMInstanceTypeIsPremiumSupported(vmListItem))
                        {
                            continue;
                        }

                        // Skip if number of data disks mapped is more than maximum of current item
                        if (dataDiskCount > vmListItem.MaxDataDiskCount)
                        {
                            continue;
                        }

                        if (vmListItem.NumberOfCores >= mappingCoefficientCoresSelection * vmRes.Specs.CPUCores)
                        {
                            if (vmListItem.MemoryInMB >= mappingCoefficientMemorySelection * vmRes.Specs.MemoryInMB)
                            {
                                considerListItem = true;
                            }
                        }

                        if (considerListItem)
                        {
                            bool   mapCurrentItem            = false;
                            double currentVMSizeListItemRate = GetAzureVMCost(vmListItem, vmRes.Specs);
                            if (vmRes.ProjAzureVM.VMSize == null)
                            {
                                mapCurrentItem = true;
                            }
                            else
                            {
                                if (vmRes.ProjAzureVM.ComputeHoursRate > currentVMSizeListItemRate)
                                {
                                    mapCurrentItem = true;
                                }
                            }

                            if (mapCurrentItem)
                            {
                                vmRes.ProjAzureVM.IsMappedasperOverride = false;
                                vmRes.ProjAzureVM.VMSize           = vmListItem;
                                vmRes.ProjAzureVM.ComputeHoursRate = currentVMSizeListItemRate;
                            }
                        }
                    }
                }
                else
                {
                    vmRes.ProjAzureVM.IsMappedasperOverride = true;
                }

                if (vmRes.ProjAzureVM.VMSize == null)
                {
                    vmRes.ProjAzureVM.IsNoMapFound            = true;
                    vmRes.ProjAzureVM.AzureProjectionComments = AzureVMProjectionCommentsLiterals.ProjectionCommentsVMCannotbeMapped;
                }
                else
                {
                    vmRes.ProjAzureVM.IsNoMapFound = false;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }