/// <summary>
        ///     Helper to convert our 'public-facing' color enum to the delcom light.
        ///     Given that DelcomLightWrapper.LightColors.Yellow == DelcomLightWrapper.LightColors.Blue
        ///     (the byte we send to the light indicating which LED we want to change is the same whether
        ///     it supports yellow or blue), this makes no difference at present.
        /// </summary>
        /// <param name="inputColor"></param>
        /// <returns></returns>
        private DelcomLightWrapper.LightColors ConvertColor(DelcomColor inputColor)
        {
            DelcomLightWrapper.LightColors result = DelcomLightWrapper.LightColors.Red;

            // Make this a configurable value since delcom lights come in both RGY (the default) and RGB, and
            // we want to be able to work with both.
            bool lightSupportsYellow = RRLightProgram.Properties.Settings.Default.LightSupportsYellow;

            switch (inputColor)
            {
            case DelcomColor.Red:
                result = DelcomLightWrapper.LightColors.Red;
                break;

            case DelcomColor.Green:
                result = DelcomLightWrapper.LightColors.Green;
                break;

            case DelcomColor.Yellow:
                // Map yellow to the appropriate color based on what the light supports
                result = lightSupportsYellow ? DelcomLightWrapper.LightColors.Yellow : DelcomLightWrapper.LightColors.Blue;
                break;
            }

            return(result);
        }
        /// <summary>
        ///     Change the color of the light, including options to flash or show for only a particular duration
        /// </summary>
        /// <param name="inputColor"></param>
        /// <param name="steady"></param>
        /// <param name="duration"></param>
        public void ChangeColor(DelcomColor inputColor, bool steady, TimeSpan?duration)
        {
            lock (this)
            {
                changeColorRequestId++;

                if (inputColor == DelcomColor.Off)
                {
                    if (!DelcomLightWrapper.DelcomLEDAllAction(this.hUSB, DelcomLightWrapper.LightStates.Off) && Program.RunFromConsole)
                    {
                        Trace.TraceInformation(DateTime.Now + ": LED failure: all off");
                        Trace.Flush();
                    }
                }
                else
                {
                    // convert from the publicly exposed color to the internal value
                    DelcomLightWrapper.LightColors color = ConvertColor(inputColor);

                    DelcomLightWrapper.LightStates action = steady ? DelcomLightWrapper.LightStates.On
                                                                   : DelcomLightWrapper.LightStates.Flash;

                    if (!DelcomLightWrapper.DelcomLEDAllAction(this.hUSB, DelcomLightWrapper.LightStates.Off) && Program.RunFromConsole)
                    {
                        Trace.TraceInformation(DateTime.Now + ": LED failure: all off");
                        Trace.Flush();
                    }
                    if (!DelcomLightWrapper.DelcomLEDAction(this.hUSB, color, action) && Program.RunFromConsole)
                    {
                        Trace.TraceInformation(DateTime.Now + ": LED failure: " + Enum.GetName(typeof(DelcomLightWrapper.LightColors), color) +
                                               " " + Enum.GetName(typeof(DelcomLightWrapper.LightStates), action));
                        Trace.Flush();
                    }

                    // We need to only have the light on for the requested duration
                    if (duration != null)
                    {
                        // Create a callback that will safely turn the light off
                        TimerCallback callback = new TimerCallback(delegate(object state)
                        {
                            // Get the current button action (as of the callback)
                            int currentButtonAction = -1;
                            lock (this)
                            {
                                currentButtonAction = this.changeColorRequestId;
                            }

                            int rememberedButtonAction = (int)state;

                            // Compare the current buttonaction to the remembered action
                            if (currentButtonAction == rememberedButtonAction)
                            {
                                // Only turn the light off if they still match, otherwise we've moved on to a new action
                                if (!DelcomLightWrapper.DelcomLEDAllAction(this.hUSB, DelcomLightWrapper.LightStates.Off) && Program.RunFromConsole)
                                {
                                    Trace.TraceInformation(DateTime.Now + ": LED failure: all off");
                                    Trace.Flush();
                                }
                            }
                            else
                            {
                                // Another request has come in while waiting for the timer to fire, ignore the delayed request to turn the light off
                            }
                        });

                        // Make a timer
                        Timer ledTimer = new Timer(
                            callback,
                            changeColorRequestId,
                            duration.Value,
                            TimeSpan.Zero);
                    }
                }
            }
        }
 /// <summary>
 ///     Change the color of the light
 /// </summary>
 /// <param name="inputColor"></param>
 public void ChangeColor(DelcomColor inputColor)
 {
     ChangeColor(inputColor, steady: true, duration: null);
 }