public override void Start()
        {
            hours.AddRange("5:00 pm", "11:00 pm");

            bool.TryParse(Exec.GetKey("InflatablesRunning", false.ToString()), out inflatablesRunning);

            buttonOverrideHours.ActiveChanged += (i, e) =>
            {
                if (e.NewState)
                {
                    hours.SetForced(true);
                }
                else
                {
                    hours.SetForced(null);
                }
            };

            candyCane
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                const int spacing = 4;

                while (true)
                {
                    for (int i = 0; i < spacing; i++)
                    {
                        allPixels.Inject((i % spacing) == 0 ? Color.Red : Color.White, 0.5);

                        instance.WaitFor(S(0.2), true);
                    }
                }
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();
            });

            twinkleSeq
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                var rnd = new Random();

                while (!instance.IsCancellationRequested)
                {
                    allPixels.SetAll(Color.White, 0.5);
                    instance.WaitFor(S(1.0), true);

                    int pixel1 = rnd.Next(allPixels.Pixels);
                    int pixel2 = rnd.Next(allPixels.Pixels);
                    var task1  = allPixels.FadeToAsync(instance, pixel1, Color.Red, 1.0, S(2.0));
                    var task2  = allPixels.FadeToAsync(instance, pixel2, Color.Red, 1.0, S(2.0));
                    Task.WaitAll(task1, task2);

                    instance.WaitFor(S(1.0), true);

                    task1 = allPixels.FadeToAsync(instance, pixel1, Color.White, 0.5, S(1.0));
                    task2 = allPixels.FadeToAsync(instance, pixel2, Color.White, 0.5, S(1.0));
                    Task.WaitAll(task1, task2);
                }
            })
            .TearDown(() => allPixels.TurnOff());

            backgroundLoop
            .WhenExecuted
            .SetUp(() =>
            {
                pulsatingEffect1.Start();
                flickerEffect.Start();
                switchButtonBlue.SetPower(true);
                switchButtonRed.SetPower(true);
                lightTreeUp.SetOnlyColor(Color.Red);

                faderIn.Restart();

                Executor.Current.Execute(twinkleSeq);
            })
            .TearDown(() =>
            {
                Executor.Current.Cancel(twinkleSeq);

                switchButtonBlue.SetPower(false);
                switchButtonRed.SetPower(false);
                EverythingOff();
            });

            offHours1Seq
            .WhenExecuted
            .Execute(instance =>
            {
                audioPlayer.PlayEffect("force1");
                instance.WaitFor(S(4));
            });

            offHours2Seq
            .WhenExecuted
            .Execute(instance =>
            {
                audioPlayer.PlayEffect("darkside");
                instance.WaitFor(S(4));
            });

            music1Seq
            .WhenExecuted
            .SetUp(() =>
            {
                audioPlayer.CueTrack("21. Christmas Canon Rock");
                // Make sure it's ready
                System.Threading.Thread.Sleep(800);

                EverythingOff();
            })
            .Execute(instance =>
            {
                audioPlayer.ResumeTrack();
                var task = timeline1.Start();

                try
                {
                    task.Wait(instance.CancelToken);

                    instance.WaitFor(S(10));
                }
                finally
                {
                    timeline1.Stop();
                    audioPlayer.PauseTrack();
                }

                if (!instance.IsCancellationRequested)
                {
                    instance.WaitFor(S(2));
                }
                EverythingOff();

                instance.WaitFor(S(2));
            })
            .TearDown(() =>
            {
                EverythingOff();
            });

            starwarsCane
            .WhenExecuted
            .SetUp(() =>
            {
                allPixels.TurnOff();
                starwarsPixels.TurnOff();
            })
            .Execute(instance =>
            {
                const int spacing = 4;

                while (!instance.CancelToken.IsCancellationRequested)
                {
                    for (int i = 0; i < spacing; i++)
                    {
                        switch (i % spacing)
                        {
                        case 0:
                        case 1:
                            starwarsPixels.InjectRev(Color.Yellow, 1.0);
                            break;

                        case 2:
                        case 3:
                            starwarsPixels.InjectRev(Color.Orange, 0.2);
                            break;
                        }

                        instance.WaitFor(S(0.1));

                        if (instance.IsCancellationRequested)
                        {
                            break;
                        }
                    }
                }
            })
            .TearDown(() => starwarsPixels.TurnOff());

            fatherSeq
            .WhenExecuted
            .Execute(instance =>
            {
                EverythingOff();

                Executor.Current.Execute(starwarsCane);

                audioPlayer.PlayTrack("01. Star Wars - Main Title");

                //lightCeiling1.SetOnlyColor(Color.Yellow);
                //lightCeiling2.SetOnlyColor(Color.Yellow);
                //lightCeiling3.SetOnlyColor(Color.Yellow);
                //pulsatingEffect2.Start();
                instance.WaitFor(S(16));
                //pulsatingEffect2.Stop();
                audioPlayer.PauseTrack();
                Executor.Current.Cancel(starwarsCane);
                allPixels.TurnOff();
                instance.WaitFor(S(0.5));

                elJesus.SetPower(true);
                pulsatingStar.Start();
                lightJesus.SetColor(Color.White, 0.3);
                light3wise.SetOnlyColor(Color.LightYellow);
                light3wise.RunEffect(new Effect2.Fader(0.0, 1.0), S(1.0));
                lightVader.SetOnlyColor(Color.LightYellow);
                lightVader.RunEffect(new Effect2.Fader(0.0, 1.0), S(1.0));

                instance.WaitFor(S(2.5));

                //elLightsaber.SetPower(true);
                audioPlayer.PlayEffect("saberon");
                for (int sab = 0; sab < 60; sab++)
                {
                    saberPixels.Inject(Color.Red, 0.5);
                    instance.WaitFor(S(0.01));
                }

//                    lightVader.SetColor(Color.Red, 1.0);
                audioPlayer.PlayEffect("father");
                instance.WaitFor(S(4));

                lightVader.TurnOff();
                light3wise.TurnOff();
                lightJesus.TurnOff();
                pulsatingStar.Stop();
                elJesus.TurnOff();

                audioPlayer.PlayEffect("force1");
                instance.WaitFor(S(4));

                lightVader.TurnOff();
                audioPlayer.PlayEffect("saberoff");
                instance.WaitFor(S(0.7));
                for (int sab = 0; sab < 30; sab++)
                {
                    saberPixels.InjectRev(Color.Black, 0);
                    saberPixels.InjectRev(Color.Black, 0);
                    instance.WaitFor(S(0.01));
                }
                //elLightsaber.SetPower(false);
                instance.WaitFor(S(2));

                //lightJesus.TurnOff();
                //light3wise.TurnOff();
                //elLightsaber.TurnOff();
                //pulsatingStar.Stop();
                //elJesus.TurnOff();
                //instance.WaitFor(S(2));
            })
            .TearDown(() => {
                EverythingOff();
            });


            waveformSeq
            .WhenExecuted
            .SetUp(() =>
            {
                audioPlayer.CueTrack("05. Frozen - Let It Go");
                // Make sure it's ready
                System.Threading.Thread.Sleep(800);

                EverythingOff();
            })
            .Execute(i =>
            {
                var timer = new Controller.HighPrecisionTimer(50, false);
                byte[] buffer;
                using (var fs = System.IO.File.OpenRead("Let It Go - Waveform 50ms.dat"))
                {
                    buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, buffer.Length);
                    fs.Close();
                }

                var cb = new ColorBrightness[allPixels.Pixels];
                for (int cb_pos = 0; cb_pos < cb.Length; cb_pos++)
                {
                    cb[cb_pos] = new ColorBrightness(Color.Turquoise, 0.0);
                }

                double lastValue = 0;

                timer.Tick += (o, e) =>
                {
                    int pos = (int)e.TotalTicks;
                    if (pos >= buffer.Length)
                    {
                        e.Cancel = true;
                        return;
                    }

                    double curValue = buffer[pos].GetDouble();
                    if (curValue > lastValue)
                    {
                        lastValue = curValue;
                    }
                    double value = lastValue;
                    lastValue    = (lastValue - 0.02).Limit(0.0, 1.0);

                    const double d1             = 0.00;
                    const double d2             = 0.15;
                    const double d3             = 0.20;
                    const double d4             = 0.25;
                    lightHat1.Brightness        = value.LimitAndScale(d1, 0.2);
                    lightHat2.Brightness        = value.LimitAndScale(d1, 0.2);
                    lightHat3.Brightness        = value.LimitAndScale(d2, 0.2);
                    lightHat4.Brightness        = value.LimitAndScale(d2, 0.2);
                    lightTreeUp.Brightness      = value.LimitAndScale(d3, 0.2);
                    lightGarland1.Brightness    = value.LimitAndScale(d3, 0.2);
                    lightGarland2.Brightness    = value.LimitAndScale(d3, 0.2);
                    lightGarland3.Brightness    = value.LimitAndScale(d3, 0.2);
                    lightGarland4.Brightness    = value.LimitAndScale(d3, 0.2);
                    lightNet1.Brightness        = value.LimitAndScale(d2, 0.2);
                    lightNet2.Brightness        = value.LimitAndScale(d2, 0.2);
                    lightSnow1.Brightness       = value.LimitAndScale(d3, 0.2);
                    lightSnow2.Brightness       = value.LimitAndScale(d3, 0.2);
                    lightStairs1.Brightness     = value.LimitAndScale(d1, 0.2);
                    lightStairs2.Brightness     = value.LimitAndScale(d1, 0.2);
                    lightDeerSmall.Brightness   = curValue;
                    lightTopperLarge.Brightness = curValue;
                    lightDeerLarge.Brightness   = curValue;
                    lightTopperSmall.Brightness = curValue;
                    lightString1.Brightness     = value.LimitAndScale(d4, 0.2);
                    lightString2.Brightness     = value.LimitAndScale(d4, 0.2);
                    lightXmasTree.Brightness    = value.LimitAndScale(d4, 0.2);
                    lightStar.Brightness        = value.LimitAndScale(d4, 0.2);

                    int vuPos = (int)(cb.Length * value);
                    for (int cb_pos = 0; cb_pos < cb.Length; cb_pos++)
                    {
                        cb[cb_pos].Brightness = cb_pos < vuPos ? 1.0 : 0.2;
                    }

                    allPixels.SetColors(0, cb);
                };

                timer.Start();
                audioPlayer.ResumeTrack();

                timer.WaitUntilFinished(i);
            })
            .TearDown(() =>
            {
                EverythingOff();
            });

            buttonStartInflatables.ActiveChanged += (o, e) =>
            {
                if (e.NewState && hours.IsOpen)
                {
                    InflatablesRunning = true;

                    switchDeerHuge.SetPower(true);
                    switchSanta.SetPower(true);
                }
            };

            this.oscServer.RegisterAction <int>("/osc/button1", (msg, data) =>
            {
                if (data.Any() && data.First() == 1)
                {
                    stateMachine.SetState(States.Vader);
                }
            });

            this.oscServer.RegisterAction <int>("/osc/button2", (msg, data) =>
            {
                if (data.Any() && data.First() == 1)
                {
                    stateMachine.SetState(States.Music1);
                }
            });

            this.oscServer.RegisterAction <int>("/osc/button3", (msg, data) =>
            {
                if (data.Any() && data.First() == 1)
                {
                    stateMachine.SetState(States.Music2);
                }
            });

            this.oscServer.RegisterAction <int>("/osc/button4", (msg, data) =>
            {
                if (data.Any() && data.First() == 1)
                {
                    stateMachine.SetState(States.Background);
                }
            });

            this.oscServer.RegisterAction <int>("/osc/button5", (msg, data) =>
            {
                if (data.Any() && data.First() == 1)
                {
                    audioPlayer.PlayEffect("darkside");
                }
            });

            this.oscServer.RegisterAction <int>("/osc/button6", (msg, data) =>
            {
                if (data.Any() && data.First() == 1)
                {
                    audioPlayer.PlayEffect("Darth Breathing");
                }
            });

            // Test Button
            buttonTest.ActiveChanged += (sender, e) =>
            {
                //                lightGarland4.Brightness = e.NewState ? 1.0 : 0.0;

                if (e.NewState)
                {
                    Exec.Execute(waveformSeq);
                }
                else
                {
                    Exec.Cancel(waveformSeq);
                }

                if (!e.NewState)
                {
                    return;
                }


                //Exec.Cancel(candyCane);

                //allPixels.RunEffect(new Effect2.Fader(1.0, 0.0), S(2.0)).Wait();
                //allPixels.SetAllOnlyColor(Color.Purple);
                //allPixels.RunEffect(new Effect2.Fader(0.0, 1.0), S(2.0)).Wait();
                //allPixels.RunEffect(new Effect2.Fader(1.0, 0.0), S(2.0)).Wait();

                //allPixels.SetAllOnlyColor(Color.Orange);
                //allPixels.RunEffect(new Effect2.Fader(0.0, 1.0), S(2.0)).Wait();

                //allPixels.RunEffect(new Effect2.Fader(1.0, 0.0), S(2.0)).Wait();

                //Exec.Execute(candyCane);
            };

            buttonBlue.ActiveChanged += (o, e) =>
            {
                if (!e.NewState)
                {
                    return;
                }

                if (mute.HasValue && (DateTime.Now - mute.Value).TotalSeconds < 30)
                {
                    return;
                }

                if (hours.IsOpen)
                {
                    if (stateMachine.CurrentState == States.Music1 ||
                        stateMachine.CurrentState == States.Music2)
                    {
                        // Stop
                        //stateMachine.SetState(States.Background);
                        return;
                    }

                    switch (this.whichMusic++ % 2)
                    {
                    case 0:
                        stateMachine.SetState(States.Music1);
                        break;

                    case 1:
                        stateMachine.SetState(States.Music2);
                        break;
                    }
                }
                else
                {
                    Exec.Execute(offHours1Seq);
                }

                mute = DateTime.Now;
            };

            buttonRed.ActiveChanged += (o, e) =>
            {
                if (!e.NewState)
                {
                    return;
                }

                if (mute.HasValue && (DateTime.Now - mute.Value).TotalSeconds < 30)
                {
                    return;
                }

                if (hours.IsOpen)
                {
                    if (stateMachine.CurrentState == States.Vader)
                    {
                        return;
                    }
                    //stateMachine.SetState(States.Background);
                    else
                    {
                        stateMachine.SetState(States.Vader);
                    }
                }
                else
                {
                    Exec.Execute(offHours2Seq);
                }

                mute = DateTime.Now;
            };

            audioPlayer.AudioTrackDone += (o, e) =>
            {
                //                switchButtonBlue.SetPower(false);
            };

            pulsatingEffect1
            .AddDevice(lightStar);

            pulsatingStar
            .AddDevice(lightStar);

            flickerEffect
            .AddDevice(lightHat1)
            .AddDevice(lightHat2)
            .AddDevice(lightHat3)
            .AddDevice(lightHat4);

            hours.OpenHoursChanged += (i, e) =>
            {
                if (e.IsOpenNow)
                {
                    stateMachine.SetBackgroundState(States.Background);
                    stateMachine.SetState(States.Background);
                    //lightTreeUp.SetColor(Color.Red, 1.0);
                    //lightSnow1.SetBrightness(1.0);
                    //lightSnow2.SetBrightness(1.0);

                    if (InflatablesRunning)
                    {
                        switchDeerHuge.SetPower(true);
                        switchSanta.SetPower(true);
                    }
                }
                else
                {
                    if (buttonOverrideHours.Active)
                    {
                        return;
                    }

                    stateMachine.Hold();
                    stateMachine.SetBackgroundState(null);
                    EverythingOff();
                    System.Threading.Thread.Sleep(200);

                    switchDeerHuge.TurnOff();
                    switchSanta.TurnOff();
                    InflatablesRunning = false;
                }
            };

            faderIn
            .AddDevice(lightGarland1)
            .AddDevice(lightGarland2)
            .AddDevice(lightGarland3)
            .AddDevice(lightGarland4)
            .AddDevice(lightStairs1)
            .AddDevice(lightStairs2)
            .AddDevice(lightXmasTree)
            .AddDevice(lightDeerSmall)
            .AddDevice(lightDeerLarge)
            .AddDevice(lightTopperLarge)
            .AddDevice(lightTopperSmall)
            .AddDevice(lightNet1)
            .AddDevice(lightNet2)
            .AddDevice(lightString1)
            .AddDevice(lightString2)
            .AddDevice(lightSnow1)
            .AddDevice(lightSnow2)
            .AddDevice(lightTreeUp);

            stateMachine.ForFromSequence(States.Background, backgroundLoop);
            stateMachine.ForFromSequence(States.Music1, music1Seq);
            stateMachine.ForFromSequence(States.Music2, waveformSeq);
            stateMachine.ForFromSequence(States.Vader, fatherSeq);

            hatLightState.For(0).Execute(i => lightHat1.RunEffect(new Effect2.Fader(1.0, 0.0), S(0.5)));
            hatLightState.For(1).Execute(i => lightHat2.RunEffect(new Effect2.Fader(1.0, 0.0), S(0.5)));
            hatLightState.For(2).Execute(i => lightHat3.RunEffect(new Effect2.Fader(1.0, 0.0), S(0.5)));
            hatLightState.For(3).Execute(i => lightHat4.RunEffect(new Effect2.Fader(1.0, 0.0), S(0.5)));
            hatLightState.For(4).Execute(i => lightHat3.RunEffect(new Effect2.Fader(1.0, 0.0), S(0.5)));
            hatLightState.For(5).Execute(i => lightHat2.RunEffect(new Effect2.Fader(1.0, 0.0), S(0.5)));

            //lightGarland1.Follow(hours);
            //lightGarland2.Follow(hours);
            //lightGarland3.Follow(hours);
            //lightGarland4.Follow(hours);
            //lightGarland5.Follow(hours);
            //lightXmasTree.Follow(hours);
            //lightStairs1.Follow(hours);
            //lightDeerSmall.Follow(hours);
            //lightDeerLarge.Follow(hours);
            //lightTopperLarge.Follow(hours);
            //lightTopperSmall.Follow(hours);
            //lightNet1.Follow(hours);
            //lightNet2.Follow(hours);
            //lightString1.Follow(hours);
            //lightString2.Follow(hours);

            //light3wise.Follow(hours);
            //lightVader.Follow(hours);
            //switchButtonBlue.Follow(hours);
            //switchButtonRed.Follow(hours);

            ConfigureMusic1();
        }
        public override void Start()
        {
            candyCane
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                var cbList = new List <ColorBrightness>();
                //cbList.Add(new ColorBrightness(Color.Green, 1.00));
                //cbList.Add(new ColorBrightness(Color.Green, 0.70));
                //cbList.Add(new ColorBrightness(Color.Green, 0.40));
                //cbList.Add(new ColorBrightness(Color.White, 1.00));
                //cbList.Add(new ColorBrightness(Color.White, 0.70));
                //cbList.Add(new ColorBrightness(Color.White, 0.40));
                //cbList.Add(new ColorBrightness(Color.Red, 1.00));
                //cbList.Add(new ColorBrightness(Color.Red, 0.70));
                //cbList.Add(new ColorBrightness(Color.Red, 0.40));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));

                double b1 = 1.00;
                double b2 = 0.70;
                double b3 = 0.40;
                Color c1  = Color.Blue;
                Color c2  = Color.Yellow;
                Color c3  = Color.Blue;
                Color c4  = Color.Black;

                cbList.Add(new ColorBrightness(c1, b1));
                cbList.Add(new ColorBrightness(c1, b2));
                cbList.Add(new ColorBrightness(c1, b3));
                cbList.Add(new ColorBrightness(c2, b1));
                cbList.Add(new ColorBrightness(c2, b2));
                cbList.Add(new ColorBrightness(c2, b3));
                cbList.Add(new ColorBrightness(c3, b1));
                cbList.Add(new ColorBrightness(c3, b2));
                cbList.Add(new ColorBrightness(c3, b3));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));

/*                    b1 = 1.00;
 *                  b2 = 0.70;
 *                  b3 = 0.40;
 *                  c1 = Color.White;
 *                  c2 = Color.Blue;
 *                  c3 = Color.Red;
 *                  c4 = Color.Black;
 *
 *                  cbList.Add(new ColorBrightness(c1, b1));
 *                  cbList.Add(new ColorBrightness(c1, b2));
 *                  cbList.Add(new ColorBrightness(c1, b3));
 *                  cbList.Add(new ColorBrightness(c2, b1));
 *                  cbList.Add(new ColorBrightness(c2, b2));
 *                  cbList.Add(new ColorBrightness(c2, b3));
 *                  cbList.Add(new ColorBrightness(c3, b1));
 *                  cbList.Add(new ColorBrightness(c3, b2));
 *                  cbList.Add(new ColorBrightness(c3, b3));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *
 *                  b1 = 1.00;
 *                  b2 = 0.70;
 *                  b3 = 0.40;
 *                  c1 = Color.Red;
 *                  c2 = Color.White;
 *                  c3 = Color.Blue;
 *                  c4 = Color.Black;
 *
 *                  cbList.Add(new ColorBrightness(c1, b1));
 *                  cbList.Add(new ColorBrightness(c1, b2));
 *                  cbList.Add(new ColorBrightness(c1, b3));
 *                  cbList.Add(new ColorBrightness(c2, b1));
 *                  cbList.Add(new ColorBrightness(c2, b2));
 *                  cbList.Add(new ColorBrightness(c2, b3));
 *                  cbList.Add(new ColorBrightness(c3, b1));
 *                  cbList.Add(new ColorBrightness(c3, b2));
 *                  cbList.Add(new ColorBrightness(c3, b3));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 *                  cbList.Add(new ColorBrightness(c4, 0.0));
 */
                while (true)
                {
                    foreach (var cb in cbList)
                    {
                        allPixels.Inject(cb);
                        instance.WaitFor(S(0.350), true);
                    }
                }
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();
            });
        }
        private void ConfigureMusic1()
        {
            popOut1Piano     = new Effect.PopOut(S(0.4));
            popOut1Drums     = new Effect.PopOut(S(0.4));
            popOut1DrumsFast = new Effect.PopOut(S(0.3));
            popOut1Chord     = new Effect.PopOut(S(0.4));
            popOut1Solo      = new Effect.PopOut(S(0.3));
            popOut1Solo2     = new Effect.PopOut(S(0.2));
            popOut1Choir     = new Effect.PopOut(S(1.0));
            popOut1Voice     = new Effect.PopOut(S(1.0));
            popOut1Vocal2    = new Effect.PopOut(S(2.0));
            popOut1VocalLong = new Effect.PopOut(S(5.0));
            popOut1End       = new Effect.PopOut(S(5.0));

            popOut1Piano
            .AddDevice(lightString1)
            .AddDevice(lightString2)
            .AddDevice(lightTreeUp)
            .AddDevice(lightStar);

            popOut1Drums
            .AddDevice(lightDeerLarge);

            popOut1DrumsFast
            .AddDevice(lightDeerSmall)
            .AddDevice(lightGarland1)
            .AddDevice(lightGarland2)
            .AddDevice(lightGarland3)
            .AddDevice(lightGarland4)
            .AddDevice(allPixels);

            popOut1Chord
            .AddDevice(lightTopperSmall)
            .AddDevice(lightTopperLarge);
            //.AddDevice(lightTree)
            //.AddDevice(lightCeiling2)
            //.AddDevice(lightCeiling3);

            popOut1Solo
            .AddDevice(lightNet1)
            .AddDevice(lightNet2)
            //.AddDevice(lightCeiling1)
            //.AddDevice(lightCeiling3)
            .SetPriority(2);

            popOut1Solo2
            .AddDevice(lightTreeUp)
            //.AddDevice(lightCeiling1)
            //.AddDevice(lightCeiling3)
            .SetPriority(2);

            popOut1Choir
            .AddDevice(lightGarland1)
            .AddDevice(lightSnow1)
            .AddDevice(lightTopperLarge)
            .AddDevice(lightTopperSmall);
            //.AddDevice(lightCeiling1);

            popOut1Voice
            .AddDevice(lightGarland1)
            .AddDevice(lightGarland2)
            .AddDevice(lightSnow2);
            //.AddDevice(lightCeiling3);

            popOut1Vocal2
            //.AddDevice(lightReindeers)
            .AddDevice(allPixels)
            .SetPriority(10);

            popOut1VocalLong
            .AddDevice(lightSnow1)
            .AddDevice(lightSnow2)
            .AddDevice(lightGarland1)
            .AddDevice(lightGarland2)
            .AddDevice(lightGarland3)
            .AddDevice(lightGarland4)
            //.AddDevice(lightNetRight)
            //.AddDevice(lightGarlandRight)
            //.AddDevice(lightHatsRight)
            .SetPriority(10);

            popOut1End
            .AddDevice(lightStar)
            .AddDevice(lightHat1)
            .AddDevice(lightHat2)
            .AddDevice(lightHat3)
            .AddDevice(lightHat4)
            .AddDevice(lightSnow1)
            .AddDevice(lightSnow2)
            .AddDevice(lightStairs1)
            .AddDevice(lightStairs2)
            .AddDevice(lightGarland1)
            .AddDevice(lightGarland2)
            .AddDevice(lightGarland3)
            .AddDevice(lightGarland4)
            .AddDevice(lightString1)
            .AddDevice(lightString2)
            .AddDevice(lightXmasTree)
            .AddDevice(lightDeerLarge)
            .AddDevice(lightDeerSmall)
            .AddDevice(lightTreeUp)
            .AddDevice(lightTopperSmall)
            .AddDevice(lightTopperLarge)
            .AddDevice(lightNet1)
            .AddDevice(lightNet2)
            .AddDevice(allPixels)
            .SetPriority(100);

            timeline1.AddMs(0, "INIT");
            timeline1.PopulateFromCSV("Christmas Canon Rock All Labels.csv");
            int state    = 0;
            int halfSolo = 0;

            timeline1.TimelineTrigger += (sender, e) =>
            {
                switch (e.Step)
                {
                case 62:
                    // First drum
                    state = 1;
                    allPixels.TurnOff();
                    break;

                case 69:
                    state = 2;
                    //lightCeiling2.SetOnlyColor(Color.Green);
                    //lightCeiling3.SetOnlyColor(Color.Blue);
                    break;

                case 136:
                    // First solo
                    state = 3;
                    allPixels.TurnOff();
                    //lightCeiling2.SetOnlyColor(Color.White);
                    //lightCeiling3.SetOnlyColor(Color.Red);
                    break;

                case 265:
                    // First choir
                    allPixels.TurnOff();
                    state = 4;
                    break;

                case 396:
                    // Vocal 2
                    state = 5;
                    allPixels.SetAllOnlyColor(Color.Blue);
                    break;

                case 497:
                    // Second solo
                    state = 6;
                    allPixels.TurnOff();
                    //lightCeiling2.SetOnlyColor(Color.White);
                    //lightCeiling3.SetOnlyColor(Color.Red);
                    break;

                case 561:
                    // End second solo
                    state = 7;
                    allPixels.TurnOff();
                    break;

                case 585:
                    // End third solo
                    state = 8;
                    allPixels.TurnOff();
                    break;

                case 721:
                    // End third solo
                    state = 9;
                    allPixels.TurnOff();
                    break;
                }

                switch (e.Code)
                {
                case "INIT":
                    state    = 0;
                    halfSolo = 0;
                    //lightCeiling1.SetColor(Color.White, 0);
                    //lightCeiling2.SetColor(Color.Blue, 0);
                    //lightCeiling3.SetColor(Color.Red, 0);
                    break;

                case "N1":
                    hatLightState.NextState();
                    popOut1Piano.Pop(0.4);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.Red, 0.5);
                    }
                    break;

                case "N2":
                    hatLightState.NextState();
                    popOut1Piano.Pop(0.6);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.White, 0.5);
                    }
                    break;

                case "N3":
                    hatLightState.NextState();
                    popOut1Piano.Pop(0.8);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.Blue, 0.5);
                    }
                    break;

                case "N4":
                    hatLightState.NextState();
                    popOut1Piano.Pop(1.0);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.Black, 0.0);
                    }
                    break;

                case "Base":
                    popOut1Drums.Pop(1.0);
                    if (state < 3)
                    {
                        allPixels.SetAllOnlyColor(Color.Purple);
                        popOut1DrumsFast.Pop(1.0);
                    }
                    break;

                case "Cymbal":
                    popOut1Drums.Pop(1.0);
                    if (state < 3)
                    {
                        allPixels.SetAllOnlyColor(Color.Green);
                        popOut1DrumsFast.Pop(1.0);
                    }
                    break;

                case "Chord":
                    popOut1Chord.Pop(1.0);
                    break;

                case "Solo":
                    popOut1Solo.Pop(1.0);
                    if ((halfSolo++ % 2) == 0)
                    {
                        popOut1Solo2.Pop(0.8);
                    }
                    if (state == 3 || state == 6 || state == 8)
                    {
                        Color pixCol = Color.Black;
                        switch (e.Step % 4)
                        {
                        case 0:
                            pixCol = Color.Red;
                            break;

                        case 1:
                            pixCol = Color.Yellow;
                            break;

                        case 2:
                            pixCol = Color.Blue;
                            break;

                        case 3:
                            pixCol = Color.Pink;
                            break;
                        }
                        allPixels.Inject(pixCol, 1.0);
                    }
                    break;

                case "Choir":
                    popOut1Choir.Pop(1.0);
                    break;

                case "Voice":
                    popOut1Voice.Pop(1.0);
                    break;

                case "Vocal2":
                    popOut1Vocal2.Pop(1.0);
                    break;

                case "Long":
                    popOut1VocalLong.Pop(1.0);
                    break;

                case "LongUp":
                    // TODO
                    break;

                case "Down":
                    // TODO
                    break;

                case "End":
                    AllLightsOff();
                    popOut1End.Pop(1.0);
                    break;

                default:
                    this.log.Information("Unhandled code: " + e.Code);
                    break;
                }
            };
        }
        public XmasScene2(IEnumerable <string> args, System.Collections.Specialized.NameValueCollection settings)
        {
            hours = new OperatingHours("Hours");
            if (!args.Contains("TEST"))
            {
                hours.AddRange("5:00 pm", "10:00 pm");
                hours.AddRange("5:00 am", "7:00 am");
            }

            lightNetRight     = new Dimmer("Net Right");
            lightGarlandRight = new Dimmer("Garland Right");
            lightHatsRight    = new Dimmer("Hats Right");
            lightTreesRight   = new Dimmer("Trees Right");
            lightReindeers    = new Dimmer("Reindeers");
            lightIcicles      = new Dimmer("Icicles");
            lightNetLeft      = new Dimmer("Net Left");
            lightTree         = new Dimmer("Tree");
            lightGarlandLeft  = new Dimmer("Garland Left");
            lightUnused1      = new Dimmer("Unused 1");
            lightUnused2      = new Dimmer("Unused 2");
            lightJesus        = new StrobeColorDimmer("Jesus");
            lightCeiling1     = new StrobeColorDimmer("Ceiling 1");
            lightCeiling2     = new StrobeColorDimmer("Ceiling 2");
            lightCeiling3     = new StrobeColorDimmer("Ceiling 3");
            lightVader        = new StrobeColorDimmer("Vader");
            buttonLightRed    = new Switch("Button Red");
            buttonLightBlue   = new Switch("Button Blue");
            elLightsaber      = new Switch("Lightsaber");
            elJesus           = new Switch("Jesus Halo");
            bigReindeer       = new Switch("Big Reindeer");

            buttonBlue          = new DigitalInput("Button Blue");
            buttonRed           = new DigitalInput("Button Red");
            buttonStartReindeer = new DigitalInput("Start Reindeer");

            timeline       = new Controller.Timeline <string>(1);
            stateMachine   = new Controller.EnumStateMachine <States>("Main");
            candyCane      = new Controller.Sequence("Candy Cane");
            starwarsCane   = new Controller.Sequence("Starwars Cane");
            backgroundLoop = new Controller.Sequence("Background");
            musicSeq       = new Controller.Sequence("Christmas Canon");
            buttonSeq      = new Controller.Sequence("Buttons");
            fatherSeq      = new Controller.Sequence("Father");
            breathSeq      = new Controller.Sequence("Breath");
            laserSeq       = new Controller.Sequence("Laser");

            allPixels = new VirtualPixel1D(100);

            pulsatingEffect1 = new Effect.Pulsating(S(2), 0.3, 1.0, false);
            pulsatingEffect2 = new Effect.Pulsating(S(2), 0.3, 1.0, false);

            popOutPiano     = new Effect.PopOut(S(0.4));
            popOutDrums     = new Effect.PopOut(S(0.4));
            popOutDrumsFast = new Effect.PopOut(S(0.3));
            popOutChord     = new Effect.PopOut(S(0.4));
            popOutSolo      = new Effect.PopOut(S(0.3));
            popOutSolo2     = new Effect.PopOut(S(0.2));
            popOutChoir     = new Effect.PopOut(S(1.0));
            popOutVoice     = new Effect.PopOut(S(1.0));
            popOutVocal2    = new Effect.PopOut(S(2.0));
            popOutVocalLong = new Effect.PopOut(S(5.0));
            popOutEnd       = new Effect.PopOut(S(5.0));

            popOutPiano
            .AddDevice(lightIcicles);

            popOutDrums
            .AddDevice(lightReindeers)
            .AddDevice(lightHatsRight);

            popOutDrumsFast
            .AddDevice(lightCeiling1)
            .AddDevice(allPixels);

            popOutChord
            .AddDevice(lightTree)
            .AddDevice(lightCeiling2)
            .AddDevice(lightCeiling3);

            popOutSolo
            .AddDevice(lightNetLeft)
            .AddDevice(lightNetRight)
            .AddDevice(lightCeiling1)
            .AddDevice(lightCeiling3)
            .SetPriority(2);

            popOutSolo2
            .AddDevice(lightCeiling1)
            .AddDevice(lightCeiling3)
            .SetPriority(2);

            popOutChoir
            .AddDevice(lightGarlandRight)
            .AddDevice(lightTreesRight)
            .AddDevice(lightCeiling1);

            popOutVoice
            .AddDevice(lightGarlandLeft)
            .AddDevice(lightCeiling3);

            popOutVocal2
            .AddDevice(lightReindeers)
            .AddDevice(allPixels)
            .SetPriority(10);

            popOutVocalLong
            .AddDevice(lightNetRight)
            .AddDevice(lightGarlandRight)
            .AddDevice(lightHatsRight)
            .SetPriority(10);

            popOutEnd
            .AddDevice(lightIcicles)
            .AddDevice(lightReindeers)
            .AddDevice(lightHatsRight)
            .AddDevice(lightCeiling1)
            .AddDevice(lightCeiling2)
            .AddDevice(lightCeiling3)
            .AddDevice(lightGarlandRight)
            .AddDevice(lightGarlandLeft)
            .AddDevice(lightTreesRight)
            .AddDevice(lightNetRight)
            .AddDevice(lightNetLeft)
            .AddDevice(allPixels)
            .SetPriority(100);


            timeline.AddMs(0, "INIT");
            timeline.PopulateFromCSV("Christmas Canon Rock All Labels.csv");
            int state    = 0;
            int halfSolo = 0;

            timeline.TimelineTrigger += (sender, e) =>
            {
                switch (e.Step)
                {
                case 62:
                    // First drum
                    state = 1;
                    allPixels.TurnOff();
                    break;

                case 69:
                    state = 2;
                    lightCeiling2.SetOnlyColor(Color.Green);
                    lightCeiling3.SetOnlyColor(Color.Blue);
                    break;

                case 136:
                    // First solo
                    state = 3;
                    allPixels.TurnOff();
                    lightCeiling2.SetOnlyColor(Color.White);
                    lightCeiling3.SetOnlyColor(Color.Red);
                    break;

                case 265:
                    // First choir
                    allPixels.TurnOff();
                    state = 4;
                    break;

                case 396:
                    // Vocal 2
                    state = 5;
                    allPixels.SetAllOnlyColor(Color.Blue);
                    break;

                case 497:
                    // Second solo
                    state = 6;
                    allPixels.TurnOff();
                    lightCeiling2.SetOnlyColor(Color.White);
                    lightCeiling3.SetOnlyColor(Color.Red);
                    break;

                case 561:
                    // End second solo
                    state = 7;
                    allPixels.TurnOff();
                    break;

                case 585:
                    // End third solo
                    state = 8;
                    allPixels.TurnOff();
                    break;

                case 721:
                    // End third solo
                    state = 9;
                    allPixels.TurnOff();
                    break;
                }

                switch (e.Code)
                {
                case "INIT":
                    state    = 0;
                    halfSolo = 0;
                    lightCeiling1.SetColor(Color.White, 0);
                    lightCeiling2.SetColor(Color.Blue, 0);
                    lightCeiling3.SetColor(Color.Red, 0);
                    break;

                case "N1":
                    popOutPiano.Pop(0.4);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.Red, 0.5);
                    }
                    break;

                case "N2":
                    popOutPiano.Pop(0.6);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.White, 0.5);
                    }
                    break;

                case "N3":
                    popOutPiano.Pop(0.8);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.Blue, 0.5);
                    }
                    break;

                case "N4":
                    popOutPiano.Pop(1.0);
                    if (state == 0)
                    {
                        allPixels.Inject(Color.Black, 0.0);
                    }
                    break;

                case "Base":
                    popOutDrums.Pop(1.0);
                    if (state < 3)
                    {
                        allPixels.SetAllOnlyColor(Color.Purple);
                        popOutDrumsFast.Pop(1.0);
                    }
                    break;

                case "Cymbal":
                    popOutDrums.Pop(1.0);
                    if (state < 3)
                    {
                        allPixels.SetAllOnlyColor(Color.Green);
                        popOutDrumsFast.Pop(1.0);
                    }
                    break;

                case "Chord":
                    popOutChord.Pop(1.0);
                    break;

                case "Solo":
                    popOutSolo.Pop(1.0);
                    if ((halfSolo++ % 2) == 0)
                    {
                        popOutSolo2.Pop(0.8);
                    }
                    if (state == 3 || state == 6 || state == 8)
                    {
                        Color pixCol = Color.Black;
                        switch (e.Step % 4)
                        {
                        case 0:
                            pixCol = Color.Red;
                            break;

                        case 1:
                            pixCol = Color.Yellow;
                            break;

                        case 2:
                            pixCol = Color.Blue;
                            break;

                        case 3:
                            pixCol = Color.Pink;
                            break;
                        }
                        allPixels.Inject(pixCol, 1.0);
                    }
                    break;

                case "Choir":
                    popOutChoir.Pop(1.0);
                    break;

                case "Voice":
                    popOutVoice.Pop(1.0);
                    break;

                case "Vocal2":
                    popOutVocal2.Pop(1.0);
                    break;

                case "Long":
                    popOutVocalLong.Pop(1.0);
                    break;

                case "LongUp":
                    // TODO
                    break;

                case "Down":
                    // TODO
                    break;

                case "End":
                    EverythingOff();
                    popOutEnd.Pop(1.0);
                    break;

                default:
                    this.log.Information("Unhandled code: " + e.Code);
                    break;
                }
            };

            audioPlayer = new Physical.NetworkAudioPlayer(
                settings["NetworkAudioPlayerIP"],
                int.Parse(settings["NetworkAudioPlayerPort"]));
        }
        public override void Start()
        {
            pulsatingEffect1.AddDevice(lightHatsRight);
            pulsatingEffect2
            .AddDevice(lightCeiling1)
            .AddDevice(lightCeiling2)
            .AddDevice(lightCeiling3);

            candyCane
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                const int spacing = 4;

                while (true)
                {
                    for (int i = 0; i < spacing; i++)
                    {
                        allPixels.Inject((i % spacing) == 0 ? Color.Red : Color.White, 1.0);

                        instance.WaitFor(S(0.2), true);
                    }
                }
            })
            .TearDown(() => allPixels.TurnOff());

            starwarsCane
            .WhenExecuted
            .Execute(instance =>
            {
                const int spacing = 4;

                allPixels.TurnOff();

                while (!instance.CancelToken.IsCancellationRequested)
                {
                    for (int i = 0; i < spacing; i++)
                    {
                        switch (i % spacing)
                        {
                        case 0:
                        case 1:
                            allPixels.InjectRev(Color.Yellow, 1.0);
                            break;

                        case 2:
                        case 3:
                            allPixels.InjectRev(Color.Orange, 0.2);
                            break;
                        }

                        instance.WaitFor(S(0.1));

                        if (instance.IsCancellationRequested)
                        {
                            break;
                        }
                    }
                }
                allPixels.TurnOff();
            });

            backgroundLoop
            .WhenExecuted
            .SetUp(() =>
            {
                pulsatingEffect1.Start();
                lightGarlandLeft.Brightness  = 1;
                lightGarlandRight.Brightness = 1;
                lightIcicles.Brightness      = 1;
                lightTreesRight.Brightness   = 1;
                lightHatsRight.Brightness    = 1;
                lightNetLeft.Brightness      = 0.5;
                lightNetRight.Brightness     = 0.5;
                lightReindeers.Brightness    = 1;
                lightTree.Brightness         = 1;
                lightCeiling1.SetColor(Color.Red, 0.5);
                lightCeiling2.SetColor(Color.Red, 0.5);
                lightCeiling3.SetColor(Color.Red, 0.5);

                Executor.Current.Execute(candyCane);
            })
            .TearDown(() =>
            {
                Executor.Current.Cancel(candyCane);

                EverythingOff();
            });


            musicSeq
            .Loop
            .WhenExecuted
            .SetUp(() =>
            {
                audioPlayer.CueTrack("21 Christmas Canon Rock");
                // Make sure it's ready
                System.Threading.Thread.Sleep(800);

                EverythingOff();
            })
            .Execute(instance =>
            {
                audioPlayer.PlayTrack();
                var task = timeline.Start();

                try
                {
                    task.Wait(instance.CancelToken);

                    instance.WaitFor(S(10));
                }
                finally
                {
                    timeline.Stop();
                    audioPlayer.PauseTrack();
                }

                if (!instance.IsCancellationRequested)
                {
                    instance.WaitFor(S(2));
                }
                EverythingOff();

                instance.WaitFor(S(2), true);


                Executor.Current.Execute(backgroundLoop);
                instance.WaitFor(S(30));
                Executor.Current.Cancel(backgroundLoop);
                EverythingOff();
                instance.WaitFor(S(1));
            })
            .TearDown(() =>
            {
                EverythingOff();
            });

            buttonSeq
            .Loop
            .WhenExecuted
            .Execute(instance =>
            {
                buttonLightBlue.SetPower(true);
                buttonLightRed.SetPower(false);
                instance.WaitFor(S(0.2));
                buttonLightBlue.SetPower(false);
                buttonLightRed.SetPower(true);
                instance.WaitFor(S(0.2));
            })
            .TearDown(() =>
            {
                buttonLightBlue.SetPower(false);
                buttonLightRed.SetPower(false);
            });

            fatherSeq
            .WhenExecuted
            .Execute(instance =>
            {
                Executor.Current.Execute(starwarsCane);

                EverythingOff();

                audioPlayer.CueTrack("01 Star Wars_ Main Title");
                // Make sure it's ready
                instance.WaitFor(S(0.5));
                audioPlayer.PlayTrack();

                lightCeiling1.SetOnlyColor(Color.Yellow);
                lightCeiling2.SetOnlyColor(Color.Yellow);
                lightCeiling3.SetOnlyColor(Color.Yellow);
                pulsatingEffect2.Start();
                instance.WaitFor(S(16));
                pulsatingEffect2.Stop();
                audioPlayer.PauseTrack();
                Executor.Current.Cancel(starwarsCane);
                allPixels.TurnOff();
                instance.WaitFor(S(0.5));

                elJesus.SetPower(true);
                lightJesus.SetColor(Color.White, 0.3);

                instance.WaitFor(S(1.5));

                elLightsaber.SetPower(true);
                audioPlayer.PlayEffect("saberon");
                instance.WaitFor(S(1));

                lightVader.SetColor(Color.Red, 1.0);
                audioPlayer.PlayEffect("father");
                instance.WaitFor(S(3));

                lightVader.TurnOff();
                audioPlayer.PlayEffect("saberoff");
                instance.WaitFor(S(0.5));
                elLightsaber.SetPower(false);
                instance.WaitFor(S(1));

                lightJesus.TurnOff();
                elLightsaber.TurnOff();
                elJesus.TurnOff();
            });

            breathSeq
            .WhenExecuted
            .Execute(instance =>
            {
                audioPlayer.PlayEffect("Darth Breathing");
                instance.WaitFor(S(4));
            });

            laserSeq
            .WhenExecuted
            .SetUp(() =>
            {
                allPixels.TurnOff();
            })
            .Execute(instance =>
            {
                audioPlayer.PlayEffect("lazer");

                var cb = new ColorBrightness[6];
                cb[0]  = new ColorBrightness(Color.Black, 1.0);
                cb[1]  = new ColorBrightness(Color.Red, 1.0);
                cb[2]  = new ColorBrightness(Color.Orange, 1.0);
                cb[3]  = new ColorBrightness(Color.Yellow, 1.0);
                cb[4]  = new ColorBrightness(Color.Blue, 1.0);
                cb[5]  = new ColorBrightness(Color.White, 1.0);

                for (int i = -6; i < allPixels.Pixels; i++)
                {
                    allPixels.SetColors(i, cb);
                    System.Threading.Thread.Sleep(25);
                }

                instance.WaitFor(S(1));
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();
            });

            stateMachine.ForFromSequence(States.Background, backgroundLoop);

            stateMachine.ForFromSequence(States.Music, musicSeq);

            stateMachine.ForFromSequence(States.Vader, fatherSeq);


            // Start Reindeer
            buttonStartReindeer.ActiveChanged += (sender, e) =>
            {
                if (!e.NewState)
                {
                    return;
                }

                if (hours.IsOpen)
                {
                    bigReindeer.SetPower(true);
                }
                else
                {
                    TestAllPixels(Color.Red, 1.0, S(1));
                    TestAllPixels(Color.Red, 0.5, S(1));

                    TestAllPixels(Color.Green, 1.0, S(1));
                    TestAllPixels(Color.Green, 0.5, S(1));

                    TestAllPixels(Color.Blue, 1.0, S(1));
                    TestAllPixels(Color.Blue, 0.5, S(1));

                    TestAllPixels(Color.Purple, 1.0, S(1));
                    TestAllPixels(Color.Purple, 0.5, S(1));

                    TestAllPixels(Color.White, 1.0, S(1));
                    TestAllPixels(Color.White, 0.5, S(1));

                    allPixels.TurnOff();
                }
            };

            // Red Button
            buttonRed.ActiveChanged += (sender, e) =>
            {
                if (!e.NewState)
                {
                    return;
                }

                if (hours.IsOpen)
                {
                    stateMachine.SetMomentaryState(States.Vader);
                }
                else
                {
                    Executor.Current.Execute(laserSeq);
                }
            };

            // Blue Button
            buttonBlue.ActiveChanged += (sender, e) =>
            {
                if (!e.NewState)
                {
                    return;
                }

                if (hours.IsOpen)
                {
                    if (stateMachine.CurrentState == States.Background)
                    {
                        stateMachine.SetMomentaryState(States.Music);
                    }
                }
                else
                {
                    Executor.Current.Execute(breathSeq);
                }
            };

            // Hours
            hours.OpenHoursChanged += (sender, e) =>
            {
                if (e.IsOpenNow)
                {
                    stateMachine.SetState(States.Background);

                    Executor.Current.Execute(buttonSeq);
                }
                else
                {
                    Executor.Current.Cancel(buttonSeq);

                    stateMachine.Hold();
                    bigReindeer.SetPower(false);
                }
            };
        }
        public override void Start()
        {
            hoursSmall.AddRange("5:00 pm", "9:00 pm");
            hoursFull.AddRange("5:00 pm", "9:00 pm");
            //hoursFull.SetForced(true);
            //hoursSmall.SetForced(true);
            //hoursFull.SetForced(false);
            //hoursSmall.SetForced(false);

#if !true
            hoursFull.SetForced(true);

            audioBeauty.SetSilent(true);
            audioCat.SetSilent(true);
            audioGeorge.SetSilent(true);
            audioSpider.SetSilent(true);
            georgeMotor.SetDisabled(true);
#endif
            var backgroundSeq = new Controller.Sequence("BG Sequence");
            backgroundSeq.WhenExecuted
            .SetUp(() =>
            {
                audioGeorge.PlayBackground();
                lightFloor.SetOnlyColor(Color.Orange);
                pulsatingEffect1.Start();
                flickerEffect.Start();
            })
            .Execute(instance =>
            {
                while (!instance.IsCancellationRequested)
                {
                    instance.WaitFor(S(1));
                    if (!this.lastFogRun.HasValue || (DateTime.Now - this.lastFogRun.Value).TotalMinutes > 10)
                    {
                        // Run the fog for a little while
                        switchFog.SetPower(true);
                        instance.WaitFor(S(4));
                        switchFog.SetPower(false);
                        this.lastFogRun = DateTime.Now;
                    }
                }
            })
            .TearDown(() =>
            {
                audioGeorge.PauseBackground();
                pulsatingEffect1.Stop();
                flickerEffect.Stop();
            });

            var deadendSeq = new Controller.Sequence("Deadend dr");
            deadendSeq.WhenExecuted
            .Execute(instance =>
            {
                switchDeadendDrive.SetPower(true);
                Thread.Sleep(1000);
                switchDeadendDrive.SetPower(false);
            });

            var stairSeq = new Controller.Sequence("Stair Sequence");
            stairSeq.WhenExecuted
            .SetUp(() =>
            {
            })
            .Execute(instance =>
            {
                switchFog.SetPower(true);
                this.lastFogRun = DateTime.Now;
                Executor.Current.Execute(deadendSeq);
                audioGeorge.PlayEffect("ghostly");
                instance.WaitFor(S(0.5));
                popOutEffect.Pop(1.0);

                instance.WaitFor(S(1.0));
                audioSpider.PlayNewEffect("348 Spider Hiss");
                switchSpider.SetPower(true);
                instance.WaitFor(S(0.5));
                switchSpiderEyes1.SetPower(true);
                instance.WaitFor(S(2));
                switchSpider.SetPower(false);
                switchSpiderEyes1.SetPower(false);
                instance.WaitFor(S(4));
                stateMachine.NextState();
            })
            .TearDown(() =>
            {
                switchFog.SetPower(false);
                audioGeorge.PauseFX();
            });

            var georgeReturnSeq = new Controller.Sequence("George Return Seq");
            georgeReturnSeq.WhenExecuted
            .Execute(instance =>
            {
                georgeMotor.WaitForVectorReached();
                georgeMotor.SetVector(0.9, 0, S(15));
                georgeMotor.WaitForVectorReached();
            });

            var georgeSeq = new Controller.Sequence("George Sequence");
            georgeSeq.WhenExecuted
            .Execute(instance =>
            {
                //Exec.WaitUntilFinished(georgeReturnSeq);

                audioGeorge.PlayEffect("laugh");
                georgeMotor.SetVector(1.0, 350, S(10));
                instance.WaitFor(TimeSpan.FromSeconds(0.8));
                lightGeorge.SetColor(Color.Red);
                georgeMotor.WaitForVectorReached(instance);
                instance.WaitFor(TimeSpan.FromSeconds(2));
                georgeMotor.SetVector(0.9, 0, S(15));
                lightGeorge.RunEffect(new Effect2.Fader(1.0, 0.0), S(1.0));
                instance.WaitFor(TimeSpan.FromSeconds(1));
                lightFloor.SetOnlyColor(Color.Green);
                pulsatingEffect1.Start();
                georgeMotor.WaitForVectorReached(instance);

                instance.WaitFor(S(15));
            })
            .TearDown(() =>
            {
                Exec.Execute(georgeReturnSeq);
                pulsatingEffect1.Stop();
                lightGeorge.TurnOff();
            });

            var spiderEyes2Seq = new Controller.Sequence("Spider Eyes 2");
            spiderEyes2Seq.WhenExecuted
            .Execute(instance =>
            {
                var rnd = new Random();
                while (!instance.IsCancellationRequested)
                {
                    switchSpiderEyes2.SetPower(true);
                    instance.WaitFor(S(1.0 + rnd.Next(10)));
                    switchSpiderEyes2.SetPower(false);
                    instance.WaitFor(S(1.0 + rnd.Next(2)));
                }
            });

            var popupSeq = new Controller.Sequence("Popup Sequence");
            popupSeq.WhenExecuted
            .Execute(instance =>
            {
                audioBeauty.PlayEffect("scream", 0.0, 1.0);
                switchPopEyes.SetPower(true);
                instance.WaitFor(TimeSpan.FromSeconds(1.0));
                lightPopup.SetBrightness(1.0);
                switchPopUp.SetPower(true);

                instance.WaitFor(S(3));

                lightPopup.RunEffect(new Effect2.Fader(1.0, 0.0), S(1.0));
                switchPopEyes.TurnOff();
                switchPopUp.TurnOff();
            });

            var beautySeq = new Controller.Sequence("Beauty Sequence");
            beautySeq.WhenExecuted
            .Execute(instance =>
            {
                flickerEffect2.Stop();
                lightBeauty.SetColor(Color.Purple);
                switchHand.SetPower(true);
                instance.WaitFor(TimeSpan.FromSeconds(1));
                audioBeauty.PlayEffect("gollum_precious1", 1.0, 0.0);
                instance.WaitFor(TimeSpan.FromSeconds(0.4));
                switchHead.SetPower(true);
                instance.WaitFor(TimeSpan.FromSeconds(6));
                switchHead.SetPower(false);
                switchHand.SetPower(false);

                instance.WaitFor(TimeSpan.FromSeconds(1.5));
                lightBeauty.TurnOff();
                instance.WaitFor(TimeSpan.FromSeconds(0.5));
                switchDrawer1.SetPower(true);
                switchHead.SetPower(true);
                instance.WaitFor(TimeSpan.FromSeconds(0.5));
                lightBeauty.SetColor(Color.Red, 1.0);
                audioBeauty.PlayEffect("my_pretty", 1.0, 0.0);
                instance.WaitFor(TimeSpan.FromSeconds(4));
                switchDrawer2.SetPower(true);
                instance.WaitFor(TimeSpan.FromSeconds(2));
                switchDrawer1.SetPower(false);
                instance.WaitFor(TimeSpan.FromSeconds(0.15));
                switchDrawer2.SetPower(false);
                instance.WaitFor(TimeSpan.FromSeconds(1));

                switchHead.SetPower(false);
                lightBeauty.RunEffect(new Effect2.Fader(1.0, 0.0), S(1.0));
                if (hoursSmall.IsOpen)
                {
                    flickerEffect2.Start();
                }
                instance.WaitFor(TimeSpan.FromSeconds(5));
            });


            var catSeq = new Controller.Sequence("Cat Sequence");
            catSeq.WhenExecuted
            .Execute(instance =>
            {
                var maxRuntime = System.Diagnostics.Stopwatch.StartNew();

                var random = new Random();

                catLights.SetPower(true);

                while (true)
                {
                    switch (random.Next(4))
                    {
                    case 0:
                        audioCat.PlayEffect("266 Monster Growl 7", 1.0, 1.0);
                        instance.WaitFor(TimeSpan.FromSeconds(2.0));
                        break;

                    case 1:
                        audioCat.PlayEffect("285 Monster Snarl 2", 1.0, 1.0);
                        instance.WaitFor(TimeSpan.FromSeconds(3.0));
                        break;

                    case 2:
                        audioCat.PlayEffect("286 Monster Snarl 3", 1.0, 1.0);
                        instance.WaitFor(TimeSpan.FromSeconds(2.5));
                        break;

                    case 3:
                        audioCat.PlayEffect("287 Monster Snarl 4", 1.0, 1.0);
                        instance.WaitFor(TimeSpan.FromSeconds(1.5));
                        break;

                    default:
                        instance.WaitFor(TimeSpan.FromSeconds(3.0));
                        break;
                    }

                    instance.CancelToken.ThrowIfCancellationRequested();

                    if (maxRuntime.Elapsed.TotalSeconds > 10)
                    {
                        break;
                    }
                }
            })
            .TearDown(() =>
            {
                catLights.TurnOff();
            });

            var candyCane = new Controller.Sequence("Candy Cane");
            candyCane
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                var cbList = new List <ColorBrightness>();
                //cbList.Add(new ColorBrightness(Color.Green, 1.00));
                //cbList.Add(new ColorBrightness(Color.Green, 0.70));
                //cbList.Add(new ColorBrightness(Color.Green, 0.40));
                //cbList.Add(new ColorBrightness(Color.White, 1.00));
                //cbList.Add(new ColorBrightness(Color.White, 0.70));
                //cbList.Add(new ColorBrightness(Color.White, 0.40));
                //cbList.Add(new ColorBrightness(Color.Red, 1.00));
                //cbList.Add(new ColorBrightness(Color.Red, 0.70));
                //cbList.Add(new ColorBrightness(Color.Red, 0.40));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));
                //cbList.Add(new ColorBrightness(Color.Black, 0.0));

                double b1 = 1.00;
                double b2 = 0.70;
                double b3 = 0.40;
                Color c1  = Color.Blue;
                Color c2  = Color.Yellow;
                Color c3  = Color.Blue;
                Color c4  = Color.Black;

                cbList.Add(new ColorBrightness(c1, b1));
                cbList.Add(new ColorBrightness(c1, b2));
                cbList.Add(new ColorBrightness(c1, b3));
                cbList.Add(new ColorBrightness(c2, b1));
                cbList.Add(new ColorBrightness(c2, b2));
                cbList.Add(new ColorBrightness(c2, b3));
                cbList.Add(new ColorBrightness(c3, b1));
                cbList.Add(new ColorBrightness(c3, b2));
                cbList.Add(new ColorBrightness(c3, b3));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));

                b1 = 1.00;
                b2 = 0.70;
                b3 = 0.40;
                c1 = Color.White;
                c2 = Color.Blue;
                c3 = Color.Red;
                c4 = Color.Black;

                cbList.Add(new ColorBrightness(c1, b1));
                cbList.Add(new ColorBrightness(c1, b2));
                cbList.Add(new ColorBrightness(c1, b3));
                cbList.Add(new ColorBrightness(c2, b1));
                cbList.Add(new ColorBrightness(c2, b2));
                cbList.Add(new ColorBrightness(c2, b3));
                cbList.Add(new ColorBrightness(c3, b1));
                cbList.Add(new ColorBrightness(c3, b2));
                cbList.Add(new ColorBrightness(c3, b3));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));

                b1 = 1.00;
                b2 = 0.70;
                b3 = 0.40;
                c1 = Color.Red;
                c2 = Color.White;
                c3 = Color.Blue;
                c4 = Color.Black;

                cbList.Add(new ColorBrightness(c1, b1));
                cbList.Add(new ColorBrightness(c1, b2));
                cbList.Add(new ColorBrightness(c1, b3));
                cbList.Add(new ColorBrightness(c2, b1));
                cbList.Add(new ColorBrightness(c2, b2));
                cbList.Add(new ColorBrightness(c2, b3));
                cbList.Add(new ColorBrightness(c3, b1));
                cbList.Add(new ColorBrightness(c3, b2));
                cbList.Add(new ColorBrightness(c3, b3));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));
                cbList.Add(new ColorBrightness(c4, 0.0));

                while (true)
                {
                    foreach (var cb in cbList)
                    {
                        allPixels.Inject(cb);
                        instance.WaitFor(S(0.350), true);
                    }
                }
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();
            });


            stateMachine.ForFromSequence(States.Background, backgroundSeq);
            stateMachine.ForFromSequence(States.Stair, stairSeq);
            stateMachine.ForFromSequence(States.George, georgeSeq);
            stateMachine.ForFromSequence(States.Popup, popupSeq);

            hoursSmall.OpenHoursChanged += (sender, e) =>
            {
                if (e.IsOpenNow)
                {
                    pulsatingEffect2.Start();
                    flickerEffect.Start();
                    flickerEffect2.Start();
                    catFan.SetPower(true);
                    lightEyes.SetPower(true);
                    lightTreeGhost.SetBrightness(1.0);
                    //                        Exec.Execute(candyCane);
                    allPixels.SetAll(Color.FromArgb(255, 115, 0), 0.5);
                }
                else
                {
                    pulsatingEffect2.Stop();
                    flickerEffect.Stop();
                    flickerEffect2.Stop();
                    catFan.SetPower(false);
                    lightEyes.SetPower(false);
                    lightTreeGhost.TurnOff();
                    allPixels.TurnOff();
                }
            };

            hoursFull.OpenHoursChanged += (sender, e) =>
            {
                if (e.IsOpenNow)
                {
                    Executor.Current.Execute(spiderEyes2Seq);
                    stateMachine.SetBackgroundState(States.Background);
                    stateMachine.SetState(States.Background);
                }
                else
                {
                    Executor.Current.Cancel(spiderEyes2Seq);
                    stateMachine.Hold();
                    stateMachine.SetBackgroundState(null);
                    audioGeorge.PauseBackground();
                }
            };

            buttonMotionCat.ActiveChanged += (sender, e) =>
            {
#if CHECK_SENSOR_ALIGNMENT
                catLights.SetPower(e.NewState);
#else
                if (e.NewState && hoursSmall.IsOpen)
                {
                    Executor.Current.Execute(catSeq);
                }
#endif
            };

            buttonMotionBeauty.ActiveChanged += (sender, e) =>
            {
                if (e.NewState && hoursFull.IsOpen)
                {
                    Executor.Current.Execute(beautySeq);
                }
            };

            buttonTriggerStairs.ActiveChanged += (sender, e) =>
            {
                if (!hoursSmall.IsOpen)
                {
                    lightFloor.SetColor(Color.Purple, e.NewState ? 0.6 : 0.0);
                }
                else
                {
                    if (e.NewState && hoursFull.IsOpen)
                    {
                        if (!stateMachine.CurrentState.HasValue || stateMachine.CurrentState == States.Background)
                        {
                            stateMachine.SetState(States.Stair);
                        }
                    }
                }
            };

            buttonTriggerPopup.ActiveChanged += (sender, e) =>
            {
                if (!hoursSmall.IsOpen)
                {
                    lightPopup.SetBrightness(e.NewState ? 0.5 : 0.0);
                }
                else
                {
                    if (e.NewState)
                    {
                        if (stateMachine.CurrentState == States.George)
                        {
                            stateMachine.SetState(States.Popup);
                        }
                    }
                }
            };

            flickerEffect.AddDevice(skullsLight);
            flickerEffect2.AddDevice(skullsLight2);
            lightFloor.SetColor(Color.Orange, 0);
            lightSign.SetColor(Color.Pink, 0);
            pulsatingEffect1.AddDevice(lightFloor);
            pulsatingEffect1.AddDevice(lightSpiderWeb);
            pulsatingEffect2.AddDevice(lightSign);

            popOutEffect.AddDevice(skullsLight);

            ForTest();
        }
        public override void Start()
        {
            testSeq
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                allPixels.SetAllOnlyColor(Color.Orange);
                allPixels.RunEffect(new Effect2.Pulse(0.0, 1.0), S(2.0))
                .SetIterations(2)
                .Wait();
                allPixels.StopEffect();
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();

                Exec.Execute(candyCane);
            });


            candyCane
            .WhenExecuted
            .SetUp(() => allPixels.TurnOff())
            .Execute(instance =>
            {
                const int spacing = 4;

                while (true)
                {
                    for (int i = 0; i < spacing; i++)
                    {
                        allPixels.Inject((i % spacing) == 0 ? Color.Red : Color.White, 0.5);

                        instance.WaitFor(S(0.30), true);
                    }
                }
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();
            });


            laserSeq
            .WhenExecuted
            .SetUp(() =>
            {
                allPixels.TurnOff();
            })
            .Execute(instance =>
            {
                var cb = new ColorBrightness[6];
                cb[0]  = new ColorBrightness(Color.Black, 1.0);
                cb[1]  = new ColorBrightness(Color.Red, 1.0);
                cb[2]  = new ColorBrightness(Color.Orange, 1.0);
                cb[3]  = new ColorBrightness(Color.Yellow, 1.0);
                cb[4]  = new ColorBrightness(Color.Blue, 1.0);
                cb[5]  = new ColorBrightness(Color.White, 1.0);

                for (int i = -6; i < allPixels.Pixels; i++)
                {
                    allPixels.SetColors(i, cb);
                    System.Threading.Thread.Sleep(25);
                }

                instance.WaitFor(S(1));
            })
            .TearDown(() =>
            {
                allPixels.TurnOff();

                Exec.Execute(candyCane);
            });


            // Test Button
            buttonTest.ActiveChanged += (sender, e) =>
            {
                if (!e.NewState)
                {
                    return;
                }

                Exec.Cancel(candyCane);

                allPixels.RunEffect(new Effect2.Fader(1.0, 0.0), S(2.0)).Wait();
                allPixels.SetAllOnlyColor(Color.Purple);
                allPixels.RunEffect(new Effect2.Fader(0.0, 1.0), S(2.0)).Wait();
                allPixels.RunEffect(new Effect2.Fader(1.0, 0.0), S(2.0)).Wait();

                allPixels.SetAllOnlyColor(Color.Orange);
                allPixels.RunEffect(new Effect2.Fader(0.0, 1.0), S(2.0)).Wait();

                allPixels.RunEffect(new Effect2.Fader(1.0, 0.0), S(2.0)).Wait();

                Exec.Execute(candyCane);
            };
        }