public static async Task <ParkingRateDTO> CalcNRAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function CalcNormalRates processed a request.");

            string       name              = string.Empty;
            string       requestBody       = await new StreamReader(req.Body).ReadToEndAsync();
            EntryExitDTO entryExitDateTime = JsonConvert.DeserializeObject <EntryExitDTO>(requestBody);

            ParkingRateDTO result = new ParkingRateDTO()
            {
                Name = CONSTANTS.RateType.STANDARD
            };

            string response = await client.GetStringAsync(CONSTANTS.ProjectURLs.ReturnParkingRatesNormal);

            List <NormalRate> normalRates = JsonConvert.DeserializeObject <List <NormalRate> >(response);

            double     resultNormalMacro = 0.0;
            double     resultNormalMicro = 0.0;
            bool       isNormal          = false;
            double     duration          = (entryExitDateTime.EndDT - entryExitDateTime.StartDT).TotalHours;
            NormalRate maxNormalRate     = normalRates.OrderBy(nr => nr.MaxHours).LastOrDefault();

            if (duration >= maxNormalRate.MaxHours)
            {
                resultNormalMacro = Math.Floor(duration / maxNormalRate.MaxHours) * maxNormalRate.Rate;
                duration          = duration % maxNormalRate.MaxHours;
            }
            if (duration > 0)
            {
                foreach (NormalRate normalRate in normalRates)
                {
                    if (!isNormal && duration <= normalRate.MaxHours)
                    {
                        isNormal          = true;
                        resultNormalMicro = normalRate.Rate;
                    }
                }
            }

            result.Price = resultNormalMacro + resultNormalMicro;

            return(result);
        }
        public static async Task <ParkingRateDTO> CalcSRAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function CalcSpecialRates processed a request.");

            string       name              = string.Empty;
            string       requestBody       = await new StreamReader(req.Body).ReadToEndAsync();
            EntryExitDTO entryExitDateTime = JsonConvert.DeserializeObject <EntryExitDTO>(requestBody);

            ParkingRateDTO result = new ParkingRateDTO();

            string response = await client.GetStringAsync(CONSTANTS.ProjectURLs.ReturnParkingRatesSpecial);

            List <SpecialRate> specialRates = JsonConvert.DeserializeObject <List <SpecialRate> >(response);


            foreach (SpecialRate specialRate in specialRates)
            {
                // Start of parking time
                bool isSpecial = (entryExitDateTime.StartDT.TimeOfDay >= specialRate.Entry.Start && entryExitDateTime.StartDT.TimeOfDay <= specialRate.Entry.End) ||
                                 (specialRate.MaxDays > 0 &&
                                  (specialRate.Entry.Start <= entryExitDateTime.StartDT.TimeOfDay &&
                                   entryExitDateTime.StartDT.TimeOfDay <= specialRate.Entry.End.Add(TimeSpan.FromDays(1))) ||
                                  (specialRate.Entry.Start.Subtract(TimeSpan.FromDays(1)) >= entryExitDateTime.StartDT.TimeOfDay &&
                                   entryExitDateTime.StartDT.TimeOfDay <= specialRate.Entry.End));

                if (!specialRate.Entry.Days.Any(d => string.Equals(d, entryExitDateTime.StartDT.DayOfWeek.ToString(), StringComparison.InvariantCultureIgnoreCase)))
                {
                    isSpecial = false;
                }

                // End of parking time
                DateTime maxExitDay = entryExitDateTime.StartDT.AddDays(specialRate.MaxDays);
                DateTime maxExit    = new DateTime(maxExitDay.Year, maxExitDay.Month, maxExitDay.Day, specialRate.Exit.End.Hours,
                                                   specialRate.Exit.End.Minutes, 0);
                if ((entryExitDateTime.EndDT.TimeOfDay < specialRate.Exit.Start || entryExitDateTime.EndDT.TimeOfDay > specialRate.Exit.End))
                {
                    isSpecial = false;
                }
                if (entryExitDateTime.EndDT > maxExit)
                {
                    isSpecial = false;
                }

                if (!specialRate.Exit.Days.Any(d => string.Equals(d, entryExitDateTime.EndDT.DayOfWeek.ToString(), StringComparison.InvariantCultureIgnoreCase)))
                {
                    isSpecial = false;
                }

                if (isSpecial)
                {
                    if (result.Price == 0 || result.Price > specialRate.TotalPrice)
                    {
                        result.Name  = specialRate.Name;
                        result.Price = specialRate.TotalPrice;
                    }
                }
            }

            return(result);
        }
        public static async Task <ParkingRateDTO> CalcRatesAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function CalcRatesAsync processed a request.");

            string       name = string.Empty;
            string       requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic      data = JsonConvert.DeserializeObject(requestBody);
            string       startdt = data?.startDT, enddt = data?.endDT;
            EntryExitDTO entryExitDT = new EntryExitDTO();

            try
            {
                entryExitDT.StartDT = Convert.ToDateTime(startdt);
                entryExitDT.EndDT   = Convert.ToDateTime(enddt);
            }
            catch (Exception)
            {
                log.LogInformation("C# HTTP trigger function CalcRatesAsync processed with bad input dates.");
                return(null); //TODO: return StatusCode instead
            }

            //Call NormalRates Service
            ParkingRateDTO             normalRatesResults = new ParkingRateDTO();
            Task <HttpResponseMessage> postTask           = client.PostAsJsonAsync(CONSTANTS.ProjectURLs.CalcNormalRates, entryExitDT);

            postTask.Wait();

            HttpResponseMessage result = postTask.Result;

            if (result.IsSuccessStatusCode)
            {
                Task <ParkingRateDTO> readTask = result.Content.ReadAsAsync <ParkingRateDTO>();
                readTask.Wait();
                normalRatesResults = readTask.Result;
            }
            else
            {
                log.LogInformation("C# HTTP trigger function CalcRatesAsync failed to get rates from CalcNormalRates.");
            }


            //Call SpecialRates Service
            ParkingRateDTO selectedRatesResults = new ParkingRateDTO();

            postTask = client.PostAsJsonAsync(CONSTANTS.ProjectURLs.CalcSpecialRates, entryExitDT);
            postTask.Wait();

            result = postTask.Result;
            if (result.IsSuccessStatusCode)
            {
                Task <ParkingRateDTO> readTask = result.Content.ReadAsAsync <ParkingRateDTO>();
                readTask.Wait();
                selectedRatesResults = readTask.Result;
            }
            else
            {
                log.LogInformation("C# HTTP trigger function CalcRatesAsync failed to get rates from CalcSpecialRates.");
            }

            // select applicable
            if (normalRatesResults.Price > 0 && (selectedRatesResults.Price == 0 || selectedRatesResults.Price > normalRatesResults.Price))
            {
                selectedRatesResults.Name  = normalRatesResults.Name;
                selectedRatesResults.Price = normalRatesResults.Price;
            }

            return(selectedRatesResults);
        }