public CreateProfileViewModel(IScreen hostScreen, IFermentationControllerAPI api)
        {
            HostScreen = hostScreen;

            AllSteps = new ReactiveList <StepData> ();

            StepTiles = AllSteps.CreateDerivedCollection(x => new ProfileStepTileViewModel(x.StepId, x));

            var canAddStep = this.WhenAnyValue(x => x.StepDays, x => x.StepHours, x => x.StepMins)
                             .Select(x => x.Item1 > 0 || x.Item2 > 0 || x.Item3 > 0);

            AddStep = ReactiveCommand.Create(canAddStep);
            AddStep
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(x => new StepData(TemperatureConvert.ConvertToCelsius(StartingTemp),
                                      TemperatureConvert.ConvertToCelsius(EndingTemp),
                                      new TimeSpan(StepDays,
                                                   StepHours,
                                                   StepMins,
                                                   0),
                                      AllSteps.Count + 1,
                                      IsRampStep))
            .Subscribe(AllSteps.Add);

            var canCommit = this.WhenAnyValue(x => x.Name, x => x.AllSteps).Select(x => !string.IsNullOrWhiteSpace(x.Item1) && x.Item2.Count > 0);

            CommitProfile = ReactiveCommand.CreateAsyncTask(canCommit, (x, ct) => {
                //TODO: create the profile dto
                return(api.StoreProfile(Name, new byte[0]));
            }, RxApp.MainThreadScheduler);

            //on non-ramp steps the starting and ending temp are the same
            this.WhenAnyValue(x => x.StartingTemp, y => y.IsRampStep)
            .Where(x => !x.Item2)
            .Subscribe(x => EndingTemp = StartingTemp);
        }
        public MainPageViewModel(IFermentationControllerAPI fermApi, IScreen hostScreen)
        {
            var retry = Polly.Policy.Handle <WebException>().WaitAndRetryAsync(1, x => TimeSpan.FromSeconds(Math.Pow(2, x)));

            HostScreen = hostScreen;

            SetTimeToNow = ReactiveCommand.CreateAsyncTask(async _ => {
                var secFromEpoch = DateTimeMixins.SecondsFromEpoch();
                await retry.ExecuteAsync(() => fermApi.SetTime(secFromEpoch));
            });

            Echo = ReactiveCommand.CreateAsyncTask(async _ => {
                var response = await retry.ExecuteAsync(() => fermApi.Echo(this.EchoText));
                return(response);
            });

            Echo.ToProperty(this, vm => vm.EchoResponse, out _EchoResponse);

            GetStatus = ReactiveCommand.CreateAsyncTask(async _ => {
                string output = string.Empty;
                var response  = await retry.ExecuteAsync(fermApi.GetStatus);
                var theData   = Convert.FromBase64String(response);
                using (var ms = new MemoryStream(theData))
                {
                    var systemTime               = ms.ReadUInt32();
                    var systemMode               = ms.ReadByte();
                    var regMode                  = ms.ReadByte();
                    var probe0Assignment         = ms.ReadByte();
                    var probe0Temp               = ms.ReadUInt16();
                    var probe1Assignment         = ms.ReadByte();
                    var probe1Temp               = ms.ReadUInt16();
                    var heatRelayStatus          = ms.ReadByte();
                    var coolRelayStatus          = ms.ReadByte();
                    var runningProfile           = ms.ReadString(64);
                    var profileStepIdx           = ms.ReadUInt16();
                    var profileStepTemp          = ms.ReadUInt16();
                    var profileStepTimeRemaining = ms.ReadUInt32();
                    var manualSetpointTemp       = ms.ReadUInt16();
                    var profileStartTime         = ms.ReadUInt32();

                    output += string.Format("System Time:{0}\n", DateTimeMixins.TimeFromEpoch(systemTime));
                    output += string.Format("System Mode:{0}\n", systemMode);
                    output += string.Format("Regulation Mode:{0}\n", regMode);

                    output += string.Format("Probe0 Assign:{0}\n", probe0Assignment);
                    output += string.Format("Probe0 Temp C:{0}\n", probe0Temp / 10.0);

                    output += string.Format("Probe1 Assign:{0}\n", probe1Assignment);
                    output += string.Format("Probe1 Temp C:{0}\n", probe1Temp / 10.0);

                    output += string.Format("Heat Relay Status:{0}\n", heatRelayStatus);
                    output += string.Format("Cool Relay Status:{0}\n", coolRelayStatus);

                    output += string.Format("Running Profile:{0}\n", runningProfile);

                    output += string.Format("Profile Step Index:{0}\n", profileStepIdx);
                    output += string.Format("Profile Step Temperature C:{0}\n", profileStepTemp / 10.0);
                    output += string.Format("Profile Step Time Remaining:{0}\n", profileStepTimeRemaining);
                    output += string.Format("Manual Setpoint Temp C:{0}\n", manualSetpointTemp / 10.0);
                    output += string.Format("Profile Start Time:{0}\n", DateTimeMixins.TimeFromEpoch(profileStartTime));
                }

                return(output);
            });

            GetStatus.ThrownExceptions
            .Select(x => new UserError("Status cannot be retrieved", "Check your connected to the TEMPERATURE wifi"))
            .SelectMany(UserError.Throw);

            GetStatus.ToProperty(this, vm => vm.StatusResponse, out _StatusResponse);

            NavigateToCreateProfilePage = ReactiveCommand.Create();
            NavigateToCreateProfilePage
            .Subscribe(_ => HostScreen.Router.Navigate.Execute(new CreateProfileViewModel(hostScreen, fermApi)));

            NavigateToPreferencesPage = ReactiveCommand.Create();
            NavigateToPreferencesPage
            .Subscribe(_ => HostScreen.Router.Navigate.Execute(new PreferencesPageViewModel(hostScreen, new UserSettings())));
        }