public async Task <GetCustomerAppliancesResponse> Handle(GetCustomerAppliancesRequest request,
                                                                 CancellationToken cancellationToken)
        {
            if (!_validator.Validate(request).IsValid)
            {
                return(new GetCustomerAppliancesResponse(new [] { new Error("InvalidRequest", "Parameters are incorrect.") }));
            }

            var applianceInfoTask = _applianceService.GetApplianceInfo(request.CustomerGuid);
            var applianceTask     = _applianceService.GetCustomerAppliances(request.CustomerGuid);
            await Task.WhenAll(applianceInfoTask, applianceTask);

            var applianceInfo = applianceInfoTask.Result;
            var appliances    = applianceTask.Result.ToList();

            _applianceService.AddApplianceInfo(appliances, applianceInfo);

            return(new GetCustomerAppliancesResponse(new CustomerAppliancesDto {
                Appliances = appliances
            }));
        }
        public async Task <GetDetailedCustomerPageResponse> Handle(GetDetailedCustomerPageRequest request,
                                                                   CancellationToken cancellationToken)
        {
            if (!_validator.Validate(request).IsValid)
            {
                return(new GetDetailedCustomerPageResponse(new [] { new Error("InvalidRequest", "Parameters are incorrect.") }));
            }

            var applianceInfoTask = _applianceService.GetApplianceInfo(request.CustomerGuid);
            var applianceTask     = _applianceService.GetCustomerAppliances(request.CustomerGuid);

            var responseTask = _applianceService.GetCustomerApplianceHistory(request.CustomerGuid, request.Interval, request.IntervalOffset);
            await Task.WhenAll(responseTask, applianceInfoTask, applianceTask);

            var applianceMap  = applianceTask.Result.ToDictionary(x => x.ApplianceId, x => x);
            var applianceInfo = applianceInfoTask.Result;
            var response      = responseTask.Result;

            if (response == null)
            {
                return(new GetDetailedCustomerPageResponse(new [] { new Error("CouldNotFetchData", "Remote Api did not return any data") }));
            }

            var skips = SkipsDictionary[request.Interval];

            var startTime     = DateTimeOffset.FromUnixTimeSeconds(response.Timestamps.FirstOrDefault());
            var intervalStart = response.Timestamps.Count - skips * (request.IntervalOffset + 1);

            if (intervalStart < 0)
            {
                return(new GetDetailedCustomerPageResponse(new []
                {
                    new Error("InvalidRequest", $"Invalid {nameof(request.IntervalOffset)} parameter: {request.IntervalOffset}.")
                }));
            }

            var intervalStop = intervalStart + skips - 1;

            var intervalStartTime = DateTimeOffset.FromUnixTimeSeconds(response.Timestamps[intervalStart]);
            var intervalStopTime  = DateTimeOffset.FromUnixTimeSeconds(response.Timestamps[intervalStop]);
            var endTime           = DateTimeOffset.FromUnixTimeSeconds(response.Timestamps.LastOrDefault());
            var dataPointFreq     = response.Timestamps.Count / 60;

            var appliances = response.ApplianceTypes.SelectMany(x => x.Appliances, (p, c) =>
            {
                return(new ApplianceUsageDto
                {
                    Appliance = applianceMap.ContainsKey((int)c.ApplianceId) ? applianceMap[(int)c.ApplianceId] : null,
                    TotalAverageUsage = (short?)c.CalculateTotalAverage(),
                    CurrentAverageUsage = (short?)c.PowerConsumption.Skip(intervalStart)
                                          .Take(intervalStop - intervalStart).Average(x => x ?? 0),
                    UsagePoints = c.GetIntervalEveryNthPoint(dataPointFreq)
                });
            }).ToList();

            _applianceService.AddApplianceInfo(appliances.Select(x => x.Appliance), applianceInfo);

            return(new GetDetailedCustomerPageResponse(new CustomerDetailedPageDto
            {
                StartTime = startTime,
                StartTimeInterval = intervalStartTime,
                EndTimeInterval = intervalStopTime,
                EndTime = endTime,
                Appliances = appliances,
                DataPointEvery = response.Timestamps[dataPointFreq] - response.Timestamps[0]
            }));
        }