/// <summary>
        /// Turn the coffee machine on.
        /// </summary>
        /// <param name="customMinutesToTurnOff">A custom time in milliseconds to turn of the machine
        /// if automatic turn off mode is switched on.</param>
        private void TurnOnCoffeeMachine(int customMinutesToTurnOff = 0)
        {
            // If delay timer was running, dispose it at this point
            TurnOnCoffeeMachineTimer?.Dispose();

            this.MachineState = CoffeeMachineState.Brewing;

            Ports.Led.Write(true);
            Ports.Relay.Write(false);

            // Setup automatic turn off if requested by the client.
            if (TurnOffMode == TurnOffMode.Automatic)
            {
                // Check if request is overriding previous request and dispose
                // previous turn off timer in that case.
                TurnOffCoffeeTimer?.Dispose();

                TimeSpan dueTime = new TimeSpan(0, customMinutesToTurnOff <= 0 ? TURN_OFF_MIN_DEFAULT : customMinutesToTurnOff, 0);
                TurningMachineOffAt = DateTime.Now.AddTicks(dueTime.Ticks);

                TurnOffCoffeeTimer = new Timer((obj) => { TurnOffCoffeeMachine(); }, null, dueTime, dueTime);
            }
            else
            {
                // Check if request is overriding previous request and dispose
                // previous turn off timer in that case.
                TurnOffCoffeeTimer?.Dispose();
            }
        }
        /// <summary>
        /// Request to turn the coffee machine on.
        /// </summary>
        /// <param name="turnOffMode"></param>
        /// <param name="customMsToTurnOff">A custom time in milliseconds to turn of the machine
        /// if automatic turn off mode is switched on.</param>
        /// <param name="delayBrewingByMinutes">The delay in milliseconds, befor turning the coffee machine on.</param>
        public void RequestTurnOnCoffeeMachine(TurnOffMode turnOffMode    = TurnOffMode.Automatic,
                                               int customMinutesToTurnOff = 0, int delayBrewingByMinutes = 0)
        {
            TurnOffMode = turnOffMode;

            // Delay the brewing if requested and the machine was not already in brewing mode
            if (delayBrewingByMinutes > 0 && MachineState != CoffeeMachineState.Brewing)
            {
                // Check if request is overriding previous request and dispose
                // previous turn on timer in that case.
                TurnOnCoffeeMachineTimer?.Dispose();

                this.MachineState = CoffeeMachineState.TimedForActivation;

                BrewingCoffeeAt = DateTime.Now.AddMinutes(delayBrewingByMinutes);

                TimeSpan dueTime = new TimeSpan(0, delayBrewingByMinutes, 0);

                TurnOnCoffeeMachineTimer = new Timer((obj) => { TurnOnCoffeeMachine(customMinutesToTurnOff); },
                                                     null, dueTime, dueTime);
            }
            else
            {
                // Check if request is overriding previous request and dispose
                // previous turn on timer in that case.
                TurnOnCoffeeMachineTimer?.Dispose();

                TurnOnCoffeeMachine(customMinutesToTurnOff);
            }
        }
        /// <summary>
        /// Request to turn the coffee machine off and all delayed processes.
        /// </summary>
        public void RequestTurnOffCoffeeMachine()
        {
            // Release and stop the delayed brewing
            TurnOnCoffeeMachineTimer?.Dispose();

            BrewingCoffeeAt = DateTime.MinValue;

            // Finally turn the machine off
            TurnOffCoffeeMachine();
        }
        public void RequestChangeBrewingDelay(int minutes)
        {
            if (MachineState == CoffeeMachineState.TimedForActivation)
            {
                var      delay = BrewingCoffeeAt.AddMinutes(minutes);
                TimeSpan dueDate;

                if (delay < DateTime.Now)
                {
                    dueDate = new TimeSpan(0, 0, 0, 0, 1);
                }
                else
                {
                    BrewingCoffeeAt = delay;

                    dueDate = delay - DateTime.Now;
                }

                TurnOnCoffeeMachineTimer.Change(dueDate, dueDate.Add(new TimeSpan(1, 0, 0)));
            }
        }