public SolutionFileView()
		{
			this.Colors = new Dictionary<SolutionFileTextFragment, Color>
			{
				{ SolutionFileTextFragment.Comment, Color.FromRGB(0, 0x80, 0) },
				{ SolutionFileTextFragment.Keyword, Color.Blue },

				{ SolutionFileTextFragment.None, Color.None},

				{ SolutionFileTextFragment.String, Color.FromRGB(0x80, 0, 0) },
				{ SolutionFileTextFragment.Type, Color.FromRGB(43, 145, 175) },

				{ SolutionFileTextFragment.XMLKeyword, Color.FromRGB(0, 0, 0xff) },
				{ SolutionFileTextFragment.XMLElement, Color.FromRGB(0x80, 0, 0) },
				{ SolutionFileTextFragment.XMLAttributeName, Color.FromRGB(0xff, 0, 0) },
				{ SolutionFileTextFragment.XMLAttributeValue, Color.FromRGB(0, 0, 0xff) },
				{ SolutionFileTextFragment.XMLComment, Color.FromRGB(0, 0x80, 0) },
				{ SolutionFileTextFragment.XMLText, Color.None},

			};

			this.Container = new IHTMLDiv();

			this.View = new IHTMLPre().AttachTo(this.Container);
			this.View.style.margin = "0";

			this.Container.style.overflow = IStyle.OverflowEnum.auto;
		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {

            var c = new Form1();

            // Error	2	The type 'ScriptCoreLib.JavaScript.DOM.HTML.IHTMLContent' cannot be used as type parameter 'T' in the generic type or method 'ScriptCoreLib.Extensions.FormsExtensions.AttachTo<T>(T, System.Windows.Forms.Control)'. There is no implicit reference conversion from 'ScriptCoreLib.JavaScript.DOM.HTML.IHTMLContent' to 'System.Windows.Forms.Control'.	X:\jsc.svn\examples\javascript\test\TestFormsShadowSplit\TestFormsShadowSplit\Application.cs	37	13	TestFormsShadowSplit
            new IHTMLContent { }.AttachTo(
                //c.splitContainer1.Panel2
                c.splitContainer1.Panel2.GetHTMLTargetContainer()
            );

            var s = new IHTMLPre { "the shadow dom" }.AttachTo(Native.document.documentElement.shadow);

            // forms shall use position fixed
            // to prevent overflow!?

            __Form.InternalHTMLTargetAttachToDocument =
                (that, yield) =>
                {
                    if (that.HTMLTarget.parentNode == null)
                    {
                        that.HTMLTarget.AttachTo(Native.document.documentElement.shadow);
                    }

                    // animate!
                    yield(true);
                };

            c.Show();


        }
        public Application(IApp page)
        {
            this.page = page;
            // historic callsite scoping does not yet support instance references
            that = this;



            // X:\jsc.svn\examples\javascript\UIAutomationEvents\UIAutomationEvents\Application.cs

            page.YesIAgree.Historic(
                async scope =>
                {
                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201405/20140526

                    new UIEvent(UIEventsOfInterestAndSignificance.ClickAgree, NestedEvents: that.Events.ToArray()).With(
                         e =>
                            {
                                that.Events.Clear();
                                that.Events.Add(e);
                            }
                     );

                    var message = await that.Agree(that.page.email);
                    var x = new IHTMLPre { new { message } }.AttachToDocument();
                    await scope;
                    x.Orphanize();

                }
            );
        }
 /// <summary>
 /// This is a javascript application.
 /// </summary>
 /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
 public Application(IApp page)
 {
     Action getCurrency = async delegate
     {
         var c = await this.GetConversionRate();
         if (c.ContainsKey("GBP"))
         {
             Console.WriteLine(c["GBP"].ToString());
         }
         Console.WriteLine(c.ToString());
         var p = new IHTMLPre { innerText = c["GBP"].ToString()};
         p.AttachTo(page.body);
     };
     getCurrency();
 }
        // Z:\jsc.svn\examples\javascript\crypto\WebServiceAuthorityExperiment\

        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            new { }.With(
                async delegate
                {
                    var x = await base.GetData();


                    var o = x.value;
                    var t = new IHTMLTextArea { value = x, readOnly = true }.AttachToDocument();

                    t.style.whiteSpace = IStyle.WhiteSpaceEnum.nowrap;
                    t.style.width = "80em";
                    //t.style.right = "1em";
                    t.style.height = "20em";

                    var status = new IHTMLPre { new { verify = await base.Verify(x) } }.AttachToDocument();

                    t.style.paddingLeft = "1em";
                    t.style.borderLeft = "1em solid green";
                    t.readOnly = false;

                    //while (await t.async.onchange)

                    while (await t.async.onkeyup)
                    {
                        t.style.borderLeft = "1em solid yellow";

                        // Z:\jsc.svn\core\ScriptCoreLib.Windows.Forms\ScriptCoreLib.Windows.Forms\JavaScript\BCLImplementation\System\Windows\Forms\TextBox.cs
                        x.value = t.value.Replace(Environment.NewLine, "\n").Replace("\n", Environment.NewLine);

                        var verify = await base.Verify(x);
                        status.innerText = new { isoriginal = o == x.value, o = o.Length, t = x.value.Length, verify }.ToString();

                        if (verify)
                            t.style.borderLeft = "1em solid green";
                        else
                            t.style.borderLeft = "1em solid red";
                    }

                }
            );
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            var sw = new Stopwatch();

            sw.Start();

            service.WebMethod2(
                @"A string from JavaScript.",
                value =>
                {
                    var p = new IHTMLPre { };


                    new IHTMLSpan { innerText = "[" + sw.ElapsedMilliseconds + "ms] " }.AttachTo(p).style.color = "gray";
                    new IHTMLSpan { innerText = value }.AttachTo(p);

                    p.AttachToDocument();
                }
            );
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");

                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "Launched2");

                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: null
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion

            // 
            // http://stackoverflow.com/questions/13076272/how-do-i-give-webkitgetusermedia-permission-in-a-chrome-extension-popup-window
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150712
            new { }.With(
                async delegate
                {
                    Native.body.Clear();
                    Native.document.documentElement.style.overflow = IStyle.OverflowEnum.auto;

                    new IHTMLPre
                    {
                        "GearVR should send analog and digital signal to start parallax tracking only if near zero rotation."
                    }.AttachToDocument();

                    // would it be easy to do head tracking via webcam for VR?
                    // the app would run on android, yet
                    // two sattelites could spawn on two laptops to track the head.

                    // would we be able to thread hop between camera devices and android?

                    // http://shopap.lenovo.com/hk/en/laptops/lenovo/u-series/u330p/
                    // The U330p's integrated 720p HD webcam


                    // HD wont work for chrome app?
                    var v = await Native.window.navigator.async.onvideo;
                    v.AttachToDocument();

                    v.play();

                    new IHTMLButton { "stop" }.AttachToDocument().onclick += delegate
                    {
                        //v.src = null;
                        v.src = "";
                        //v.pause();
                        //v.stop();
                    };

                    var sw = Stopwatch.StartNew();

                    while (v.videoWidth == 0)
                        await Native.window.async.onframe;


                    const int zoomx = 2;
                    //const int zoomy = 4;

                    //var ow = v.videoWidth / zoomx;
                    var ow = 512;
                    //var oh = v.videoHeight / zoomy;
                    //var oh = 256;
                    //var oh = 96;
                    //var oh = 256;
                    var oh = 128;

                    // 40 with udp
                    //var oh = 0xA0;
                    //var oh = 0xb0;

                    // 58
                    //var oh = 196;
                    // 35
                    //var oh = 256;

                    var aloop = new IHTMLInput
                    {
                        title = "loop it",

                        type = ScriptCoreLib.Shared.HTMLInputTypeEnum.checkbox,
                        @checked = true
                    }.AttachToDocument();

                    var slider = new IHTMLInput
                    {
                        title = "stabilizer?",

                        type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range,
                        //max = 255,
                        //max = 128,
                        max = 64,

                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150712-1
                        valueAsNumber = 48
                    }.AttachToDocument();


                    var z = 0;
                    var x = 0;
                    var y = 0;

                    var frame0in = new CanvasRenderingContext2D(ow, oh);

                    Action frame0in_drawImage = delegate
                    {

                        var clip = v.videoHeight / 6;

                        // 6000 zoom out
                        // 8000 zoom in

                        // haha. this wont work.
                        //var zz = (2000 - (z - 6000).Min(2000)) / 2000f;
                        //clip = (int)(clip * zz);

                        frame0in.drawImage(v, 0, clip, v.videoWidth, v.videoHeight - clip * 2, 0, 0, ow, oh);
                    };

                    //frame0in.canvas.AttachToDocument();

                    //var frame0out = new CanvasRenderingContext2D(ow, oh);
                    ////frame0out.canvas.AttachToDocument();

                    //var frame1out = new CanvasRenderingContext2D(ow, oh);
                    ////frame1out.canvas.AttachToDocument();

                    //var frame2out = new CanvasRenderingContext2D(ow, oh);
                    //frame2out.canvas.AttachToDocument();


                    var frame3out = new CanvasRenderingContext2D(ow, oh);
                    frame3out.canvas.AttachToDocument();


                    var frame0sw = Stopwatch.StartNew();
                    var frameID = 0;
                    var frame0sw0 = Stopwatch.StartNew();

                    var fps3 = 0;

                    // avg per sec x3
                    var fps3avg = new byte[20 * 3];



                    var sent = new IHTMLPre
                    {
                    }.AttachToDocument();


                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150701


                    // what about 255.255.255.255 ?
                    chrome.socket.getNetworkList().ContinueWithResult(async n =>
                    {
                        // which networks should we notify of our data?

                        //new IHTMLPre { new { n.Length } }.AttachToDocument();

                        foreach (var item in n)
                        {
                            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                            // skip ipv6
                            if (item.address.Contains(":"))
                                continue;

                            #region send
                            new IHTMLButton { "send onframe " + item.address }.AttachToDocument().With(
                                async refresh =>
                                {
                                    refresh.style.color = "blue";

                                    refresh.style.display = IStyle.DisplayEnum.block;

                                    // experimental until ref count 33?
                                    await refresh.async.onmousedown;

                                    refresh.disabled = true;

                                    var port = new Random().Next(16000, 40000);

                                    //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();

                                    // where is bind async?
                                    var socket = new UdpClient();
                                    socket.Client.Bind(

                                         //new IPEndPoint(IPAddress.Any, port: 40000)
                                         new IPEndPoint(IPAddress.Parse(item.address), port)
                                     );


                                    // this will eat too much memory?
                                    //div.ownerDocument.defaultView.onframe +=
                                    Native.window.onframe += e =>
                                     {
                                         //var px = (float)(__yscan64max_ix - v.videoWidth / 2) / (float)v.videoWidth;
                                         var px0 = (float)(x - ow / 2) / (float)ow;
                                         var py0 = (float)(y - oh / 2) / (float)oh;


                                         // 4000 zoom out
                                         // 7000 zoom in

                                         // haha. this wont work.
                                         //var pz = ((z - 4500) / 2000f).Max(0f).Min(1.5f);

                                         // in a dark room?
                                         var pz = ((z - 6000) / 1000f).Max(0f).Min(1.5f);

                                         // allow py only if pz is negative.
                                         // 0 means py stays
                                         // 1 means py is zero

                                         var pzz = (1.0f - pz).Max(0.0f).Min(1.0f);

                                         var py = py0 * pzz;
                                         var px = px0 * pzz;

                                         pz -= 0.3f;
                                         // !! leaning in kills parallax left and up.
                                         // rotating on gear vr will cancel all parallax.

                                         // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                                         var nmessage = e.counter + ":" + px + ":" + py + ":" + pz;

                                         //sent.innerText = nmessage.Replace(":", ":\n") + new { py0, pzz, py };
                                         sent.innerText = nmessage.Replace(":", ":\n");

                                         var data = Encoding.UTF8.GetBytes(nmessage);      //creates a variable b of type byte



                                         //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                                         // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                                         socket.Send(
                                              data,
                                              data.Length,
                                              hostname: "239.1.2.3",
                                              port: 43834
                                          );
                                     };


                                }
                            );
                            #endregion

                        }
                    }
                );


                    var status = new IHTMLPre {
                        () => new {
                            frameID,
                            frame0sw.ElapsedMilliseconds,

                            fps = 1000 / frame0sw.ElapsedMilliseconds ,
                            fps3avg = (byte)fps3avg.Average(k => k),

                            x,y,z,

                            fps3,

                            // script: error JSC1000: No implementation found for this native method, please implement [System.String.Replace(System.Char, System.Char)]
                        }.ToString().Replace(",", ",\t")
                    }.AttachToDocument();


                    var fdiv = new IHTMLDiv { }.AttachToDocument();

                    new { }.With(
                        async delegate
                        {
                            var vw = ow;
                            var vh = oh;

                            #region 3 workers
                            // what about sending bytes[2,3] over?
                            byte[] rgba_bytes0in = null;
                            var rgba_bytes0in_set = new System.Threading.SemaphoreSlim(1);
                            byte[] rgba_bytes0out = null;
                            var rgba_bytes0out_set = new System.Threading.SemaphoreSlim(1);
                            //SemaphoreSlim rgba_bytes0out_set = new __SemaphoreSlim(1) { Name = "rgba_bytes0out_set" };


                            byte[] rgba_bytes1in = null;
                            var rgba_bytes1in_set = new System.Threading.SemaphoreSlim(1);
                            byte[] rgba_bytes1out = null;
                            var rgba_bytes1out_set = new System.Threading.SemaphoreSlim(1);

                            byte[] rgba_bytes2in = null;
                            var rgba_bytes2in_set = new System.Threading.SemaphoreSlim(1);
                            byte[] rgba_bytes2out = null;
                            var rgba_bytes2out_set = new System.Threading.SemaphoreSlim(1);


                            Task.Run(
                                async delegate
                                {
                                    var w = new WorkerThread(0, vw, vh);
                                    next:
                                    await rgba_bytes0in_set.WaitAsync();

                                    rgba_bytes0out = w.Invoke(rgba_bytes0in);
                                    rgba_bytes1out = null;
                                    rgba_bytes2out = null;

                                    rgba_bytes0in = null;
                                    rgba_bytes1in = null;
                                    rgba_bytes2in = null;
                                    // we should not sync back data we did not put there. nor should it be there anyway?
                                    rgba_bytes0out_set.Release();
                                    goto next;
                                }
                            );


                            Task.Run(
                                async delegate
                                {
                                    var w = new WorkerThread(1, vw, vh);
                                    next:
                                    await rgba_bytes1in_set.WaitAsync();
                                    rgba_bytes0out = null;
                                    rgba_bytes1out = w.Invoke(rgba_bytes1in);
                                    rgba_bytes2out = null;

                                    rgba_bytes0in = null;
                                    rgba_bytes1in = null;
                                    rgba_bytes2in = null;

                                    rgba_bytes1out_set.Release();
                                    goto next;
                                }
                            );


                            Task.Run(
                                async delegate
                                {
                                    var w = new WorkerThread(2, vw, vh);
                                    next:
                                    await rgba_bytes2in_set.WaitAsync();

                                    rgba_bytes0out = null;
                                    rgba_bytes1out = null;
                                    rgba_bytes2out = w.Invoke(rgba_bytes2in);
                                    rgba_bytes0in = null;
                                    rgba_bytes1in = null;
                                    rgba_bytes2in = null;


                                    rgba_bytes2out_set.Release();
                                    goto next;
                                }
                            );
                            #endregion

                            Console.WriteLine("worker0 spinning already...");

                            //do
                            await v.async.onclick;

                            {

                                frame0sw0 = Stopwatch.StartNew();
                                //Console.WriteLine(frame0sw0.ElapsedMilliseconds + " fetch frame0");

                                frame0in.drawImage(v, 0, v.videoHeight / 4, v.videoWidth, v.videoHeight / 2, 0, 0, vw, vh);
                                rgba_bytes0in = frame0in.bytes;
                                rgba_bytes0in_set.Release();
                                new IHTMLPre { frame0sw0.ElapsedMilliseconds + " frame0 posted" }.AttachTo(fdiv);

                                // await Task.Delay(1000 / 60);
                                // 300?
                                // Console.WriteLine(frame0sw0.ElapsedMilliseconds + " send frame2");
                                frame0in.drawImage(v, 0, v.videoHeight / 4, v.videoWidth, v.videoHeight / 2, 0, 0, vw, vh);
                                rgba_bytes1in = frame0in.bytes;
                                rgba_bytes1in_set.Release();
                                new IHTMLPre { frame0sw0.ElapsedMilliseconds + " frame1 posted" }.AttachTo(fdiv);

                                loop:
                                // 60fps!!
                                frameID += 3;

                                frame0in_drawImage();
                                rgba_bytes2in = frame0in.bytes;
                                rgba_bytes2in[0] = (byte)(frameID & 0xff);
                                rgba_bytes2in[1] = (byte)((frameID >> 8) & 0xff);
                                rgba_bytes2in[4] = slider;
                                rgba_bytes2in_set.Release();

                                //await Task.WhenAll(Native.window.async.onframe, rgba_bytes0out_set.WaitAsync());
                                await rgba_bytes0out_set.WaitAsync();
                                if (!aloop.@checked)
                                    new IHTMLPre { frame0sw0.ElapsedMilliseconds + " collected frame0" }.AttachTo(fdiv);
                                //frame0out.bytes = rgba_bytes0out;
                                //frame3out.drawImage(frame0out.canvas, 0, 0, vw, vh);
                                frame3out.bytes = rgba_bytes0out;
                                rgba_bytes2in = null;
                                rgba_bytes0out = null;

                                frame0in_drawImage();
                                rgba_bytes0in = frame0in.bytes;
                                rgba_bytes0in[0] = (byte)(frameID & 0xff);
                                rgba_bytes0in[1] = (byte)((frameID >> 8) & 0xff);
                                rgba_bytes0in[4] = slider;
                                rgba_bytes0in_set.Release();

                                //await Task.WhenAll(Native.window.async.onframe, rgba_bytes1out_set.WaitAsync());
                                await rgba_bytes1out_set.WaitAsync();
                                if (!aloop.@checked)
                                    new IHTMLPre { frame0sw0.ElapsedMilliseconds + " collected frame1" }.AttachTo(fdiv);
                                //frame1out.bytes = rgba_bytes1out;
                                //frame3out.drawImage(frame1out.canvas, 0, 0, vw, vh);
                                frame3out.bytes = rgba_bytes1out;
                                rgba_bytes0in = null;
                                rgba_bytes1out = null;


                                frame0in_drawImage();
                                rgba_bytes1in = frame0in.bytes;
                                rgba_bytes1in[0] = (byte)(frameID & 0xff);
                                rgba_bytes1in[1] = (byte)((frameID >> 8) & 0xff);
                                rgba_bytes1in[4] = slider;
                                rgba_bytes1in_set.Release();

                                await Task.WhenAll(Native.window.async.onframe, rgba_bytes2out_set.WaitAsync());
                                if (!aloop.@checked)
                                    new IHTMLPre { frame0sw0.ElapsedMilliseconds + " collected frame2, next? " + new { aloop.@checked } }.AttachTo(fdiv);

                                //
                                z = rgba_bytes2out[0] + (rgba_bytes2out[1] << 8);
                                x = rgba_bytes2out[4] + (rgba_bytes2out[5] << 8);
                                y = rgba_bytes2out[8];

                                //frame2out.bytes = rgba_bytes2out;
                                //frame3out.drawImage(frame2out.canvas, 0, 0, vw, vh);
                                frame3out.bytes = rgba_bytes2out;
                                rgba_bytes1in = null;
                                rgba_bytes2out = null;


                                frame0sw0.Stop();
                                frame0sw = frame0sw0;


                                //if (v.src == null)
                                //{
                                //    Native.body.style.backgroundColor = "red";
                                //    return;
                                //}

                                //if (aloop)
                                if (!aloop.@checked)
                                {
                                    //await Task.WhenAny(aloop.async.@checked, v.async.onclick);
                                    await v.async.onclick;

                                    fdiv.Clear();
                                }

                                frame0sw0 = Stopwatch.StartNew();
                                fps3 = (int)(3000 / frame0sw.ElapsedMilliseconds);
                                fps3avg[(frameID / 3) % fps3avg.Length] = (byte)fps3;

                                if (fps3 > 55)
                                {
                                    status.style.color = "blue";
                                }
                                else
                                {
                                    status.style.color = "red";
                                }

                                goto loop;


                                // 10000ms?
                                // 400ms?
                            }
                            //} while (await v.async.onclick);
                            //} while (await Native.window.async.onframe);
                        }
                    );

                    await Native.window.async.onblur;

                    Native.body.style.backgroundColor = "yellow";
                }
            );
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // x:\jsc.svn\examples\javascript\chrome\apps\chromeudpsendasync\chromeudpsendasync\application.cs
            // reload on idle?
            // edit and continue over udp?

            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201503/20150306/udp

            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");

                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "ChromeUDPSendAsync");

                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: null
                        );

                        //xappwindow.setAlwaysOnTop
                        xappwindow.setAlwaysOnTop(true);

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion

            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeNetworkInterfaces\ChromeNetworkInterfaces\Application.cs

            //{{ Length = 4 }}
            //{{ prefixLength = 64, name = {D7020941-742E-4570-93B2-C0372D3D870F}, address = fe80::88c0:f0a:9ccf:cba0 }}
            //{{ prefixLength = 24, name = {D7020941-742E-4570-93B2-C0372D3D870F}, address = 192.168.43.28 }}
            //{{ prefixLength = 64, name = {A8657A4E-8BFA-41CC-87BE-6847E33E1A81}, address = 2001:0:9d38:6abd:20a6:2815:3f57:d4e3 }}
            //{{ prefixLength = 64, name = {A8657A4E-8BFA-41CC-87BE-6847E33E1A81}, address = fe80::20a6:2815:3f57:d4e3 }}


            var c = new CanvasRenderingContext2D(800, 400);

            c.canvas.style.border = "1px solid blue";
            c.canvas.AttachToDocument();
            c.canvas.style.SetLocation(0, 0);

            Native.document.body.style.marginTop = "400px";

            new IHTMLButton { "clear" }.AttachToDocument().onclick += delegate
            {
                c.clearRect(0, 0, 800, 400);
            };

            Action begin = delegate
            {
                c.beginPath();
                c.moveTo(0, 0);
            };

            // ok his app needs to run as a chrome app.
            new { }.With(
                async delegate
                {
                    (Native.document.body.style as dynamic).webkitUserSelect = "auto";
                    Native.document.documentElement.style.overflow = IStyle.OverflowEnum.auto;


                    new IHTMLButton { "update pending... update available. click to reload.." }.AttachToDocument().onclick += delegate
                    {
                        // can we get an udp signal from the compiler when the app is out of date, when the update is pending?
                        chrome.runtime.reload();
                    };

                    var n = await chrome.socket.getNetworkList();

                    // Z:\jsc.svn\examples\javascript\chrome\hybrid\HybridHopToUDPChromeApp\Application.cs
                    var n24 = n.Where(x => x.prefixLength == 24).ToArray();

                    n24.WithEach(
                        async nic =>
                        {
                            // wifi? lan?
                            var status = new IHTMLPre { new { nic.name, nic.address } }.AttachToDocument();
                            var buffer = new IHTMLPre { }.AttachToDocument();

                            // Z:\jsc.svn\examples\javascript\chrome\hybrid\HybridHopToUDPChromeApp\Application.cs
                            //var uu = new UdpClient(40014);
                            var uu = new UdpClient(40094);

                            //args.mouse = "awaiting vertexTransform at " + nic + " :40014";

                            // X:\jsc.svn\examples\java\android\forms\FormsUDPJoinGroup\FormsUDPJoinGroup\ApplicationControl.cs
                            // X:\jsc.svn\examples\java\android\LANBroadcastListener\LANBroadcastListener\ApplicationActivity.cs
                            //uu.JoinMulticastGroup(IPAddress.Parse("239.1.2.3"), nic);
                            uu.JoinMulticastGroup(IPAddress.Parse("239.1.2.3"));
                            while (true)
                            {
                                var ux = await uu.ReceiveAsync(); // did we jump to ui thread?
                                                                  //Console.WriteLine("ReceiveAsync done " + Encoding.UTF8.GetString(x.Buffer));
                                                                  //args.vertexTransform = x.Buffer;


                                buffer.innerText = new { ux.Buffer.Length }.ToString();

                                // cam we get also some floats?

                                // https://www.khronos.org/registry/typedarray/specs/latest/

                                float[] f = new Float32Array(new Uint8ClampedArray(ux.Buffer).buffer);

                                // pen x, y, pressure
                                if (f.Length >= 3)
                                {
                                    for (int i = 0; i < 3; i++)
                                    {
                                        var fi = f[i];

                                        new IHTMLDiv { new { i, fi } }.AttachTo(buffer);

                                    }

                                    var x = f[0];
                                    var y = f[1];
                                    var pressure = f[2];


                                    begin();

                                    c.lineWidth = 1 + (pressure / 255.0 * 7);

                                    if (pressure > 0)
                                        c.strokeStyle = "blue";
                                    else
                                        c.strokeStyle = "rgba(0,0,255,0.25)";

                                    c.lineTo((int)(x * 0.1), 400 - (int)(y * 0.1));

                                    //c.lineTo(e.OffsetX, e.OffsetY);
                                    //c.lineTo(e.movementX, e.movementY);
                                    c.stroke();

                                    begin = delegate
                                    {
                                        c.beginPath();
                                        c.moveTo((int)(x * 0.1), 400 - (int)(y * 0.1));
                                    };

                                }
                                //new Float32Array()
                            }
                        }
                    );

                }
             );


        }
        // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201511/20151111/udp

        // subst b: s:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPFloats\ChromeUDPFloats\bin\Debug\staging\ChromeUDPFloats.Application\web



        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // https://www.shadertoy.com/view/lsSGRz


            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");

                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "ChromeUDPSendAsync");

                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: null
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion




            new IHTMLButton { "update pending... update available. click to reload.." }.AttachToDocument().onclick += delegate
            {
                // can we get an udp signal from the compiler when the app is out of date, when the update is pending?
                chrome.runtime.reload();
            };


            Action<chrome.NetworkInterface> listen = async nic =>
            {
                var status = new IHTMLPre { new { nic.address } }.AttachToDocument();
                var buffer = new IHTMLPre { }.AttachToDocument();

                // Z:\jsc.svn\examples\javascript\chrome\hybrid\HybridHopToUDPChromeApp\Application.cs
                var uu = new UdpClient(40014);

                //args.mouse = "awaiting vertexTransform at " + nic + " :40014";

                // z:\jsc.svn\examples\java\android\forms\FormsUDPJoinGroup\FormsUDPJoinGroup\ApplicationControl.cs
                // X:\jsc.svn\examples\java\android\LANBroadcastListener\LANBroadcastListener\ApplicationActivity.cs
                //uu.JoinMulticastGroup(IPAddress.Parse("239.1.2.3"), nic);
                uu.JoinMulticastGroup(IPAddress.Parse("239.1.2.3"));
                while (true)
                {
                    var x = await uu.ReceiveAsync(); // did we jump to ui thread?
                    //Console.WriteLine("ReceiveAsync done " + Encoding.UTF8.GetString(x.Buffer));
                    //args.vertexTransform = x.Buffer;


                    buffer.innerText = new { x.Buffer.Length }.ToString();

                    // cam we get also some floats?

                    // https://www.khronos.org/registry/typedarray/specs/latest/

                    float[] f = new Float32Array(new Uint8ClampedArray(x.Buffer).buffer);

                    if (f.Length >= 16)
                        for (int i = 0; i < 16; i++)
                        {
                            var fi = f[i];

                            new IHTMLDiv { new { i, fi } }.AttachTo(buffer);

                        }
                    //new Float32Array()
                }
            };


            new { }.With(
                async delegate
                {
                    // 2012 wont like nested async methods..

                    var n = await chrome.socket.getNetworkList();

                    // Z:\jsc.svn\examples\javascript\chrome\hybrid\HybridHopToUDPChromeApp\Application.cs
                    //var n24 = n.Where(x => x.prefixLength == 24).ToArray();

                    foreach (var x in n)
                    {
                        if (x.prefixLength == 24)
                            listen(x);
                    }

                }
             );


        }
		public Application(IApp page)
		{
			// X:\jsc.svn\examples\javascript\chrome\extensions\ChromeTabsExperiment\ChromeTabsExperiment\Application.cs

			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_tabs = self_chrome.tabs;

			//if (self_chrome_tabs == null)
			//	return;


			//	....488: { SourceMethod = Void.ctor(ChromeExtensionHopToTabThenShadow.HTML.Pages.IApp), i = [0x00ba] brtrue.s + 0 - 1 }
			//1984:02:01 RewriteToAssembly error: System.ArgumentException: Value does not fall within the expected range.
			//at jsc.ILInstruction.ByOffset(Int32 i) in X:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1184
			//at jsc.ILInstruction.get_BranchTargets() in X:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1225

			#region self_chrome_tabs
			if (self_chrome_tabs != null)
			{
				Console.WriteLine("self_chrome_tabs");

				chrome.tabs.Updated += async (i, x, tab) =>
				{
					// chrome://newtab/

					if (tab.url.StartsWith("chrome-devtools://"))
						return;

					if (tab.url.StartsWith("chrome://"))
						return;


					// while running tabs.insertCSS: The extensions gallery cannot be scripted.
					if (tab.url.StartsWith("https://chrome.google.com/webstore/"))
						return;


					if (tab.status != "complete")
						return;

					//new chrome.Notification
					//{
					//	Message = "chrome.tabs.Updated " + new
					//	{
					//		tab.id,
					//		tab.url,
					//		tab.status,
					//		tab.title
					//	}
					//};


					// while running tabs.insertCSS: The tab was closed.

					// 		public static Task<object> insertCSS(this TabIdInteger tabId, object details);
					// public static void insertCSS(this TabIdInteger tabId, object details, IFunction callback);


					// for some sites the bar wont show as they html element height is 0?
					await tab.id.insertCSS(
								new
								{
									code = @"

	html { 
	border-left: 1em solid cyan;
	padding-left: 1em; 
	}


	"
								}
							);

					Console.WriteLine(
						"insertCSS done " + new { tab.id, tab.url }
						);


					// where is the hop to iframe?
					// X:\jsc.svn\examples\javascript\Test\TestSwitchToIFrame\TestSwitchToIFrame\Application.cs


					// https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150403

					//await (HopToChromeTab)tab.id;
					await (HopToChromeTab)tab;
					//await tab.id;

					// are we now on the tab?
					// can we jump back?

					// what about jumping with files/uploads?
					Console.WriteLine("// are we now on the tab yet?");

					Native.body.style.borderLeft = "1em solid blue";
					Native.document.documentElement.style.borderLeft = "1em solid blue";


					// <div class="player-video-title">Ariana Grande - One Last Time (Official)</div>

					Native.document.title = "(" + Native.document.title + ")";

					// this is a shadow application

					var pre = new IHTMLPre { "shadow application. repackage the ui. root html element still displays borders." };

					// AttachToDocumentShadow
					// see jsc, we are proposing a convinience method
					pre.AttachTo(
						Native.document.documentElement.shadow
					);

					var div = new IHTMLDiv { }.AttachTo(pre);

					new IStyle(div)
					{
						//  time to tell where we want our content 

						// css breaks? cannot use this scenario yet. without rewriting css
						position = IStyle.PositionEnum.@fixed,
						//position = IStyle.PositionEnum.absolute,

						top = "3em",

						left = "0.5em",
						right = "0.5em",
						bottom = "0.5em"
					};

					var content = new IHTMLContent {
						// show only the body
						//select = "body"
					}.AttachTo(div);



					// X:\jsc.svn\examples\javascript\xml\FindByClassAndObserve\FindByClassAndObserve\Application.cs

					// luckyly its only hidden... no need to await the element and find it later

					// <span id="eow-title" class="watch-title " dir="ltr" title="THORnews Weird Weather Watch! Wind Dragon inbound to USA Pacific Coast!">


					//var yt0 = Native.document.querySelectorAll(" [class='player-video-title']");
					//var yt1 = Native.document.querySelectorAll(" [class='watch-title ']");

					//yt0.Concat(yt1).WithEach(
					//	 async e =>
					//	 {
					//		 do
					//		 {
					//			 Native.document.title = e.innerText;

					//			 // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenShadow\ChromeExtensionHopToTabThenShadow\Application.cs
					//			 // we would need to jump back here to do extension notification
					//			 // the jump back would be to another state machine tho
					//			 // we would need other ports opened?

					//			 Native.document.documentElement.style.borderLeft = "1em solid yellow";
					//			 for (int xi = 0; xi < 5; xi++)
					//			 {
					//				 Native.body.style.borderLeft = "1em solid yellow";
					//				 await Task.Delay(100);
					//				 Native.body.style.borderLeft = "1em solid black";
					//				 await Task.Delay(100);
					//			 }
					//			 Native.document.documentElement.style.borderLeft = "1em solid red";

					//			 // or actually instead of jumping back we need to send back progress?
					//		 }
					//		 while (await e.async.onmutation);
					//	 }
					// );

					// lets start monitoring
				};



				return;
			}
			#endregion


			// we made the jump?
			Native.body.style.borderLeft = "1em solid red";

			// yes we did. can we talk to the chrome extension?

			// lets do some SETI

			// The runtime.onMessage event is fired in each content script running in the specified tab for the current extension.

			// Severity	Code	Description	Project	File	Line
			//Error       'runtime.onMessage' is inaccessible due to its protection level ChromeExtensionHopToTabThenShadow X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenShadow\ChromeExtensionHopToTabThenShadow\Application.cs 272

			// public static event System.Action<object, object, object> Message

			#region chrome.runtime.Message
			chrome.runtime.Message += (object message, chrome.MessageSender sender, IFunction sendResponse) =>
			{
				var s = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

				// 59ms onmessage {{ message = hello, id = aemlnmcokphbneegoefdckonejmknohh }}
				Console.WriteLine("xonmessage " + new { s.state, sender.id });
				Native.body.style.borderLeft = "1px solid blue";

				#region xAsyncStateMachineType
				var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
					item =>
					{
						// safety check 1

						//Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

						var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(item);
						if (xisIAsyncStateMachine)
						{
							//Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

							return item.FullName == s.TypeName;
						}

						return false;
					}
				);
				#endregion


				var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
				var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

				var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

				#region 1__state
				xAsyncStateMachineType.GetFields(
						  System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
					  ).WithEach(
					   AsyncStateMachineSourceField =>
					   {

						   Console.WriteLine(new { AsyncStateMachineSourceField });

						   if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
						   {
							   AsyncStateMachineSourceField.SetValue(
								   NewStateMachineI,
								   s.state
								);
						   }


					   }
				  );
				#endregion

				NewStateMachineI.MoveNext();

				//Task.Delay(1000).ContinueWith(
				//	delegate
				//	{
				//		sendResponse.apply(null, "response");
				//	}
				//);

			};
			#endregion


			//         Native.window.onmessage += e =>
			//{

			//};
		}
		private void ContinueBuildingApplication()
		{

			var note1 = new IHTMLPre
			{
				innerHTML = @"Notice: If flash does not respond to events, you need to clear your cache. 
+ Chrome flash in 'localhost' on Cassini always fails?
  - If so Try http://127.0.0.1 or http://COMPUTERNAME
+ Opera does not pass delegates?
+ IE cannot return from javascript to flash
+ Web page could be delivered within flash package
+ Javascript rewrite could omit unused types and methods
"

			}.AttachToDocument();

			note1.style.whiteSpace = ScriptCoreLib.JavaScript.DOM.IStyle.WhiteSpaceEnum.pre;
			note1.style.fontSize = "small";
			note1.style.color = Color.Red;


			var s = new UltraSprite();

			s.AttachSpriteToDocument();

			var SayHello = new IHTMLButton { innerText = "Say Hello to flash!" }.AttachToDocument();

			SayHello.onclick +=
				delegate
				{
					s.AppendLine("Hello from javascript");

					s.WhenReady(
						delegate
						{
							s.AppendLine("What about using the web service?");
						}
					);
				};

			s.AppendLine("This call is delayed until flash is loaded (1)");
			s.AppendLine("This call is delayed until flash is loaded (2)");
			s.AppendLine("This call is delayed until flash is loaded (3)");

			s.WhenReady(
				delegate
				{
					s.AppendLine("What about using the web service?");
				}
			);

			// passing the interface to flash is delayed until it is loaded, using the getter will fault
			s.WebService = new AlphaWebService();
			s.WebServiceEnabled = this;

			s.AppendLine("This call is delayed until flash is loaded (4)");

			new IHTMLBreak().AttachToDocument();


			this.WebServiceEnabled = new IHTMLInput(ScriptCoreLib.Shared.HTMLInputTypeEnum.checkbox);

			var WebServiceEnabledLabel = new IHTMLLabel("WebService is enabled for flash", this.WebServiceEnabled);

			new IHTMLDiv(
				WebServiceEnabledLabel,
				WebServiceEnabled
			).AttachToDocument();

			ButtonsForWebService();
		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            page.TakePicture.style.color = "blue";



            page.TakePicture.onclick +=
                delegate
                {
                    //Unknown chromium error: -324

                    service.TakePicture("",
                        path =>
                        {
                            Console.WriteLine(new { path });

                            //new IHTMLDiv { innerText = new { e }.ToString() }.AttachToDocument();

                            new IHTMLImage { }.AttachToDocument().With(
                                img =>
                                {
                                    // portrait mode only!

                                    //div.style.color = JSColor.Red;
                                    img.src = "/thumb/" + path;

                                    #region onload +=
                                    img.InvokeOnComplete(
                                        delegate
                                        {
                                            //div.style.color = JSColor.Green;

                                            IHTMLPre p = null;

                                            img.onclick += delegate
                                            {
                                                if (p == null)
                                                {
                                                    img.src = "/io/" + path;
                                                    img.style.width = "100%";
                                                    //div.style.display = IStyle.DisplayEnum.block;

                                                    p = new IHTMLPre { }.AttachToDocument();
                                                    service.GetEXIF("/io/" + path,
                                                        x =>
                                                        {
                                                            p.innerText = x;
                                                        }
                                                    );


                                                }
                                                else
                                                {

                                                    p.Orphanize();
                                                    p = null;
                                                    img.src = "/thumb/" + path;
                                                    img.style.width = "";
                                                }

                                            };
                                        }
                                    );
                                    #endregion



                                }
                            );
                        }
                    );

                };
        }
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IDefaultPage page)
		{
			new JSCSolutionsNETImage().ToBackground(page.Item1.style, false);
			new JSCSolutionsNETImage().ToBackground(page.Item2.style, false);


			// Update document title
			// http://do.jsc-solutions.net/Update-document-title

			@"Hello world".ToDocumentTitle();
			// Send xml to server
			// http://do.jsc-solutions.net/Send-xml-to-server

			var v = new SolutionFileView();

			var f = new SolutionFile();

			f.WriteHTMLElement(StockPageDefault.Element);

			v.File = f;

			var Container = new IHTMLDiv();

			Container.style.position = IStyle.PositionEnum.relative;
			Container.style.display = IStyle.DisplayEnum.inline_block;
			Container.style.width = "600px";
			Container.style.height = "400px";
			Container.style.border = "1px solid gray";

			var ToolbarHeight = "1.3em";
			var Content = new IHTMLDiv().AttachTo(Container);

			Content.style.position = IStyle.PositionEnum.absolute;
			Content.style.left = "0px";
			Content.style.top = "0px";
			Content.style.right = "0px";
			Content.style.bottom = ToolbarHeight;


			var Toolbar = new IHTMLDiv().AttachTo(Container);

			Toolbar.style.backgroundColor = Color.FromGray(0xef);
			Toolbar.style.position = IStyle.PositionEnum.absolute;
			Toolbar.style.left = "0px";
			Toolbar.style.height = ToolbarHeight;
			Toolbar.style.right = "0px";
			Toolbar.style.bottom = "0px";

			Action<IHTMLImage, string, Action> AddToolbarButton =
				(img, text, handler) =>
				{
					var span = new IHTMLSpan { innerText = text };

					span.style.paddingLeft = "1.5em";
					span.style.paddingRight = "0.3em";

					var a = new IHTMLAnchor
					{
						img, span
					};

					img.style.verticalAlign = "middle";
					img.border = 0;
					img.style.position = IStyle.PositionEnum.absolute;

					a.style.backgroundColor = Color.FromGray(0xef);
					a.style.color = Color.Black;
					a.style.textDecoration = "none";
					a.style.fontFamily = IStyle.FontFamilyEnum.Tahoma;

					a.href = "javascript: void(0);";
					a.onclick +=
						delegate
						{
							handler();
						};
					a.style.display = IStyle.DisplayEnum.inline_block;
					a.style.height = "100%";


					a.onmousemove +=
						delegate
						{
							a.style.backgroundColor = Color.FromGray(0xff);
						};

					a.onmouseout +=
						delegate
						{
							a.style.backgroundColor = Color.FromGray(0xef);
						};

					Toolbar.Add(a);
				};


			v.Container.style.height = "100%";
			v.Container.AttachTo(Content);


			Content.Add(v.Container);

			var i = CreateEditor();

			i.AttachTo(Content);



			var ii = new IHTMLPre().AttachTo(Content);

			ii.style.position = IStyle.PositionEnum.absolute;
			ii.style.left = "0px";
			ii.style.top = "0px";
			ii.style.right = "0px";
			ii.style.bottom = "0px";
			ii.style.overflow = IStyle.OverflowEnum.auto;
			ii.style.padding = "0px";
			ii.style.margin = "0px";
			ii.style.whiteSpace = IStyle.WhiteSpaceEnum.normal;

			v.Container.style.display = IStyle.DisplayEnum.none;
			i.style.display = IStyle.DisplayEnum.empty;
			ii.style.display = IStyle.DisplayEnum.none;

			AddToolbarButton(new RTA_mode_design(), "Design",
				delegate
				{
					v.Container.style.display = IStyle.DisplayEnum.none;
					ii.style.display = IStyle.DisplayEnum.none;
					i.style.display = IStyle.DisplayEnum.empty;
				}
			);

			AddToolbarButton(new RTA_mode_html(), "Source",
				delegate
				{
					v.Container.style.display = IStyle.DisplayEnum.empty;
					ii.style.display = IStyle.DisplayEnum.none;
					i.style.display = IStyle.DisplayEnum.none;

					f.Clear();

					i.WhenContentReady(
						body =>
						{
							f.WriteHTMLElement(body.AsXElement());

							// update
							v.File = f;
						}
					);


				}
			);

			AddToolbarButton(new RTA_mode_html(), "Source raw",
				delegate
				{
					v.Container.style.display = IStyle.DisplayEnum.none;
					ii.style.display = IStyle.DisplayEnum.empty;
					i.style.display = IStyle.DisplayEnum.none;



					i.WhenContentReady(
						body =>
						{
							ii.innerText = body.AsXElement().ToString();
						}
					);


				}
			);

			page.PageContainer.Add(Container);

			new ApplicationWebService().WebMethod2(
				new XElement(@"Document",
					new object[] {
						new XElement(@"Data", 
							new object[] {
								@"Hello world"
							}
						),
						new XElement(@"Client", 
							new object[] {
								@"Unchanged text"
							}
						)
					}
				),
				delegate(XElement doc)
				{
					// Show server message as document title
					// http://do.jsc-solutions.net/Show-server-message-as-document-title

					doc.Element(@"Data").Value.ToDocumentTitle();
				}
			);
		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // user gets to drop a csv
            // with X and Y fields.
            // where is our csv parser? assetslibary?

            // show title?


            #region test
            new { }.With(
                async delegate
                {
                    { fixup: await Task.CompletedTask; }

                    var bytes = new byte[] { 0xcc };

                    await new IHTMLButton { "test worker " + new { Thread.CurrentThread.ManagedThreadId, bytes = bytes.ToHexString() } }.AttachToDocument().async.onclick;

                    await default(HopToWorker);

                    var output = "hello " + new { Thread.CurrentThread.ManagedThreadId, bytes = bytes.ToHexString() };

                    Console.Title = "progress!";

                    await Task.Delay(500);

                    new { }.With(
                        async delegate
                        {
                            { fixup: await Task.CompletedTask; }

                            // is this supposed to work?
                            var output2 = "hello " + new { Thread.CurrentThread.ManagedThreadId };
                            await default(HopToUI);

                            new IHTMLPre { "progress... " + new { Thread.CurrentThread.ManagedThreadId, output2 } }.AttachToDocument();
                        }
                    );



                    await Task.Delay(500);



                    await default(HopToUI);

                    new IHTMLPre { "ready " + new { Thread.CurrentThread.ManagedThreadId, output } }.AttachToDocument();

                    // ready { ManagedThreadId = 1, output = hello { ManagedThreadId = 10 } }
                }
            );
            #endregion


            Native.css[IHTMLElement.HTMLElementEnum.head].style.display = IStyle.DisplayEnum.block;
            Native.css[IHTMLElement.HTMLElementEnum.title].style.display = IStyle.DisplayEnum.block;

            new { }.With(
                async delegate
                {
                    { fixup: await Task.CompletedTask; }

                    Native.document.documentElement.css.hover.style.backgroundColor = "pink";
                    //Native.document.documentElement.css.dragover
                    // while await ondrop ?
                    Native.document.documentElement.ondragover += ee =>
                    {
                        Native.document.documentElement.style.backgroundColor = "cyan";
                        // await leave? unless ondrop?
                    };

                    Native.document.documentElement.ondragleave += delegate
                    {
                        Native.document.documentElement.style.backgroundColor = "";
                    };

                    new IHTMLPre { "drop a file" }.AttachToDocument();

                    //Native.document.documentElement.ondrop += e =>
                    //var e = await Native.document.documentElement.async.ondrop;
                    var f = await Native.document.documentElement.async.ondropfile;

                    Native.document.documentElement.style.backgroundColor = "yellow";

                    new IHTMLPre { new { Thread.CurrentThread.ManagedThreadId, f.name, f.size } }.AttachToDocument();
                    // { name = download.csv, size = 20851425 }

                    var sw = Stopwatch.StartNew();
                    // if the drop is from a network share it wil take a while..

                    //{ ManagedThreadId = 1, name = data.csv, size = 110777754 }
                    //{ ManagedThreadId = 1, ElapsedMilliseconds = 43418 }

                    var bytes = await f.readAsBytes();

                    new IHTMLPre { new { Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds } }.AttachToDocument();

                    // nuget google
                    await google.maps.api;

                    #region map
                    var div = new IHTMLDiv
                    {
                    }.AttachToDocument();

                    div.style.border = "1px dashed red";
                    div.style.height = "300px";
                    div.style.left = "0px";
                    div.style.right = "0px";



                    // https://developers.google.com/maps/documentation/javascript/reference?csw=1#MapOptions
                    map = new google.maps.Map(div,
                        new
                        {
                            disableDefaultUI = true,

                            center = new { lat = 59.4329527, lng = 24.7023564 },
                            zoom = 6.0
                        }
                    );


                    new IHTMLPre { () => new { zoom = map.getZoom() } }.AttachToDocument();


                    var marker0 = new google.maps.Marker(
                         new
                         {
                             position = new
                             {
                                 lat = 59.4329527,
                                 lng = 24.7023564
                             },
                             //label = "T",
                             //title = "Tallinn",
                             map
                         }
                      );

                    #endregion


                    await new IHTMLButton { "go" }.AttachToDocument().async.onclick;
                    var bytes1 = bytes;
                    await default(HopToWorker);

                    // start the static line reader.

                    WorkerReader = new StreamReader(new MemoryStream(bytes1));

                    // now before we jump back to ui. lets start reading the lines...
                    // working... { ManagedThreadId = 1, output = hello { ManagedThreadId = 11, Length = 20851425, WorkerReaderLineCount = 0 } }

                    new { }.With(
                        async delegate
                        {
                            { fixup: await Task.CompletedTask; }

                            var output = "hello " + new { Thread.CurrentThread.ManagedThreadId };
                            await default(HopToUI);
                            WorkerUI = new IHTMLPre { "working... " + new { Thread.CurrentThread.ManagedThreadId, output } }.AttachToDocument();

                            // cant jump back can we?
                        }
                    );

                    var header = WorkerReader.ReadLine();

                    #region rows
                    // Jkn;Kohanimi;Keel;Kohanime staatus;Kohanime olek;Nimeobjekti liik;Lisainfo;Maakond,omavalitsus,asustusüksus;X;Y; 

                    //EIC;X;Y;ID;IK3MAX A;POSTOFFICE;ADDRESS
                    //00117987-Y;6590203.66;534216.50;6250743;2916.98;Tallinn Harju maakond;Tallinn, Nooda tee, 7

                    //var headerX = header.Split(';').TakeWhile(x => x != "X").Count();
                    //var headerY = header.Split(';').TakeWhile(x => x != "Y").Count();

                    var line1 = WorkerReader.ReadLine();

                    var sw1 = Stopwatch.StartNew();

                    WorkerReaderLineCount = 0;

                    var HasLine = !string.IsNullOrEmpty(line1);

                    // URI malformed at decodeURIComponent

                    while (HasLine)
                    {
                        WorkerReaderLineCount++;

                        //await Task.Delay(33);

                        //Console.WriteLine("520 " + new { WorkerReaderLineCount });

                        var x = new CSVHeaderLookup { header = header, line = line1 }["X"];
                        var y = new CSVHeaderLookup { header = header, line = line1 }["Y"];

                        //Console.WriteLine("525 " + new { WorkerReaderLineCount });

                        // hop supports strings for now..
                        var lat = "" + (double)LEST97.lest_function_vba.lest_geo(x, y, 0);
                        var lng = "" + (double)LEST97.lest_function_vba.lest_geo(x, y, 1);

                        //Console.WriteLine("531 " + new { WorkerReaderLineCount });

                        #region progress
                        //if (WorkerReaderLineCount % 500 == 1)
                        {
                            Console.Title = WorkerReaderLineCount + " in " + sw1.ElapsedMilliseconds + "ms " + new { WorkerReader.BaseStream.Position, WorkerReader.BaseStream.Length };
                        }


                        if (WorkerReaderLineCount % 300 == 1)
                        {
                            new { }.With(
                                async delegate
                                {
                                    { fixup: await Task.CompletedTask; }

                                    var lng1 = lng;
                                    var lat1 = lat;
                                    var title1 = line1;

                                    var output = "working... " + WorkerReaderLineCount + " in " + sw1.ElapsedMilliseconds + "ms " + new { x, y, lat, lng };
                                    await default(HopToUI);
                                    WorkerUI.innerText = output;

                                    Console.WriteLine(new { lng1, lat1 });

                                    var position = new
                                             {
                                                 // InvalidValueError: setPosition: not a LatLng or LatLngLiteral: in property lat: not a number

                                                 lat = Convert.ToDouble(lat1),
                                                 lng = Convert.ToDouble(lng1)
                                             };

                                    Console.WriteLine(new { position });

                                    // http://stackoverflow.com/questions/20044308/google-maps-api-3-show-hide-markers-depending-on-zoom-level
                                    // http://stackoverflow.com/questions/19304574/center-set-zoom-of-map-to-cover-all-markers-visible-markers

                                    var marker = new google.maps.Marker(
                                         new
                                         {
                                             // https://developers.google.com/maps/documentation/javascript/examples/marker-symbol-predefined
                                             // https://developers.google.com/maps/documentation/javascript/markers
                                             //icon = new marker().src,

                                             // can we have two zoom levels?
                                             icon = new markersmall().src,

                                             position,
                                             //label = "T",

                                             title = title1,

                                             map
                                         }
                                      );

                                    // http://stackoverflow.com/questions/8198635/change-marker-icon-on-mouseover-google-maps-v3
                                    AddZoomAwareMarker(map, marker, new markersmall().src, new markerxsmall().src);


                                    while (await marker.async.onmouseover)
                                    {

                                        Console.Title = title1;
                                    }

                                }
                            );



                            //await Task.Delay(300);
                        }
                        #endregion

                        //Console.WriteLine("606 " + new { WorkerReaderLineCount });

                        //await Task.Delay(3);

                        line1 = WorkerReader.ReadLine();
                        HasLine = !string.IsNullOrEmpty(line1);

                        //Console.WriteLine("611 " + new { WorkerReaderLineCount });
                    }
                    #endregion

                    Console.WriteLine("done at " + new { WorkerReaderLineCount });

                    // done... { ManagedThreadId = 1, output = done { ManagedThreadId = 10, WorkerReaderLineCount = 153411, ElapsedMilliseconds = 99979 } }
                    // done... { ManagedThreadId = 1, output = done { ManagedThreadId = 10, WorkerReaderLineCount = 153411, ElapsedMilliseconds = 260865 } }
                    {

                        var output = "done " + new { Thread.CurrentThread.ManagedThreadId, WorkerReaderLineCount, sw1.ElapsedMilliseconds };
                        await default(HopToUI);
                        WorkerUI.innerText = "done... " + new { Thread.CurrentThread.ManagedThreadId, output };

                        // done... { ManagedThreadId = 1, output = done { ManagedThreadId = 10, WorkerReaderLineCount = 153411 } }
                    }




                }
            );

        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // allow to be called from historic function
            service = this;


            new IStyle(IHTMLElement.HTMLElementEnum.head).display = IStyle.DisplayEnum.block;
            new IStyle(IHTMLElement.HTMLElementEnum.title).display = IStyle.DisplayEnum.block;

            // UI Automation

            // can we show svg as background?
            // we already had multimouse drawing dint we?

            document.onmousemove +=
                e =>
                {
                    // update the curent shadow element



                    // contentText wont work on non pseudo?
                    pseudo[index % 2].contentText =
                        new
                    {
                        random,
                        index,
                        x = e.CursorX,
                        y = e.CursorY,
                        z = window.history.length
                    }
                    .ToString();

                    pseudo[index % 2].style.SetLocation(
                      e.CursorX,
                      e.CursorY
                    );

                    pseudo[index % 2].style.position = IStyle.PositionEnum.@fixed;
                    pseudo[index % 2].style.color = "blue";

                    //current.memory
                };

            //document.documentElement.click();


            // do not resume if browser has historic data.
            if (window.history.length != 1)
                // cant we use console as body?
                //body.innerText = "will not try to resume, as there is history. start a new clean tab insead.";
                document.title = "will not try to resume, as there is history. start a new clean tab insead.";
            else

                // resume only works if a new tab is spawned without any history!
                Resume(
                    e =>
                    {
                        if (!e.Any())
                            return;

                        if (!window.confirm("resume state of " + e.Count()))
                        {
                            ForgetAll();
                            return;
                        }

                        replay = e.ToList();

                        foreach (var item in e)
                        {
                            // lets start to replay.
                            // ?

                            document.body.click();

                            break;
                        }
                        // fake
                        //Console.WriteLine("click " + new { e.x, e.y });

                    }
                );

            document.onclick +=
                e =>
                {

                    // did jsc do background compilation and update our snapshot
                    // and add the new version into AB testing view by jsc zombie server?
                    // or did I have to hit F5 again?

                    // can we flip the new shadow dom element into view?

                    // Error	2	No overload for method 'pushState' takes 2 arguments	X:\jsc.svn\examples\javascript\future\HistoricSnapshotMashup\HistoricSnapshotMashup\Application.cs	84	21	HistoricSnapshotMashup

                    //HistoryExtensions.pushState(
                    //    h: window.history,

                    long x = e.CursorX;
                    long y = e.CursorY;

                    if (replay.Any())
                    {
                        x = replay[0].x;
                        y = replay[0].y;
                    }

                    window.history.pushState(
                        state: new
                    {
                        index,

                        x,
                        y
                    },


                        yield: async scope =>
                        {
                            if (replay.Any())
                            {
                                service.data.Add(replay[0]);
                                replay.RemoveAt(0);
                            }
                            else
                            {
                                // prepare new data to be saved
                                service.data.Add(
                                    new Data.HistoricsTheEntryRow
                                {
                                    x = scope.state.x,
                                    y = scope.state.y,
                                    index = scope.state.index,
                                }
                                );

                            }

                            // make it stale
                            pseudo[index % 2].style.color = "gray";

                            Console.WriteLine("enter scope " + new { index });
                            index++;
                            // show without mouse hover!
                            pseudo[index % 2].style.color = "blue";

                            //pseudo[index % 2].contentText = new { index, z = window.history.length }.ToString();
                            pseudo[index % 2].contentText =
                                 new
                            {
                                service.random,
                                index,
                                x = scope.state.x,
                                y = scope.state.y,
                                z = window.history.length
                            }
                                     .ToString();

                            var pre = new IHTMLPre {
                                new
                                {
                                    service.random,
                                    index,
                                    x = scope.state.x,
                                    y = scope.state.y,
                                    z = window.history.length
                                }
                            }.AttachToDocument();


                            pre.style.SetLocation(
                                (int)scope.state.x,
                                (int)scope.state.y
                              );

                            pseudo[index % 2].style.SetLocation(
                                        (int)scope.state.x,
                                        (int)scope.state.y
                                      );


                            pseudo[index % 2].style.backgroundColor = "yellow";
                            await Task.Delay(300);
                            pseudo[index % 2].style.backgroundColor = "transparent";

                            // save it! bit late tho
                            await service.InsertNewHistoric();




                            await scope;

                            pre.Orphanize();

                            // so. what state did we remove?
                            var forget = service.data.Last();
                            // pop. does jsc tier split support stack?
                            service.data.RemoveAt(service.data.Count - 1);
                            service.Forget(forget);

                            Console.WriteLine("exit scope " + new { index });

                            // this is from the future then? click forward to reactivate?
                            pseudo[index % 2].style.color = "red";
                            // undo???
                            // exclusive?
                            index--;

                            pseudo[index % 2].contentText = new { index, z = window.history.length }.ToString();

                            // show without mouse hover!
                            pseudo[index % 2].style.color = "blue";
                            pseudo[index % 2].style.transition = "";
                            pseudo[index % 2].style.backgroundColor = "cyan";
                            await Task.Delay(300);
                            pseudo[index % 2].style.backgroundColor = "transparent";
                        }
                    );



                };
        }
        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20160101/ovrwindwheelndk

        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151001/udppenpressure


        // net use
        // OK           R:        \\192.168.1.12\x$         Microsoft Windows Network


        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151003/ovrwindwheelactivity
        // subst b: s:\jsc.svn\examples\javascript\chrome\apps\ChromeAppWindowUDPPointerLock\ChromeAppWindowUDPPointerLock\bin\Debug\staging\ChromeAppWindowUDPPointerLock.Application\web

        // X:\jsc.svn\examples\javascript\chrome\apps\ChromeAppWindowUDPPointerLock\ChromeAppWindowUDPPointerLock\bin\Debug\staging\ChromeAppWindowUDPPointerLock.Application\web

        // logoff logon?
        // net start LanmanServer

        //        ---------------------------
        //Restoring Network Connections
        //---------------------------
        //An error occurred while reconnecting R: to
        //\\192.168.1.12\x$
        //Microsoft Windows Network: The specified network name is no longer available.


        //This connection has not been restored.
        //---------------------------
        //OK   
        //---------------------------



        //        ---------------------------
        //Restoring Network Connections
        //---------------------------
        //An error occurred while reconnecting R: to
        //\\192.168.1.12\x$
        //Microsoft Windows Network: Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.


        //This connection has not been restored.
        //---------------------------
        //OK   



        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // how are we to make this into a chrome app?
            // "X:\jsc.svn\examples\javascript\chrome\apps\ChomeAlphaAppWindow\ChomeAlphaAppWindow.sln"

            // since now jsc shows ssl support
            // how about packaging the view-source for chrome too?

            // nuget, add chrome.

            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");

                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "Launched2");

                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: null
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion


            // can we also test the shadow DOM ?
            // how does it work again?


            // now we have to update our alpha window/server window
            // to be in the correct context.

            // what about property window
            // back in the vb days we made one.
            // time to do one?



            #region UDPClipboardSend
            Action<string> UDPClipboardSend = async message =>
            {
                var n = await chrome.socket.getNetworkList();

                new IHTMLPre { new { n.Length } }.AttachToDocument();

                // LINQ and async wont mix for 2012?

                //foreach (var item in n.Where(x => x.prefixLength == 24))
                foreach (var item in n) if (item.prefixLength == 24)
                    {
                        new IHTMLPre { new { item.prefixLength, item.name, item.address } }.AttachToDocument();

                        //{ prefixLength = 64, name = {AE3B881D-488F-4C3A-93F8-7DA0D65B9300}, address = fe80::fc45:cae9:46ca:7b0f }
                        //about to bind... { port = 29129 }
                        //about to send... { Length = 0 }
                        //sent: -2
                        //{ prefixLength = 24, name = {AE3B881D-488F-4C3A-93F8-7DA0D65B9300}, address = 192.168.1.12 }
                        //about to bind... { port = 25162 }
                        //about to send... { Length = 0 }
                        //sent: 0


                        // X:\jsc.svn\examples\merge\TestDetectOpenFiles\TestDetectOpenFiles\Program.cs
                        // X:\jsc.svn\examples\javascript\chrome\apps\MulticastListenExperiment\MulticastListenExperiment\Application.cs

                        // https://code.google.com/p/chromium/issues/detail?id=455352

                        // X:\jsc.svn\examples\merge\TestDetectOpenFiles\TestDetectOpenFiles\Program.cs

                        // bind?

                        var data = Encoding.UTF8.GetBytes(message);	   //creates a variable b of type byte

                        // http://stackoverflow.com/questions/13691119/chrome-packaged-app-udp-sockets-not-working
                        // http://www.chinabtp.com/how-to-do-udp-broadcast-using-chrome-sockets-udp-api/

                        // chrome likes 0 too.
                        var port = new Random().Next(16000, 40000);
                        //var port = 0;
                        // 
                        //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();

                        // where is bind async?
                        var socket = new UdpClient();
                        socket.Client.Bind(

                            //new IPEndPoint(IPAddress.Any, port: 40000)
                            new IPEndPoint(IPAddress.Parse(item.address), port)
                        );


                        //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                        // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                        var s = await socket.SendAsync(
                            data,
                            data.Length,
                            hostname: "239.1.2.3",
                            port: 49814
                        );

                        //new IHTMLPre { "sent: " + s }.AttachToDocument();


                        //socket.ReceiveAsync
                        //socket.Close();

                        //new IHTMLPre { $"sent: {s}" }.AttachToDocument();

                        // android cannot see it. why? because it needs to know which NIC to use.

                    }
            };
            #endregion



            new IHTMLButton { "ready1" }.AttachToDocument().onclick +=
                //async
                delegate
                {
                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150701

                    new MyShadow { }.AttachTo(Native.shadow);

                    #region CaptureMouse
                    {
                        // shadow will select div from chldren
                        var div = new IHTMLDiv { }.AttachTo(Native.document.documentElement);

                        new IHTMLPre { "drag me via CaptureMouse" }.AttachTo(div);
                        var xy = new IHTMLPre { "{}" }.AttachTo(div);

                        div.css.style.backgroundColor = "transparent";
                        div.css.style.transition = "background 500ms linear";

                        div.css.active.style.backgroundColor = "yellow";

                        Native.document.documentElement.style.cursor = IStyle.CursorEnum.move;

                        div.css.hover.style.backgroundColor = "cyan";

                        div.onmousemove +=
                            e =>
                            {
                                // we could tilt the svg cursor
                                // like we do on heat zeeker:D


                                //Native.document.title = new { e.CursorX, e.CursorY }.ToString();
                                xy.innerText = new { e.CursorX, e.CursorY }.ToString();

                            };

                        div.onmousedown +=
                            async e =>
                            {
                                e.CaptureMouse();

                                await div.async.onmouseup;
                            };
                    }
                    #endregion

                    {
                        // shadow will select div from chldren
                        var div = new IHTMLDiv { }.AttachTo(Native.document.documentElement);

                        new IHTMLPre { "click to  requestPointerLock, double click to stop" }.AttachTo(div);
                        var wasd = new IHTMLPre { "{}" }.AttachTo(div);
                        var xy = new IHTMLPre { "{}" }.AttachTo(div);

                        div.css.style.backgroundColor = "transparent";
                        div.css.style.transition = "background 500ms linear";

                        div.css.active.style.backgroundColor = "yellow";

                        Native.document.documentElement.style.cursor = IStyle.CursorEnum.move;

                        div.css.hover.style.backgroundColor = "cyan";





                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704

                        var keys_ad = 0;
                        var keys_ws = 0;
                        var keys_c = 0;

                        var mousebutton = 0;
                        var mousewheel = 0;

                        var x = 0;
                        var y = 0;


                        // what about 255.255.255.255 ?
                        chrome.socket.getNetworkList().ContinueWithResult(
                             async n =>
                             {
                                 // which networks should we notify of our data?

                                 //new IHTMLPre { new { n.Length } }.AttachToDocument();

                                 foreach (var item in n)
                                 {
                                     // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                                     // skip ipv6
                                     if (item.address.Contains(":"))
                                         continue;

                                     //if (item.prefixLength != 4)
                                     //    continue;


                                     #region other
                                     new IHTMLButton { "send onmouseup " + item.address }.AttachTo(div).With(
                                         async refresh =>
                                         {
                                             refresh.style.display = IStyle.DisplayEnum.block;

                                             // experimental until ref count 33?
                                             await refresh.async.onmousedown;

                                             refresh.disabled = true;

                                             while (await div.async.onmouseup)
                                             {


                                                 #region xml

                                                 var nmessage = x + ":" + y;
                                                 var Host = "";
                                                 var PublicPort = "";

                                                 var message =
                                                     new XElement("string",
                                                         new XAttribute("c", "" + 1),
                                                         new XAttribute("n", nmessage),
                                                         "Visit me at " + Host + ":" + PublicPort
                                                     ).ToString();

                                                 #endregion

                                                 var data = Encoding.UTF8.GetBytes(message);	   //creates a variable b of type byte

                                                 var port = new Random().Next(16000, 40000);

                                                 //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();
                                                 // Z:\jsc.svn\examples\javascript\chrome\hybrid\HybridHopToUDPChromeApp\Application.cs
                                                 // where is bind async?
                                                 var socket = new UdpClient();
                                                 socket.Client.Bind(

                                                     //new IPEndPoint(IPAddress.Any, port: 40000)
                                                     new IPEndPoint(IPAddress.Parse(item.address), port)
                                                 );


                                                 //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                                                 // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                                                 var s = await socket.SendAsync(
                                                     data,
                                                     data.Length,
                                                     hostname: "239.1.2.3",
                                                     port: 40804
                                                 );

                                                 socket.Close();

                                             }
                                         }
                                     );

                                     new IHTMLButton { "send onmousemove " + item.address }.AttachTo(div).With(
                                       async refresh =>
                                       {
                                           refresh.style.display = IStyle.DisplayEnum.block;

                                           // experimental until ref count 33?
                                           await refresh.async.onmousedown;

                                           refresh.disabled = true;

                                           var port = new Random().Next(16000, 40000);

                                           //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();

                                           // where is bind async?
                                           var socket = new UdpClient();
                                           socket.Client.Bind(

                                               //new IPEndPoint(IPAddress.Any, port: 40000)
                                               new IPEndPoint(IPAddress.Parse(item.address), port)
                                           );


                                           while (await div.async.onmousemove)
                                           {
                                               var nmessage = x + ":" + y;


                                               var data = Encoding.UTF8.GetBytes(nmessage);	   //creates a variable b of type byte



                                               //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                                               // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                                               var s = await socket.SendAsync(
                                                   data,
                                                   data.Length,
                                                   hostname: "239.1.2.3",
                                                   port: 41814
                                               );

                                               //socket.Close();

                                           }
                                       }
                                   );
                                     #endregion


                                     new IHTMLButton { "send onframe " + item.address }.AttachTo(div).With(
                                          async refresh =>
                                          {
                                              refresh.style.color = "blue";

                                              refresh.style.display = IStyle.DisplayEnum.block;

                                              // experimental until ref count 33?
                                              await refresh.async.onmousedown;

                                              UDPClipboardSend("mousedown...");


                                              refresh.disabled = true;

                                              var port = new Random().Next(16000, 40000);

                                              //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();

                                              // where is bind async?
                                              var socket = new UdpClient();
                                              socket.Client.Bind(

                                                  //new IPEndPoint(IPAddress.Any, port: 40000)
                                                  new IPEndPoint(IPAddress.Parse(item.address), port)
                                              );


                                              // this will eat too much memory?
                                              //div.ownerDocument.defaultView.onframe +=
                                              div.onframe +=
                                                  delegate
                                                  {
                                                      // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                                                      var nmessage = x + ":" + y + ":" + keys_ad + ":" + keys_ws + ":" + keys_c + ":" + mousebutton + ":" + mousewheel;

                                                      UDPClipboardSend(nmessage);

                                                      var data = Encoding.UTF8.GetBytes(nmessage);	   //creates a variable b of type byte



                                                      //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();


                                                      // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                                                      socket.Send(
                                                          data,
                                                          data.Length,
                                                          hostname: "239.1.2.3",
                                                          port: 41814
                                                      );

                                                      // android doesnt get it?
                                                      // restart router?
                                                      // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20160101/ovrwindwheelndkg
                                                      // why wont it make it?
                                                  };

                                              return;

                                              //while (await Native.window.async.onframe)
                                              //while (await div.async.onframe)
                                              while (await div.ownerDocument.defaultView.async.onframe)
                                              {
                                                  var nmessage = x + ":" + y + ":" + keys_ad + ":" + keys_ws + ":" + keys_c + ":" + mousebutton + ":" + mousewheel;


                                                  var data = Encoding.UTF8.GetBytes(nmessage);	   //creates a variable b of type byte



                                                  //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                                                  // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                                                  var s = await socket.SendAsync(
                                                      data,
                                                      data.Length,
                                                      hostname: "239.1.2.3",
                                                      port: 41814
                                                  );

                                                  //socket.Close();

                                              }
                                          }
                                      );
                                 }
                             }
                        );


                        div.tabIndex = 1;

                        div.onkeydown +=
                             async e =>
                             {
                                 var A = e.KeyCode == 65;
                                 var D = e.KeyCode == 68;

                                 if (A || D)
                                 {
                                     keys_ad = e.KeyCode;

                                     //Native.document.title = new { e.CursorX, e.CursorY }.ToString();
                                     wasd.innerText = new { e.KeyCode, ad = keys_ad, ws = keys_ws }.ToString();

                                     while ((await div.async.onkeyup).KeyCode != e.KeyCode) ;

                                     //var ee = await div.async.onkeyup;

                                     keys_ad = 0;

                                     wasd.innerText = new { e.KeyCode, ad = keys_ad, ws = keys_ws }.ToString();

                                     return;
                                 }

                                 // CS
                                 // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                                 if (e.KeyCode == 67)
                                 {
                                     keys_c = e.KeyCode;

                                     //Native.document.title = new { e.CursorX, e.CursorY }.ToString();
                                     wasd.innerText = new { e.KeyCode, keys_ad, keys_ws, keys_c }.ToString();

                                     while ((await div.async.onkeyup).KeyCode != e.KeyCode) ;

                                     //var ee = await div.async.onkeyup;

                                     keys_c = 0;

                                     wasd.innerText = new { e.KeyCode, keys_ad, keys_ws, keys_c }.ToString();

                                     return;
                                 }

                                 {
                                     keys_ws = e.KeyCode;

                                     //Native.document.title = new { e.CursorX, e.CursorY }.ToString();
                                     wasd.innerText = new { e.KeyCode, ad = keys_ad, ws = keys_ws }.ToString();

                                     while ((await div.async.onkeyup).KeyCode != e.KeyCode) ;
                                     //var ee = await div.async.onkeyup;

                                     keys_ws = 0;

                                     wasd.innerText = new { e.KeyCode, ad = keys_ad, ws = keys_ws }.ToString();
                                 }
                             };


                        div.onmousewheel += e =>
                            {
                                // since we are a chrome app. is chrome sending us wheel delta too?
                                mousewheel += e.WheelDirection;
                            };

                        div.onmousemove +=
                            e =>
                            {
                                // we could tilt the svg cursor
                                // like we do on heat zeeker:D

                                x += e.movementX;
                                y += e.movementY;


                                //Native.document.title = new { e.CursorX, e.CursorY }.ToString();
                                xy.innerText = new { x, y }.ToString();

                            };

                        div.onmousedown +=
                            async e =>
                            {
                                // wont work for RemoteApp users tho

                                mousebutton = (int)e.MouseButton;

                                // await ?
                                div.requestPointerLock();
                                //e.CaptureMouse();

                                var ee = await div.async.onmouseup;
                                //var ee = await div.async.ondblclick;

                                if (ee.MouseButton == IEvent.MouseButtonEnum.Right)
                                    Native.document.exitPointerLock();

                                mousebutton = 0;

                            };
                    }


                };

        }
 /// <summary>
 /// This is a javascript application.
 /// </summary>
 /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
 public Application(IApp page)
 {
     var s = new IHTMLPre {innerText = 1234567L.ToCustomString()};
     s.AttachTo(page.body);
 }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IDefaultPage page)
        {
            Native.Document.title = "DCIM Thumbnails";

            // see also. http://en.wikipedia.org/wiki/Design_rule_for_Camera_File_system

            ystring ydirectory = path =>
            {

            };

            var container = new IHTMLCenter().AttachToDocument();

            ystring yfile = path =>
            {
                new IHTMLDiv { innerText = path }.With(
                    div =>
                    {
                        if (path.ToLower().EndsWith(".jpg"))
                        {
                            div.innerText = "";

                            div.AttachTo(container);
                            // hide path

                            //new IHTMLBreak().AttachTo(div);
                            div.style.display = IStyle.DisplayEnum.inline_block;

                            new IHTMLImage { }.AttachTo(div).With(
                                img =>
                                {
                                    // portrait mode only!

                                    div.style.color = JSColor.Red;
                                    img.src = "/thumb/" + path;

                                    #region onload +=
                                    img.InvokeOnComplete(
                                        delegate
                                        {
                                            div.style.color = JSColor.Green;

                                            IHTMLPre p = null;

                                            img.onclick += delegate
                                            {
                                                if (p == null)
                                                {
                                                    img.src = "/io/" + path;
                                                    img.style.width = "100%";
                                                    div.style.display = IStyle.DisplayEnum.block;

                                                     p = new IHTMLPre { }.AttachTo(div);
                                                    service.GetEXIF("/io/" + path,
                                                        x =>
                                                        {
                                                            p.innerText = x;
                                                        }
                                                    );

                                               
                                                }
                                                else
                                                {

                                                    p.Orphanize();
                                                    p = null;
                                                    img.src = "/thumb/" + path;
                                                    img.style.width = "";
                                                }

                                            };
                                        }
                                    );
                                    #endregion



                                }
                            );
                        }
                    }
                );
            };

            var skip = 0;
            var take = 30;



            new IHTMLButton { innerText = "more" }.AttachToDocument().With(
                more =>
                {
                    Action MoveNext = delegate
                    {
                        more.disabled = true;
                        more.innerText = "checking for more...";

                        ystring done = delegate
                        {
                            more.innerText = "more";
                            more.disabled = false;

                        };

                        service.File_list("",
                            ydirectory: ydirectory,
                            yfile: yfile,
                            sskip: skip.ToString(),
                            stake: take.ToString(),
                            done: done
                        );

                        skip += take;

                    };


                    MoveNext();

                    more.onclick += delegate
                    {
                        MoveNext();
                    };



                    Native.Window.onscroll +=
                          e =>
                          {

                              Native.Document.body.With(
                                  body =>
                                  {
                                      if (more.disabled)
                                          return;

                                      if (body.scrollHeight - 1 <= Native.Window.Height + body.scrollTop)
                                      {
                                          MoveNext();
                                      }

                                  }
                            );

                          };
                }
            );



        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            var dragme = new IHTMLPre { "drag me" }.AttachToDocument().With(
                async e =>
                {
                    e.css.hover.style.backgroundColor = "yellow";
                    e.css.active.style.backgroundColor = "cyan";

                    do
                    {
                        var mousedown = await e.async.onmousedown;

                        //var release = e.CaptureMouse();
                        e.style.borderLeft = "1em solid red";

                        // https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/10773216-while-var-u
                        #region  while (var u = await e.async.onmousemove)
                        var u = default(IEvent);
                        while (u = await e.async.oncapturedmousemove)
                        #endregion
                        {

                            e.innerText = new { u.OffsetX, u.OffsetY }.ToString();
                        }

                        // done

                        //release();
                        e.style.borderLeft = "0em solid yellow";

                    }
                    while (true);
                }
            );


            new CanvasRenderingContext2D(200, 200).With(
               async c =>
               {
                   var e = c.canvas;

                   e.AttachToDocument();

                   //e.style.backgroundColor = "blue";
                   //e.css.hover.style.backgroundColor = "yellow";
                   //e.css.active.style.backgroundColor = "cyan";

                   e.style.borderRight = "blue 1em solid";
                   e.css.hover.style.borderRight = "yellow 1em solid";
                   e.css.active.style.borderRight = "cyan 1em solid";

                   do
                   {
                       var mousedown = await e.async.onmousedown;

                       //var release = e.CaptureMouse();
                       e.style.borderLeft = "1em solid red";

                       // https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/10773216-while-var-u
                       #region  while (var u = await e.async.onmousemove)
                       var u = default(IEvent);
                       while (u = await e.async.oncapturedmousemove)
                       #endregion
                       {



                           dragme.innerText = new { u.OffsetX, u.OffsetY }.ToString();
                       }

                       // done

                       //release();
                       e.style.borderLeft = "0em solid yellow";

                   }
                   while (true);
               }
           );

        }
        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150807/ovroculus360photosndk

        // X:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeEquirectangularPanorama\ChromeEquirectangularPanorama\bin\Debug\staging\ChromeEquirectangularPanorama.Application\web
        // subst a: r:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeEquirectangularPanorama\ChromeEquirectangularPanorama\bin\Debug\staging\ChromeEquirectangularPanorama.Application\web
        // subst a: s:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeEquirectangularPanorama\ChromeEquirectangularPanorama\bin\Debug\staging\ChromeEquirectangularPanorama.Application\web
        // subst b: s:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeEquirectangularPanorama\ChromeEquirectangularPanorama\bin\Debug\staging\ChromeEquirectangularPanorama.Application\web

        // 237ms UdpClient.Client.vBind { ipString = 0.0.0.0, Port = 49000, bind = 0 }

        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // https://www.shadertoy.com/view/lsSGRz




            // "X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPFloats\ChromeUDPFloats\Application.cs"


            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");

                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "ChromeUDPSendAsync");

                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: null
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion

            //02000047 ChromeEquirectangularPanorama.Application+ctor>b__7>d__1d+<MoveNext>0600001d
            //script: error JSC1000: *** stack is empty, invalid pop?
            //script: error JSC1000: error at ChromeEquirectangularPanorama.Application+ctor>b__7>d__1d+<MoveNext>0600001d.<00c3> ldloca.s.try,
            // assembly: W:\ChromeEquirectangularPanorama.Application.exe
            // type: ChromeEquirectangularPanorama.Application+ctor>b__7>d__1d+<MoveNext>0600001d, ChromeEquirectangularPanorama.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
            // offset: 0x003e
            //  method:Int32 <00c3> ldloca.s.try(<MoveNext>0600001d, ctor>b__7>d__1d ByRef, System.Runtime.CompilerServices.TaskAwaiter`1[chrome.NetworkInterface[]] ByRef, System.Runtime.CompilerServices.TaskAwaiter`1[chrome.NetworkInterface[]] ByRef)
            //*** Compiler cannot continue... press enter to quit.






            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150721/udp




            var window = Native.window;

            // Error creating WebGL context.

            #region webgl
            //var fov = 70.0;
            var fov = 90.0;

            var camera = new THREE.PerspectiveCamera(fov,
                window.aspect, 1, 1100);
            var target = new THREE.Vector3(0, 0, 0);

            //(camera as dynamic).target = target;

            var scene = new THREE.Scene();

            var meshmaterial =
                new THREE.MeshBasicMaterial(new
                {
                    map = THREE.ImageUtils.loadTexture(
                        new ChromeEquirectangularPanorama.HTML.Images.FromAssets._2294472375_24a3b8ef46_o().src
                        //new WebGLEquirectangularPanorama.HTML.Images.FromAssets.PANO_20130616_222058().src
                        //new WebGLEquirectangularPanorama.HTML.Images.FromAssets.PANO_20121225_210448().src

                        )
                });

            var mesh = new THREE.Mesh(new THREE.SphereGeometry(500, 60, 40),
                meshmaterial
                );

            mesh.scale.x = -1;
            scene.add(mesh);

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.Width, window.Height);

            renderer.domElement.AttachToDocument();

            //renderer.domElement.style.position = IStyle.PositionEnum.absolute;
            renderer.domElement.style.SetLocation(0, 0);

            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;


            #region onresize
            Native.window.onresize +=
                delegate
                {
                    camera.aspect = Native.window.aspect;
                    camera.updateProjectionMatrix();

                    renderer.setSize(Native.window.Width, Native.window.Height);
                };
            #endregion


            Native.document.body.onmousewheel +=
                e =>
                {
                    fov -= e.WheelDirection * 5.0;
                    camera.projectionMatrix.makePerspective(fov,
                        (double)window.Width / window.Height, 1, 1100);
                };

            var gearvr_x = 0f;
            // left to right
            var gearvr_y = 0f;
            var gearvr_z = 0f;


            // set by?
            var gearvr_filename = "";

            var lon = 90.0;
            var lat = 0.0;
            var phi = 0.0;
            var theta = 0.0;

            Native.window.onframe +=
                delegate
                {
                    if (Native.document.pointerLockElement == Native.document.body)
                        lon += 0.00;
                    else
                        lon += 0.01;

                    lat = Math.Max(-85, Math.Min(85, lat));



                    //Native.document.title = new { lon, lat }.ToString();

                    // http://www.gamedev.net/topic/626401-quaternion-from-latitude-and-longitude/
                    //void xyz_to_latlon(const double x, const double y, const double z, double &lat, double &lon)
                    //{
                    //    double theta = pi + atan2(z, x);
                    //    double phi = acos(-y);

                    //    lat = phi/pi*180.0 - 90.0;
                    //    lon = theta/(2*pi)*360.0 - 180.0;
                    //}


                    //double vrtheta = Math.PI + Math.Atan2(gearvr_z, gearvr_x);
                    //double vrphi = Math.Acos(-gearvr_y);

                    //var vrlat = phi / Math.PI * 180.0 - 90.0;
                    //var vrlon = theta / (2 * Math.PI) * 360.0 - 180.0;


                    // 	const ovrMatrix4f centerEyeRotation = ovrMatrix4f_CreateFromQuaternion( &tracking->HeadPose.Pose.Orientation );

                    // http://stackoverflow.com/questions/11665562/three-js-how-to-use-quaternion-to-rotate-camera

                    phi = THREE.Math.degToRad(90 - lat) - Math.Sign(gearvr_x) * (gearvr_x * gearvr_x) * Math.PI;
                    theta = THREE.Math.degToRad(lon) - Math.Sign(gearvr_y) * (gearvr_y * gearvr_y) * Math.PI;

                    target.x = 500 * Math.Sin(phi) * Math.Cos(theta);
                    target.y = 500 * Math.Cos(phi);
                    target.z = 500 * Math.Sin(phi) * Math.Sin(theta);

                    camera.lookAt(target);

                    renderer.render(scene, camera);

                };
            #endregion



            // http://blog.thematicmapping.org/2013/10/terrain-visualization-with-threejs-and.html

            #region camera rotation
            Native.document.body.onmousemove +=
                e =>
                {
                    e.preventDefault();

                    if (Native.document.pointerLockElement == Native.document.body)
                    {
                        lon += e.movementX * 0.1;
                        lat -= e.movementY * 0.1;

                        //Console.WriteLine(new { lon, lat, e.movementX, e.movementY });
                    }
                };


            Native.document.body.onmouseup +=
              e =>
              {
                  if (e.MouseButton == IEvent.MouseButtonEnum.Right)
                      Native.document.exitPointerLock();

                  //drag = false;
                  e.preventDefault();
              };

            renderer.domElement.onmousedown +=
                async e =>
                {
                    //e.CaptureMouse();

                    //drag = true;
                    e.preventDefault();
                    Native.document.body.requestPointerLock();

                    //await renderer.domElement.async.onmousedown;

                    //Native.document.exitPointerLock();
                };


            //Native.document.body.oncontextmenu +=
            //    delegate
            //    {
            //        Native.document.exitPointerLock();

            //    };
            //Native.document.body.ondblclick +=
            //    e =>
            //    {
            //        e.preventDefault();

            //        Console.WriteLine("requestPointerLock");
            //    };

            #endregion


            var file64 = "";
            var file = new MemoryStream();
            var segment0 = new byte[0];

            #region toolbar
            var toolbar = new IHTMLDiv { }.AttachToDocument();

            Native.body.style.margin = "0em";
            Native.body.style.padding = "0em";
            Native.document.documentElement.style.margin = "0em";
            Native.document.documentElement.style.padding = "0em";

            new IStyle(toolbar)
            {
                position = IStyle.PositionEnum.absolute,

                padding = "1em",

                top = "0em",
                right = "0em",
                bottom = "0em",

                color = "yellow",

                //overflow = IStyle.OverflowEnum.scroll
                overflow = IStyle.OverflowEnum.auto
            };

            toolbar.css[IHTMLElement.HTMLElementEnum.img].style.cursor = IStyle.CursorEnum.pointer;

            toolbar.css[IHTMLElement.HTMLElementEnum.img].style.display = IStyle.DisplayEnum.block;
            //toolbar.css.children.style.display = IStyle.DisplayEnum.block;

            new IHTMLButton { "update pending... update available. click to reload.." }.AttachTo(toolbar).onclick += delegate
            {
                // can we get an udp signal from the compiler when the app is out of date, when the update is pending?
                chrome.runtime.reload();
            };



            //var n = await chrome.socket.getNetworkList();
            ////var n24 = n.Where(x => x.prefixLength == 24).ToArray();



            #region UDPClipboardSend
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20160103/x360videoui
            // Z:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeEquirectangularPanorama\ChromeEquirectangularPanorama\Application.cs
            Action<byte[]> UDPClipboardSend = async data =>
            {
                var n = await chrome.socket.getNetworkList();

                new IHTMLPre { new { n.Length } }.AttachToDocument();

                // LINQ and async wont mix for 2012?

                //foreach (var item in n.Where(x => x.prefixLength == 24))
                foreach (var item in n) if (item.prefixLength == 24)
                    {
                        new IHTMLPre { new { item.prefixLength, item.name, item.address } }.AttachToDocument();

                        //{ prefixLength = 64, name = {AE3B881D-488F-4C3A-93F8-7DA0D65B9300}, address = fe80::fc45:cae9:46ca:7b0f }
                        //about to bind... { port = 29129 }
                        //about to send... { Length = 0 }
                        //sent: -2
                        //{ prefixLength = 24, name = {AE3B881D-488F-4C3A-93F8-7DA0D65B9300}, address = 192.168.1.12 }
                        //about to bind... { port = 25162 }
                        //about to send... { Length = 0 }
                        //sent: 0


                        // X:\jsc.svn\examples\merge\TestDetectOpenFiles\TestDetectOpenFiles\Program.cs
                        // X:\jsc.svn\examples\javascript\chrome\apps\MulticastListenExperiment\MulticastListenExperiment\Application.cs

                        // https://code.google.com/p/chromium/issues/detail?id=455352

                        // X:\jsc.svn\examples\merge\TestDetectOpenFiles\TestDetectOpenFiles\Program.cs

                        // bind?

                        //var data = Encoding.UTF8.GetBytes(message);	   //creates a variable b of type byte

                        // http://stackoverflow.com/questions/13691119/chrome-packaged-app-udp-sockets-not-working
                        // http://www.chinabtp.com/how-to-do-udp-broadcast-using-chrome-sockets-udp-api/

                        // chrome likes 0 too.
                        var port = new Random().Next(16000, 40000);
                        //var port = 0;
                        // 
                        //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();

                        // where is bind async?
                        var socket = new UdpClient();
                        socket.Client.Bind(

                            //new IPEndPoint(IPAddress.Any, port: 40000)
                            new IPEndPoint(IPAddress.Parse(item.address), port)
                        );


                        //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                        // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                        var s = await socket.SendAsync(
                            data,
                            data.Length,
                            hostname: "239.1.2.3",
                            port: 39814
                        );

                        //new IHTMLPre { "sent: " + s }.AttachToDocument();


                        //socket.ReceiveAsync
                        //socket.Close();

                        //new IHTMLPre { $"sent: {s}" }.AttachToDocument();

                        // android cannot see it. why? because it needs to know which NIC to use.

                    }
            };
            #endregion



            new { }.With(
                  async delegate
                  {
                      //          if (nic.prefixLength != 24)
                      //              return;

                      //var status = new IHTMLPre { new { nic.address } }.AttachTo(toolbar);
                      var HUD = new IHTMLPre { "awaiting segment0..." }.AttachTo(toolbar);

                      // 500000

                      var uu = new UdpClient(49000);

                      //uu.ExclusiveAddressUse = false;
                      var md5string = "";

                      uu.JoinMulticastGroup(IPAddress.Parse("239.1.2.3"));
                      while (true)
                      {
                          var data = await uu.ReceiveAsync(); // did we jump to ui thread?

                          // jpeg progressive?
                          segment0 = data.Buffer;
                          file.Write(segment0, 0, segment0.Length);

                          // if segment is less than 65507
                          // then download is complete

                          if (file.Length > 0)
                              if (segment0.Length < 65507)
                              {

                                  //lobal::System.Security.Cryptography.MD5CryptoServiceProvider

                                  var bytes = file.ToArray();


                                  var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(bytes);

                                  // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20160103/x360videoui
                                  md5string = md5.ToHexString();


                                  // this is slow.. worker?
                                  file64 = Convert.ToBase64String(bytes);

                                  //data:[<MIME-type>][;charset=<encoding>][;base64],

                                  file = new MemoryStream();
                                  var src = "data:image/jpeg;base64," + file64;
                                  new { }.With(
                                      async delegate
                                      {
                                          var img = new IHTMLImage { src = src, title = md5string }.AttachTo(toolbar);
                                          img.style.height = "6em";

                                          do
                                          {
                                              // send udp back. so vr knows which image we went back to?

                                              mesh.material.map.image = img;
                                              mesh.material.map.needsUpdate = true;

                                              await img.async.onclick;

                                              //send sha1
                                              UDPClipboardSend(md5);
                                          }
                                          while (true);
                                      }
                                  );


                              }

                          HUD.innerText =
                              "segment0  " + segment0.Length
                              + "\nfile " + file.Length
                            + "\nfile64 " + file64.Length;


                      }
                  }
              );



            #region awaiting tracking
            new { }.With(
                    async delegate
                    {
                        //if (nic.prefixLength != 24)
                        //    return;

                        //var status = new IHTMLPre { new { nic.address } }.AttachTo(toolbar);
                        var HUD = new IHTMLPre { "awaiting tracking..." }.AttachTo(toolbar);


                        var uu = new UdpClient(49834);
                        //uu.ExclusiveAddressUse = false;
                        uu.JoinMulticastGroup(IPAddress.Parse("239.1.2.3"));
                        while (true)
                        {
                            var data = await uu.ReceiveAsync(); // did we jump to ui thread?
                            //Console.WriteLine("ReceiveAsync done " + Encoding.UTF8.GetString(x.Buffer));
                            //args.vertexTransform = x.Buffer;

                            var xy = Encoding.UTF8.GetString(data.Buffer).Split(':');

                            gearvr_x = float.Parse(xy[0]);
                            gearvr_y = float.Parse(xy[1]);
                            gearvr_z = float.Parse(xy[2]);
                            var w = float.Parse(xy[3]);
                            gearvr_filename = xy[4];

                            HUD.innerText = new { gearvr_x, gearvr_y, gearvr_z, w, gearvr_filename }.ToString().Replace(",", ",\n");

                        }
                    }
            );
            #endregion


            #endregion

        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // https://developers.google.com/web/fundamentals/input/touch/touchevents/

            // https://googlesamples.github.io/web-fundamentals/samples/input/touch/touch-demo-1.html

            // https://code.google.com/p/chromium/issues/detail?id=516050
            // http://stackoverflow.com/questions/17886073/do-chrome-and-firefox-support-pointer-event-pressure-tilt-touch-etc-any-so
            // https://mobiforge.com/design-development/html5-pointer-events-api-combining-touch-mouse-and-pen

            // http://arstechnica.com/information-technology/2015/03/chromium-team-reverses-course-will-adopt-ies-merged-mouse-touch-apis/
            // http://www.infoq.com/news/2015/04/google-pointer-events

            // http://www.theverge.com/2015/3/25/8291893/google-chrome-pointer-events-support
            // http://www.zdnet.com/article/google-will-implement-pointer-events-api-in-chrome-after-all/

            // http://www.w3.org/TR/pointerevents/

            // http://question.ikende.com/question/32303938343332303831

            // https://www.chromestatus.com/features/4504699138998272

            // https://msdn.microsoft.com/en-us/library/hh771911(v=vs.85).aspx

            var xPointerEvent = (Native.window as dynamic).PointerEvent;

            // --enable-blink-features=PointerEvent
            new IHTMLPre { new { xPointerEvent } }.AttachToDocument();

            //  dom.w3c_pointer_events.enabled
            //  dom.w3c_touch_events.enabled
            // https://hacks.mozilla.org/2015/08/pointer-events-now-in-firefox-nightly/
            new IHTMLPre { "firefox nightly seems to do pen tilt?" }.AttachToDocument();
            // works with ie too.
            // yet oly if we had tilt and pressure
            // does xt even have em natively?

            var onpointerover = new IHTMLPre { "onpointerover ?" }.AttachToDocument();
            var onpointerdown = new IHTMLPre { "onpointerdown ?" }.AttachToDocument();
            var onpointermove = new IHTMLPre { "onpointermove ?" }.AttachToDocument();

            var c = new CanvasRenderingContext2D(800, 200);

            c.canvas.style.border = "1px solid blue";
            c.canvas.AttachToDocument();
            c.canvas.style.SetLocation(0, 0);

            Native.document.body.style.marginTop = "200px";

            c.beginPath();
            c.moveTo(0, 0);

            // whatif xt does not have tilt data available?
            // X:\opensource\unmonitored\WintabDN\FormTestApp\TestForm.cs

            c.canvas.onpointerover += e =>
            {
                // got a stylus dell xt?
                // make sure ip is set to dhcp to get into wifi
                // make sure onenote still works...

                e.stopPropagation();
                e.preventDefault();

                onpointerover.innerText = "onpointerover " + new { e.pointerType, e.tiltX, e.tiltY, e.pressure, e.movementX };

            };

            c.canvas.onpointerdown += e =>
            {
                // got a stylus dell xt?
                // make sure ip is set to dhcp to get into wifi
                // make sure onenote still works...

                e.stopPropagation();
                e.preventDefault();

                onpointerdown.innerText = "onpointerdown " + new { e.pointerType, e.tiltX, e.tiltY, e.pressure, e.movementX };

            };

            //Native.document.body.onpointermove += e =>
            c.canvas.onpointermove += e =>
            {
                // got a stylus dell xt?
                // make sure ip is set to dhcp to get into wifi
                // make sure onenote still works...
                e.stopPropagation();
                e.preventDefault();


                onpointermove.innerText = "onpointermove " + new { e.pointerType, e.tiltX, e.tiltY, e.pressure, e.movementX };


                //Native.document.body.ScrollToBottom();


                if (e.pressure > 0)
                    c.strokeStyle = "red";
                else
                    c.strokeStyle = "blue";
                c.lineTo(e.CursorX, e.CursorY);
                //c.lineTo(e.OffsetX, e.OffsetY);
                //c.lineTo(e.movementX, e.movementY);
                c.stroke();
                // https://web.archive.org/web/20150423093435/http://www.n-trig.com/wintab-compatible-applications/
                // https://web.archive.org/web/20150318140957/http://www.n-trig.com/wintab-2/
                // https://web.archive.org/web/20150316135525/http://www.wacomeng.com/windows/index.html


            };

            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151001

            // https://msdn.microsoft.com/en-us/library/windows/hardware/jj151564(v=vs.85).aspx

        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");

                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "Launched2");

                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: null
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion

            // 
            // http://stackoverflow.com/questions/13076272/how-do-i-give-webkitgetusermedia-permission-in-a-chrome-extension-popup-window
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150712
            new { }.With(
                async delegate
                {
                    Native.body.Clear();
                    Native.document.documentElement.style.overflow = IStyle.OverflowEnum.auto;

                    // would it be easy to do head tracking via webcam for VR?
                    // the app would run on android, yet
                    // two sattelites could spawn on two laptops to track the head.

                    // would we be able to thread hop between camera devices and android?

                    // http://shopap.lenovo.com/hk/en/laptops/lenovo/u-series/u330p/
                    // The U330p's integrated 720p HD webcam

                    //new IHTMLPre {
                    //    "awaiting onvideo..."
                    //}.AttachToDocument();

                    // HD wont work for chrome app?
                    var v = await Native.window.navigator.async.onvideo;

                    // http://stackoverflow.com/questions/23982463/navigatorusermediaerror-constraintname-message-name-invalidstateerr

                    Console.WriteLine("awaiting onvideo... done");


                    v.AttachToDocument();

                    v.play();

                    // what do we see at this point?

                    // first, could we detect greenscreen without having one?

                    // assuming the camera is static, we could remove the pixels that never seem to move

                    // a shader program, consuming the video would be able to apply the effects a lot faster.
                    // doing it in ui thread will slow it down.

                    //					videoHeight: 480
                    //videoWidth: 640

                    // 
                    //new IHTMLPre {

                    //    new { v.videoWidth, v.videoHeight }
                    //}.AttachToDocument();
                    // do we know the size of the cam?
                    // {{ videoWidth = 0, videoHeight = 0 }}

                    var sw = Stopwatch.StartNew();

                    //Error CS4004  Cannot await in an unsafe context TestGetUserMedia    X:\jsc.svn\examples\javascript\async\test\TestGetUserMedia\TestGetUserMedia\Application.cs  45
                    // https://social.msdn.microsoft.com/Forums/en-US/29a3ca5b-c783-4197-af08-7b3c83585e99/minor-compiler-message-unsafe-async?forum=async


                    while (v.videoWidth == 0)
                        await Native.window.async.onframe;

                    //new IHTMLPre {
                    //    new { v.videoWidth, v.videoHeight, sw.ElapsedMilliseconds, Environment.ProcessorCount }
                    //}.AttachToDocument();

                    // {{ videoWidth = 640, videoHeight = 480, ElapsedMilliseconds = 793, ProcessorCount = 4 }}
                    // {{ videoWidth = 1280, videoHeight = 720, ElapsedMilliseconds = 368, ProcessorCount = 4 }}


                    var frame0 = new CanvasRenderingContext2D(
                        v.videoWidth, v.videoHeight
                    );

                    frame0.canvas.AttachToDocument();

                    var frame0sw = Stopwatch.StartNew();
                    var frame0c = 0;

                    // battery/full speed
                    // {{ frame0c = 1752, ElapsedMilliseconds = 66 }}


                    long yscanmax = 0;
                    //long yscan64max = 0;

                    var __yscan64max = 0;
                    var __yscan64max_ix = 0;

                    var slider = new IHTMLInput
                    {
                        type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range,
                        max = 255,
                        valueAsNumber = 0x40
                    }.AttachToDocument();

                    // 
                    new IHTMLPre {
                        () => new {
                            frame0c,
                            frame0sw.ElapsedMilliseconds,
                            fps = 1000 / frame0sw.ElapsedMilliseconds ,
                            yscanmax,

                            treshold = slider.valueAsNumber,

                            __yscan64max,
                            __yscan64max_ix,


                            px = (float)(__yscan64max_ix - v.videoWidth / 2)  / (float)v.videoWidth
                        }
                    }.AttachToDocument();


                    var sent = new IHTMLPre
                    {
                    }.AttachToDocument();


                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150701


                    // what about 255.255.255.255 ?
                    chrome.socket.getNetworkList().ContinueWithResult(async n =>
                   {
                       // which networks should we notify of our data?

                       //new IHTMLPre { new { n.Length } }.AttachToDocument();

                       foreach (var item in n)
                       {
                           // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                           // skip ipv6
                           if (item.address.Contains(":"))
                               continue;

                           #region send
                           new IHTMLButton { "send onframe " + item.address }.AttachToDocument().With(
                               async refresh =>
                               {
                                   refresh.style.color = "blue";

                                   refresh.style.display = IStyle.DisplayEnum.block;

                                   // experimental until ref count 33?
                                   await refresh.async.onmousedown;

                                   refresh.disabled = true;

                                   var port = new Random().Next(16000, 40000);

                                   //new IHTMLPre { "about to bind... " + new { port } }.AttachToDocument();

                                   // where is bind async?
                                   var socket = new UdpClient();
                                   socket.Client.Bind(

                                        //new IPEndPoint(IPAddress.Any, port: 40000)
                                        new IPEndPoint(IPAddress.Parse(item.address), port)
                                    );


                                   // this will eat too much memory?
                                   //div.ownerDocument.defaultView.onframe +=
                                   Native.window.onframe += e =>
                                   {
                                       var px = (float)(__yscan64max_ix - v.videoWidth / 2) / (float)v.videoWidth;

                                       // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150704
                                       var nmessage = e.counter + ":" + px + ":0";

                                       sent.innerText = nmessage;

                                       var data = Encoding.UTF8.GetBytes(nmessage);      //creates a variable b of type byte



                                       //new IHTMLPre { "about to send... " + new { data.Length } }.AttachToDocument();

                                       // X:\jsc.svn\examples\javascript\chrome\apps\ChromeUDPNotification\ChromeUDPNotification\Application.cs
                                       socket.Send(
                                           data,
                                           data.Length,
                                           hostname: "239.1.2.3",
                                           port: 43834
                                       );
                                   };


                               }
                           );
                           #endregion

                       }
                   }
                );





                    // jsc, when can we start using semaphores?
                    // this could also trgger state sync
                    //var xx = new System.Threading.SemaphoreSlim(1);



                    new { }.With(
                        async delegate
                        {
                            // could we hop into worker thread, and await for bytes to render?

                            // this is essentially a shader

                            // switch to worker here
                            // at runtime we should know, which fields in this state are in use

                            do
                            {
                                frame0c++;
                                frame0sw = Stopwatch.StartNew();


                                frame0.drawImage(
                                    v,
                                    0, 0, v.videoWidth, v.videoHeight);


                                // could we do thread hopping here to multicore process the data without shaders?
                                // RGB,
                                // would we have each core work on 8bits. a single color?

                                // X:\jsc.svn\examples\javascript\canvas\CanvasFromBytes\CanvasFromBytes\Application.cs 


                                // PLINQ via cpu count or glsl?
                                var rgba_bytes = frame0.bytes;


                                //var rgba_pixels = (rgba[])rgba_bytes;
                                //Error CS0030  Cannot convert type 'byte[]' to 'TestGetUserMedia.rgba[]'   TestGetUserMedia X:\jsc.svn\examples\javascript\async\test\TestGetUserMedia\TestGetUserMedia\Application.cs  98

#if FPOINTERS
					unsafe
					{
						//Error CS0030  Cannot convert type 'byte[]' to 'TestGetUserMedia.rgba*'    TestGetUserMedia X:\jsc.svn\examples\javascript\async\test\TestGetUserMedia\TestGetUserMedia\Application.cs  109
						//var rgba_pixels = (rgba*)rgba_bytes;
						//Error CS0030  Cannot convert type 'byte[]' to 'void*' TestGetUserMedia X:\jsc.svn\examples\javascript\async\test\TestGetUserMedia\TestGetUserMedia\Application.cs  110

						fixed (byte* rgba_ptr = rgba_bytes)
						{
							// script: error JSC1000: running a newer compiler? opcode unsupported - [0x0035] sizeof     +1 -0

							// how would a shader do it?
							var rgba_pixels = (rgba*)rgba_ptr;

							// looks legit

							// how does it compile for js?

							for (int x = 0; x < v.videoWidth; x++)
								for (int y = 0; y < v.videoHeight; y++)
								{
									rgba_pixels[x + y * v.videoWidth].b = 0;
									rgba_pixels[x + y * v.videoWidth].g = 0;

								}

						}

					}
#endif
                                // fps4

                                // https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/camera-capture

                                // make it all blue
                                // glsl. u8vec4

                                //var yscan = new long[v.videoWidth];

                                #region yscan
                                var yscan = new int[v.videoWidth];
                                yscanmax = 0;

                                // lets deal only with first half of bytes
                                //for (int x = 0; x < rgba_bytes.Length / 2; x += 4)
                                //for (int x = 0; x < rgba_bytes.Length; x += 4)
                                for (int ix = 0; ix < v.videoWidth; ix++)
                                {
                                    var yscanix = 0;

                                    // interleave?
                                    for (int iy = v.videoHeight / 4; iy < v.videoHeight - v.videoHeight / 4; iy += 5)
                                    {

                                        var x = ix * 4;
                                        var y = iy * 4 * v.videoWidth;

                                        //// red
                                        //rgba_bytes[x + 0] = 0;
                                        //rgba_bytes[x + 1] = (byte)(1 - rgba_bytes[x + 1]);
                                        //// blue
                                        //rgba_bytes[x + 2] = 0;


                                        var r = rgba_bytes[y + x + 0];
                                        var g = rgba_bytes[y + x + 1];
                                        var b = rgba_bytes[y + x + 2];


                                        // red
                                        rgba_bytes[y + x + 0] = 0;


                                        //float rf = 255f - rgba_bytes[x + 0];
                                        ////var rf = r / 255f;

                                        ////var lux =
                                        ////    ((float)rgba_bytes[x + 0] / (255f))
                                        ////    * ((float)rgba_bytes[x + 1] / (255f))
                                        ////    * ((float)rgba_bytes[x + 2] / (255f));

                                        //rgba_bytes[x + 1] = (byte)(
                                        //    rf
                                        ////(255f * rf)
                                        //);

                                        var xg = (byte)(
                                             (3 * 255 - r - g - b)
                                             / 3
                                         );

                                        // either white out or black out?



                                        if (xg < slider.valueAsNumber)
                                        {
                                            xg = 0;
                                            yscanix += 1;
                                        }


                                        // script: error JSC1000: unknown opcode stelem.i8 at <0197> nop.try + 0x0023

                                        rgba_bytes[y + x + 1] = xg;

                                        // blue
                                        rgba_bytes[y + x + 2] = 0;
                                    }

                                    yscan[ix] = yscanix;

                                    if (yscanix > yscanmax)
                                        yscanmax = yscanix;
                                }

                                //yscanmax = yscan.Max();
                                #endregion


                                #region top visualization
                                for (int ix = 0; ix < v.videoWidth; ix++)
                                {
                                    // gives a better visualization
                                    var kf = 1 - ((float)yscan[ix] / (float)yscanmax);
                                    //var kf = ((float)yscan[ix] / (float)yscanmax);
                                    var k8 = (byte)(kf * 16f);

                                    for (int iy = 0; iy < k8; iy++)
                                    {

                                        var x = ix * 4;
                                        var y = iy * 4 * v.videoWidth;

                                        rgba_bytes[y + x + 0] = 255;
                                    }
                                }
                                #endregion

                                #region now do mipmap on the yscan 
                                var yscan64 = new int[v.videoWidth];

                                __yscan64max = 0;

                                //var lookahead = 64;
                                var lookahead = 16;

                                for (int ix = 0; ix < v.videoWidth; ix++)
                                {
                                    var yscan64ix = 0;

                                    //if (ix >= 64)
                                    //    if (ix < (v.videoWidth - 64))
                                    for (int ixx = -lookahead; ixx < lookahead; ixx++)
                                    {

                                        if (ix + ixx > 0)
                                            if (ix + ixx < v.videoWidth)
                                            {
                                                var yy = yscan[ix + ixx];

                                                if (yy > 0)
                                                    yscan64ix += yy;
                                            }
                                    }

                                    if (yscan64ix > __yscan64max)
                                    {
                                        __yscan64max = yscan64ix;
                                        __yscan64max_ix = ix;
                                    }

                                    yscan64[ix] = yscan64ix;
                                }
                                #endregion

                                // parralax X . if we get Y too we could also know the zoom in out
                                //yscan64max = yscan64.Max();
                                //yscan64max = __yscan64max_ix;

                                #region bottom visualization
                                for (int ix = 0; ix < v.videoWidth; ix++)
                                {
                                    //var kf = 1 - ((float)yscan64[ix] / (float)yscan64max);
                                    var kf = ((float)yscan64[ix] / (float)__yscan64max);
                                    var k8 = (byte)(kf * 16f);



                                    for (int iy = 0; iy < k8; iy++)
                                    {

                                        var x = ix * 4;
                                        var y = (v.videoHeight - iy) * 4 * v.videoWidth;

                                        if (ix == __yscan64max_ix)
                                            rgba_bytes[y + x + 1] = 255;
                                        else
                                            rgba_bytes[y + x + 0] = 255;
                                    }
                                }
                                #endregion


                                frame0.bytes = rgba_bytes;



                                // Permission 'videoCapture ' is unknown or URL pattern is malformed.
                            } while (await Native.window.async.onframe);
                        }
                    );



                    // {{ videoWidth = 640, videoHeight = 480, ElapsedMilliseconds = 109 }}

                    await Native.window.async.onblur;

                    // stream is not stopped yet?
                    //v.Orphanize();

                    Native.body.style.backgroundColor = "yellow";
                }
            );
        }
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IDefault page)
		{


			// does not work for android 2.2?
			//Action Toggle = ApplicationContent.BindKeyboardToDiagnosticsConsole();

			//page.Tilde.onclick +=
			//    delegate
			//    {
			//        Toggle();
			//    };

			Native.Document.title = "DCIM Gallery App";

			if (Native.window.parent != Native.window.self)
			{
				Native.document.body.style.backgroundColor = JSColor.Transparent;
			}

			// see also. http://en.wikipedia.org/wiki/Design_rule_for_Camera_File_system


			var container = new IHTMLCenter().AttachToDocument();

			#region AddThumbnailTo
			Action<string, IHTMLElement> AddThumbnailTo =
				(path, div) =>
				{
					new IHTMLImage { }.AttachTo(div).With(
							 img =>
							 {
								 // portrait mode only!

								 div.style.color = JSColor.Red;
								 img.src = "/thumb/" + path;

								 #region onload +=
								 img.InvokeOnComplete(
									 delegate
									 {
										 div.style.color = JSColor.Green;

										 IHTMLPre p = null;

										 img.onclick += delegate
										 {
											 if (p == null)
											 {
												 img.src = "/io/" + path;
												 img.style.width = "100%";
												 div.style.display = IStyle.DisplayEnum.block;

												 p = new IHTMLPre { }.AttachTo(div);
												 GetEXIF("/io/" + path,
													 x =>
													 {
														 p.innerText = x;
													 }
												 );


											 }
											 else
											 {

												 p.Orphanize();
												 p = null;
												 img.src = "/thumb/" + path;
												 img.style.width = "";
											 }

										 };
									 }
								 );
								 #endregion





							 }
						 );
				};
			#endregion

			#region yfile
			ystring yfile = path =>
			{
				new IHTMLDiv { innerText = path }.With(
					div =>
					{
						if (path.ToLower().EndsWith(".jpg"))
						{
							div.innerText = "";
							div.AttachTo(container);
							// hide path

							//new IHTMLBreak().AttachTo(div);
							div.style.display = IStyle.DisplayEnum.inline_block;


							AddThumbnailTo(path, div);
						}
					}
				);
			};
			#endregion



			#region TakePicture
			page.icon.style.cursor = IStyle.CursorEnum.pointer;
			page.icon.onclick +=
				delegate
				{
					this.TakePicture("",
						path =>
						{
							Console.WriteLine(new { path });

							new IHTMLDiv { innerText = path }.With(
								div =>
								{
									if (path.ToLower().EndsWith(".jpg"))
									{
										div.innerText = "";

										container.insertBefore(div, container.firstChild);

										//div.AttachTo(container);
										// hide path

										//new IHTMLBreak().AttachTo(div);
										div.style.display = IStyle.DisplayEnum.inline_block;


										AddThumbnailTo(path, div);
									}
								}
							);
						}
					);

				};
			#endregion



			new IHTMLButton { innerText = "more" }.AttachToDocument().With(
				async more =>
				{
					more.style.margin = "1em";

					while (true)
					{


						more.disabled = true;
						more.innerText = "checking for more...";


						await this.File_list(
							yfile: yfile
						);

						this.skip += this.take;
						more.innerText = "more " + new { this.skip };
						more.disabled = false;

						#region either onclick or onscrollToBottom
						await Task.WhenAny(
							Native.window.async.onscrollToBottom,
							more.async.onclick
						);
						#endregion

					}
				}
			);



		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            new { }.With(
                async delegate
                {
                    new IHTMLPre { new { Native.document.currentScript } }.AttachToDocument();

                    var x = await base.GetData();

                    new IHTMLPre { new { Native.document.currentScript } }.AttachToDocument();

                    // IPublicKey . VerifyAsync()

                    var verificationKey = await Native.crypto.subtle.importRSAPublicKeyForVerificationAsync(
                        this.PublicKeyModulus,
                        this.PublicKeyExponent
                    );



                    new IHTMLPre { new { verificationKey } }.AttachToDocument();

                    //new System.Security.Cryptography.RSACryptoServiceProvider().e
                    var verified = await Native.crypto.subtle.verifyAsync(verificationKey, x.signature, Encoding.UTF8.GetBytes(x.value));

                    // at any point we can now verify the data from webservice is signed and valid.
                    new IHTMLPre { new { verified } }.AttachToDocument();

                    // http://caniuse.com/#feat=cryptography


                    //#region keyData
                    //var m64padding = Convert.ToBase64String(base.PublicKeyModulus);
                    //var m64 = m64padding;


                    //while (m64.EndsWith("=="))
                    //    m64 = m64.Substring(0, m64.Length - 2);


                    //// make URL friendly:
                    ////str = str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');

                    //// http://stackoverflow.com/questions/4492426/remove-trailing-when-base64-encoding
                    //m64 = m64.Replace("+", "-").Replace("/", "_").Replace("=+", "");


                    //var keyData = new
                    //{
                    //    //alg = "RS256",
                    //    alg = "RS1",
                    //    //alg = "RSA-OAEP",
                    //    e = Convert.ToBase64String(base.PublicKeyExponent),
                    //    ext = false,
                    //    kty = "RSA",
                    //    n = m64
                    //};
                    //#endregion

                    //// { keyData = { alg = RSA-OAEP, e = AQAB, ext = false, kty = RSA, n = s8uxpsmasavYjVmctC_FSnC98T-qHs8zBsuQF44015gF_jSkM8apog3SZquKXf_SyT8v-HMUSoyBuu1ztbAovQ } }


                    //// http://blog.engelke.com/2014/10/21/web-crypto-and-x-509-certificates/
                    ////  "1.2.840.113549.1.1.5" 

                    //// onError { z = DataError: The JWK "alg" member was inconsistent with that specified by the Web Crypto call }
                    //// https://github.com/diafygi/webcrypto-examples


                    //var algorithm = new
                    //{
                    //    name = "RSASSA-PKCS1-v1_5",
                    //    //name = "RSA-OAEP",
                    //    //hash = new { name = "SHA-256" },
                    //    hash = new { name = "SHA-1" }

                    //    //modulusLength = 2048,
                    //    //publicExponent,
                    //};

                    //var sw = Stopwatch.StartNew();


                    // //Native.crypto.subtle.importKey
                    //var p = Native.crypto.subtle.importKey(
                    //    format: "jwk",
                    //    keyData: keyData,
                    //    algorithm: algorithm,
                    //    extractable: false,
                    //    keyUsages: new[] { // "encrypt", 

                    //            // onError { z = SyntaxError: Cannot create a key using the specified key usages. }
                    //            "verify" 
                    //        }
                    //);

                    //p.then(
                    //    onSuccess: publicKey =>
                    //    {
                    //        // onSuccess {{ z = [object CryptoKey], ElapsedMilliseconds = 9278 }}


                    //        new IHTMLPre { "onSuccess " + new { publicKey, sw.ElapsedMilliseconds } }.AttachToDocument();

                    //        //new IHTMLButton { "encrypt for server" }.AttachToDocument().onclick +=
                    //        //async delegate
                    //        //{
                    //        //    // Man in the middle?
                    //        //    // layered security
                    //        //    var data = Encoding.UTF8.GetBytes("hello from client");
                    //        //    var esw = Stopwatch.StartNew();

                    //        //    var ebytes = await Native.crypto.subtle.encryptAsync(algorithm, z, data);
                    //        //    new IHTMLPre { "encryptAsync " + new { esw.ElapsedMilliseconds } }.AttachToDocument();

                    //        //    await UploadEncryptedString(
                    //        //        ebytes
                    //        //    );
                    //        //};

                    //        // onSuccess { z = [object CryptoKey], ElapsedMilliseconds = 0 }


                    //        Native.crypto.subtle.verify(
                    //             new
                    //             {
                    //                 name = "RSASSA-PKCS1-v1_5",
                    //             },
                    //            publicKey, //from generateKey or importKey above
                    //            x.signature, //ArrayBuffer of the signature
                    //            Encoding.UTF8.GetBytes(x.value) //ArrayBuffer of the data

                    //        ).then(

                    //        onSuccess: verified =>
                    //            {
                    //                new IHTMLPre {
                    //            "verify " +
                    //                new {
                    //               verified}
                    //            }.AttachToDocument();
                    //            }
                    //        );

                    //    },

                    //    onError: z =>
                    //    {
                    //        // onError { z = DataError: The JWK member "n" could not be base64url decoded or contained padding }

                    //        new IHTMLPre {
                    //            "onError " +
                    //                new {
                    //               z}
                    //            }.AttachToDocument();
                    //    }

                    //);


                    // onError { z = SyntaxError: Cannot create a key using the specified key usages. }


                    var o = x.value;
                    var t = new IHTMLTextArea { value = x, readOnly = true }.AttachToDocument();

                    t.style.whiteSpace = IStyle.WhiteSpaceEnum.nowrap;
                    t.style.width = "80em";
                    //t.style.right = "1em";
                    t.style.height = "20em";

                    var status = new IHTMLPre { }.AttachToDocument();

                    t.style.paddingLeft = "1em";
                    //t.style.borderLeft = "1em solid green";
                    t.readOnly = false;

                    ////while (await t.async.onchange)

                    do
                    {
                        t.style.borderLeft = "1em solid yellow";

                        // Z:\jsc.svn\core\ScriptCoreLib.Windows.Forms\ScriptCoreLib.Windows.Forms\JavaScript\BCLImplementation\System\Windows\Forms\TextBox.cs
                        x.value = t.value.Replace(Environment.NewLine, "\n").Replace("\n", Environment.NewLine);


                        verified = await Native.crypto.subtle.verifyAsync(verificationKey, x.signature, Encoding.UTF8.GetBytes(x.value));
                        //var verify = await base.Verify(x);
                        status.innerText = new { isoriginal = o == x.value, o = o.Length, t = x.value.Length, verified }.ToString();

                        if (verified)
                            t.style.borderLeft = "1em solid green";
                        else
                            t.style.borderLeft = "1em solid red";
                    }
                    while (await t.async.onkeyup);




                }
            );
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IDefault  page)
        {
            #region AtFile
            Action<File> AtFile =
                f =>
                {
                    var n = new MyFile();
                    // databind here?
                    n.name.innerText = f.name;
                    n.type.innerText = f.type;
                    n.lastModifiedDate.innerText = "" + f.lastModifiedDate;

                    #region hex
                    new FileReader().With(
                        reader =>
                        {
                            reader.onload = IFunction.Of(
                                delegate
                                {
                                    var x = (ArrayBuffer)reader.result;

                                    var u8 = new Uint8Array(x, 0, 8);

                                    var pre = new IHTMLPre().AttachTo(n.Container);

                                    pre.style.border = "1px solid gray";

                                    for (uint i = 0; i < u8.length; i++)
                                    {
                                        pre.innerText += u8[i].ToString("x2") + " ";

                                    }
                                }
                            );

                            // Read in the image file as a data URL.
                            reader.readAsArrayBuffer(f);
                        }
                     );
                    #endregion

                    #region AsDataURL
                    Action<Action<string>> AsDataURL =
                        h =>
                        {
                            var reader = new FileReader();

                            reader.onload = IFunction.Of(
                                delegate
                                {
                                    var base64 = (string)reader.result;

                                    h(base64);

                                }
                            );
                            
                            // Read in the image file as a data URL.
                            reader.readAsDataURL(f);

                        };
                    #endregion


                    #region image
                    if (f.type.StartsWith("image/"))
                    {
                        AsDataURL(
                            base64 =>
                                new IHTMLImage
                                {
                                    src = base64,

                                }.AttachTo(n.Container)
                        );
                    }
                    #endregion


                    #region audio
                    if (f.type.StartsWith("audio/"))
                    {
                        AsDataURL(
                           base64 =>
                               new IHTMLAudio
                               {
                                   src = base64,
                                   controls = true,
                               }.AttachTo(n.Container)
                       );
                    }
                    #endregion

                    #region video
                    //if (f.type.StartsWith("video/"))
                    //{
                    //    AsDataURL(
                    //       base64 =>
                    //           new IHTMLVideo
                    //           {
                    //               src = base64,
                    //               controls = true,

                    //           }.AttachTo(n.Container)
                    //   );
                    //}
                    #endregion

                    n.Container.AttachTo(page.list);
                };
            #endregion


            #region onchange
            page.files.onchange +=
                e =>
                {
                    FileList x = page.files.files;
                    page.list.Clear();
                    page.list.Add("files: " + x.length);
                    for (uint i = 0; i < x.length; i++)
                    {
                        File f = x[i];

                        AtFile(f);
                    }

                };
            #endregion

            page.drop_zone.ondragleave +=
                delegate
                {
                    page.drop_zone.style.borderColor = JSColor.Gray;
                    page.drop_zone.style.backgroundColor = JSColor.None;
                };

            #region dragover
            page.drop_zone.ondragover +=
                    evt =>
                    {
                        page.drop_zone.style.borderColor = JSColor.Red;
                        page.drop_zone.style.backgroundColor = JSColor.FromRGB(0xff, 0xaf, 0xaf);

                        evt.StopPropagation();
                        evt.PreventDefault();
                        evt.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy.
                    };

            page.drop_zone.ondrop +=
                  evt =>
                  {
                      page.drop_zone.style.borderColor = JSColor.Green;
                      page.drop_zone.style.backgroundColor = JSColor.FromRGB(0xaf, 0xff, 0xaf);


                      evt.StopPropagation();
                      evt.PreventDefault();

                      FileList x = evt.dataTransfer.files; // FileList object.

                      page.list.Clear();
                      page.list.Add("files: " + x.length);
                      for (uint i = 0; i < x.length; i++)
                      {
                          File f = x[i];

                          AtFile(f);
                      }
                  };
            #endregion


        }
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			// how are we to make this into a chrome app?
			// "X:\jsc.svn\examples\javascript\chrome\apps\ChomeAlphaAppWindow\ChomeAlphaAppWindow.sln"

			// since now jsc shows ssl support
			// how about packaging the view-source for chrome too?

			// nuget, add chrome.

			#region += Launched chrome.app.window
			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_socket = self_chrome.socket;

			if (self_chrome_socket != null)
			{
				if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
				{
					Console.WriteLine("chrome.app.window.create, is that you?");

					// pass thru
				}
				else
				{
					// should jsc send a copresence udp message?
					chrome.runtime.UpdateAvailable += delegate
					{
						new chrome.Notification(title: "UpdateAvailable");

					};

					chrome.app.runtime.Launched += async delegate
					{
						// 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
						Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

						new chrome.Notification(title: "Launched2");

						var xappwindow = await chrome.app.window.create(
							   Native.document.location.pathname, options: null
						);

						//xappwindow.setAlwaysOnTop

						xappwindow.show();

						await xappwindow.contentWindow.async.onload;

						Console.WriteLine("chrome.app.window loaded!");
					};


					return;
				}
			}
			#endregion


			// can we also test the shadow DOM ?
			// how does it work again?


			// now we have to update our alpha window/server window
			// to be in the correct context.

			// what about property window
			// back in the vb days we made one.
			// time to do one?

			new IHTMLButton { "ready1" }.AttachToDocument().onclick +=
				//async
				delegate
				{

					new MyShadow { }.AttachTo(Native.shadow);

					// shadow will select div from chldren
					var div = new IHTMLDiv { }.AttachTo(Native.document.documentElement);


					new IHTMLPre { "drag me" }.AttachTo(div);
					var xy = new IHTMLPre { "{}" }.AttachTo(div);

					div.css.style.backgroundColor = "transparent";
					div.css.style.transition = "background 500ms linear";

					div.css.active.style.backgroundColor = "yellow";

					Native.document.documentElement.style.cursor = IStyle.CursorEnum.move;

					div.onmousemove +=
						e =>
						{
							// we could tilt the svg cursor
							// like we do on heat zeeker:D


							//Native.document.title = new { e.CursorX, e.CursorY }.ToString();
							xy.innerText = new { e.CursorX, e.CursorY }.ToString();

						};

					div.onmousedown +=
						async e =>
						{
							e.CaptureMouse();

							await div.async.onmouseup;
						};
				};

		}
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			// X:\jsc.svn\examples\javascript\async\AsyncWindowUncaughtError\AsyncWindowUncaughtError\ApplicationWebService.cs

			// intellitrace
			// a self debugging programe?
			// can we have buttons for debugging?
			// https://www.youtube.com/watch?v=4vtKRE9an_I
			// could we have live patching, remote debugging via udp?

			var Next = new IHTMLButton { "Next" }.AttachToDocument();
			Next.disabled = true;

			Func<Task> Next_onclick = async delegate
			{

				Next.disabled = false;
				await Next.async.onclick;
				Next.disabled = true;
			};

			trace trace = async (string filepath, int linenumber, string line) =>
			{
				// could we go backwards in time too?
				// like intellitrace?

				var debugged = new IHTMLPre { }.AttachToDocument();




				// should we allow chaning constants?
				// by patching const load opcodes?

				var l = new IHTMLSpan { "" + linenumber }.AttachToDocument();




				l.title = filepath;

				l.style.marginRight = "2em";
				l.style.color = "darkcyan";

				l.AttachTo(debugged);

				// could we use css to do syntax highlight?
				var prefixToHide = "await trace();";

				// perhaps the next step would be to send us the origina stack usage IL 
				// we see in the jsc reflector?
				var c = new IHTMLSpan { line.Replace(prefixToHide, "") };

				c.style.marginRight = "2em";
				//c.style.color = "blue";
				c.style.backgroundColor = "yellow";

				c.AttachTo(debugged);

				await Next_onclick();

				c.style.backgroundColor = "";
			};

			interactive<string> __string = async (string data, string filepath, int linenumber, string line) =>
			{
				var i = new IHTMLInput { value = data }.AttachToDocument();

				await Next_onclick();

				return i.value;
			};


			//Func<>
			Func<string, Task<string>> program =
			// a simulaton of a program
			async data =>
			{
				await trace(); new IHTMLPre { await __string("hello") }.AttachToDocument();
				await trace(); new IHTMLPre { await __string("world") }.AttachToDocument();


				await trace(); return "done!";
			};

			new IHTMLButton { "Step Into" }.AttachToDocument().onclick +=
				async e =>
				{
					new IHTMLHorizontalRule().AttachToDocument();

					e.Element.disabled = true;
					var value = await program("data");
					e.Element.disabled = false;

					new IHTMLPre { new { value } }.AttachToDocument();

				};


			new IHTMLButton { "Run" }.AttachToDocument().onclick +=
				async e =>
				{
					// enum to string?
					new IHTMLHorizontalRule().AttachToDocument();

					var x = Next_onclick;
					// slow down the program
					Next_onclick = async delegate { await Task.Delay(300); };


					e.Element.disabled = true;
					var value = await program("data");
					e.Element.disabled = false;

					Next_onclick = x;

					new IHTMLPre { new { value } }.AttachToDocument();

				};
		}
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            @"Hello world".ToDocumentTitle();
            // Send data from JavaScript to the server tier

            //IStyleSheet.Default.AddRule("body", "-webkit-transition: background-color .15s linear .1;", 0);

            (Native.document.body.style as dynamic).webkitTransition = "background-color 500ms ease-out";

            Action<ApplicationWebService> bind =
                service =>
                {

                    service.MakeCyan = delegate
                        {
                            Native.document.body.style.backgroundColor = "cyan";
                        };

                    service.MakeYellow = delegate
                    {
                        Native.document.body.style.backgroundColor = "yellow";
                    };

                    service.set_backgroundColor = value =>
                    {
                        Native.document.body.style.backgroundColor = value;
                    };
                };

            bind(this);


            new IHTMLButton { innerText = "WebMethod2" }.AttachToDocument().WhenClicked(
                async delegate
                {
                    var Result = await this.WebMethod2(
                         42,
                         value => value.ToDocumentTitle()
                     );

                    foreach (var item in Result)
                    {
                        new IHTMLPre { innerText = new { item }.ToString() }.AttachToDocument();

                    }
                }
            );

            new IHTMLButton { innerText = "WebMethod4" }.AttachToDocument().WhenClicked(
                 async delegate
                 {
                     var Result = await this.WebMethod4(
                          42,
                          value => value.ToDocumentTitle()
                      );

                     foreach (var item in Result)
                     {
                         //new IHTMLPre { innerText = new { item.e }.ToString() }.AttachToDocument();
                         var x = new IHTMLPre { innerText = item.ToString() }.AttachToDocument();

                         var xx = await item.GetString();
                         x.innerText = xx;
                     }
                 }
             );

            Func<ApplicationWebService, Task> y = null;

            y =
                async service =>
                {
                    var Result = await service.WebMethod8(
                      42,
                      value => value.ToDocumentTitle()
                   );

                    new IHTMLBreak { }.AttachToDocument();

                    Result.WithEach(
                        xservice =>
                        {
                            // for new we have to keep rebinding
                            // because the server seems to call our functions even if we do not set them?
                            // can we even send a null delegate to server?
                            bind(xservice);

                            new IHTMLButton { innerText = "WebMethod8 " + new { xservice.xe }.ToString() }.AttachToDocument().WhenClicked(
                                   async delegate
                                   {

                                       await y(xservice);
                                   }
                            );


                        }
                    );

                };

            new IHTMLButton { innerText = "WebMethod8" }.AttachToDocument().WhenClicked(
               async delegate
               {

                   await y(this);
               }
           );
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // internal nuclear war

            // https://www.youtube.com/watch?v=qgjlqzHbwhg
            // the day after disaster
            // countdown to zero
            // confusion/disonfirmation/ what is it?
            // BRICS vs NATO

            // https://web.archive.org/web/20090219070038/http://www.deagel.com/country/United-States-of-America_c0001.aspx

            new { }.With(
                async scope =>
                {
                    var rgb_red = new { r = 255, g = 0, b = 0 };
                    var rgb_yellow = new { r = 255, g = 255, b = 0 };
                    var rgb_green = new { r = 0, g = 255, b = 0 };

                    var rgb_red_to_yellow = Enumerable.Range(0, 100 + 1).Select(
                        i => new
                    {
                        // rgb likes ints instead of doubles
                        r = (int)(rgb_yellow.r * (i / 100.0) + rgb_red.r * ((100.0 - i) / 100.0)),
                        g = (int)(rgb_yellow.g * (i / 100.0) + rgb_red.g * ((100.0 - i) / 100.0)),
                        b = (int)(rgb_yellow.b * (i / 100.0) + rgb_red.b * ((100.0 - i) / 100.0))
                    }
                    ).ToArray();

                    var rgb_yellow_to_green = Enumerable.Range(0, 100 + 1).Select(
                           i => new
                    {
                        // rgb likes ints instead of doubles
                        r = (int)(rgb_green.r * (i / 100.0) + rgb_yellow.r * ((100.0 - i) / 100.0)),
                        g = (int)(rgb_green.g * (i / 100.0) + rgb_yellow.g * ((100.0 - i) / 100.0)),
                        b = (int)(rgb_green.b * (i / 100.0) + rgb_yellow.b * ((100.0 - i) / 100.0))
                    }
                       ).ToArray();

                    var rgb_200_red_to_yellow_to_green = rgb_red_to_yellow.Concat(rgb_yellow_to_green).ToArray();

                    var ds = Data.forecast.GetDataSet();

                    var forecast0 = (
                        from item in ds.Tables["population"].Rows.AsEnumerable()
                        let row = (Data.forecastpopulationRow)item
                        let diff = row.Forecast2025Population - row.Current2013Population
                        let delta = diff / row.Current2013Population

                        select new { row, diff, delta }
                    ).ToArray();

                    // whats the max delta?

                    var min = forecast0.Min(x => x.delta);
                    var max = forecast0.Max(x => x.delta);



                    new IHTMLPre {
                            new { min, max }
                        }.AttachToDocument();



                    var forecast = (
                        from item in forecast0

                        let indicator = (int)Math.Floor(200 * (item.delta + -min) / (-min + max))
                        //let rgb = rgb_red_to_yellow[indicator]
                        let rgb = rgb_200_red_to_yellow_to_green[indicator]

                        select new { item.row, item.diff, item.delta, indicator, rgb }
                    );

                    // {{ min = -0.7816455696202531, max = 0.16666666666666666 }}
                    // how do we get from min max to red yellow green?




                    foreach (var item in forecast)
                    {


                        var pre = new IHTMLPre {

                            new { item.row.Current2013Population,
                                    item.row.Name,
                                    item.row.Forecast2025Population,

                                    item.diff,

                                    item.delta,
                                    item.indicator
                                    //, rgb

                            }
                        }.AttachToDocument();

                        //pre.style.borderLeft = "2em solid yellow";
                        pre.style.borderLeft = "2em solid rgba(" + item.rgb.r + "," + item.rgb.g + "," + item.rgb.b + ", 1.0)";
                    }


                    var svg = new WebClient().DownloadStringTaskAsync(new HTML.Images.FromAssets.BlankMap_World6_Equirectangular().src);

                    var xml = XElement.Parse(await svg);

                    // jsc, will this work?
                    xml.AttachToDocument();

                    // script: error JSC1000: No implementation found for this native method, please implement [System.Xml.Linq.XContainer.Descendants(System.Xml.Linq.XName)]
                    //var landUS = xml.Descendants("path").FirstOrDefault(path => path.Attribute("class").Value == "land us");
                    xml.Descendants().Where(x => x.Attribute("class") != null).Where(path => path.Attribute("class").Value == "land us").WithEach(
                        landUS =>
                        {
                            // http://stackoverflow.com/questions/17616233/css-hover-sometimes-doesnt-work-on-svg-paths

                            var landUS_style = landUS.Attribute("style");
                            landUS_style.Value = landUS.Value.TakeUntilIfAny("fill:").SkipUntilIfAny(";") + ";fill: red;";

                            // http://www.deagel.com/country/United-States-of-America_c0001.aspx

                            // this wont work
                            //landUS.SetAttributeValue("title", "Forecast 2025: -78%");

                            //var path = (ISVGPathElement)landUS.AsHTMLElement();
                            //path.onmouseover +=
                            //    delegate
                            //{
                            //    landUS_style.Value = landUS.Value.TakeUntilIfAny("fill:").SkipUntilIfAny(";") + ";fill: yellow;";
                            //};
                        }
                    );


                    // linq in async broken for now? need to rescope?
                    xml.Descendants().Where(x => x.Attribute("class") != null).With(
                         paths =>
                        {

                            (from item in forecast


                                 // http://msdn.microsoft.com/en-us/library/bb311040.aspx

                             join path in paths on item.row.Name equals path.Attribute("class").Value

                             select new { item, path }
                            ).WithEach(
                                x =>
                            {
                                // http://stackoverflow.com/questions/11257015/how-to-give-hsl-color-value-to-an-svg-element

                                var landUS_style = x.path.Attribute("style");
                                landUS_style.Value = x.path.Value.TakeUntilIfAny("fill:").SkipUntilIfAny(";")
                                + ";fill: "
                                    + "rgba(" + x.item.rgb.r + ", " + x.item.rgb.g + ", " + x.item.rgb.b + ", 1.0)";

                            }
                            );
                        }
                     );



                }
            );



        }
		public Application(IApp page)
		{
			// X:\jsc.svn\examples\javascript\chrome\extensions\ChromeTabsExperiment\ChromeTabsExperiment\Application.cs

			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_tabs = self_chrome.tabs;

			#region self_chrome_tabs
			if (self_chrome_tabs != null)
			{
				Console.WriteLine("extension is now running...");

				#region isYTMissing
				new { }.With(
					async delegate
					{
						var vid = "TXExg6Xj3aA";

						var thumbnail = $"https://img.youtube.com/vi/{vid}/0.jpg";

						var thumbnailImage = new IHTMLImage
						{
							src = thumbnail
						};

						// wont get those events for 404?

						//Native.window.onerror += err =>
						//{
						//	Console.WriteLine(
						//		"window onerror " +

						//		new
						//		{
						//			thumbnail,
						//			err,

						//			thumbnailImage.complete,
						//			thumbnailImage.width,
						//			thumbnailImage.naturalWidth,
						//			thumbnailImage.naturalHeight
						//		}
						//	);

						//};

						//thumbnailImage.onerror += err =>
						//{
						//	Console.WriteLine(
						//		"thumbnailImage onerror " +

						//		new
						//		{
						//			thumbnail,
						//			err,

						//			thumbnailImage.complete,
						//			thumbnailImage.width,
						//			thumbnailImage.naturalWidth,
						//			thumbnailImage.naturalHeight
						//		}
						//	);

						//};


						await thumbnailImage.async.oncomplete;


						Console.WriteLine(
							new { thumbnail, thumbnailImage.complete, thumbnailImage.width, thumbnailImage.naturalWidth, thumbnailImage.naturalHeight }
						);


						var thumbnailBytes = await thumbnailImage.async.bytes;

						Console.WriteLine(
							new { thumbnailBytes.Length }
						);


						// crc?
						var sw = Stopwatch.StartNew();

						var crc = CRCExample.ActionScript.Crc32Helper.GetCrc32(thumbnailBytes);

						// 247ms {{ crc = 9e47636d, ElapsedMilliseconds = 7 }}

						var isYTMissing = 0x9e47636d == crc;

						Console.WriteLine(
								new { crc = crc.ToString("x8"), sw.ElapsedMilliseconds, isYTMissing }
							  );

					}
				);
				#endregion

				var oncePerTab = new Dictionary<TabIdInteger, object>();

				chrome.tabs.Updated += async (i, x, tab) =>
				{

					// chrome://newtab/

					// https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150423

					#region tab
					if (tab == null)
					{
						Console.WriteLine("bugcheck :198 iframe? called with the wrong state?");
						return;
					}

					Console.WriteLine("enter async chrome.tabs.Updated " + new { tab.url, tab.status });


					if (tab.url.StartsWith("chrome-devtools://"))
					{
						return;
					}

					if (tab.url.StartsWith("chrome://"))
						return;


					// while running tabs.insertCSS: The extensions gallery cannot be scripted.
					if (tab.url.StartsWith("https://chrome.google.com/webstore/"))
						return;


					if (tab.status != "complete")
					{
						Console.WriteLine("exit async chrome.tabs.Updated, not complete?");
						return;
					}

					#endregion

					if (oncePerTab.ContainsKey(tab.id))
						return;

					oncePerTab[tab.id] = new object();

					// where is the hop to iframe?
					// X:\jsc.svn\examples\javascript\Test\TestSwitchToIFrame\TestSwitchToIFrame\Application.cs


					// https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150403

					//await (HopToChromeTab)tab.id;
					Console.WriteLine("chrome.tabs.Updated will delay, to increment state");

					// why do we need this fake await?
					// cannot resume state otherwise?
					await Task.Delay(1);

					// 
					// X:\jsc.svn\market\synergy\javascript\chrome\chrome\chrome.idl
					var tabIdString = Convert.ToString((object)tab.id);

					// 13032ms chrome.tabs.Updated will HopToChromeTab {{ tabIdString = 608 }}
					Console.WriteLine("chrome.tabs.Updated will HopToChromeTab " + new { tabIdString });
					// state1:
					await (HopToChromeTab)tab;

					// TypeError: Cannot set property 'ztabIdString' of null
					ztabIdString = tabIdString;

					//await tab.id;

					// are we now on the tab?
					// can we jump back?

					// 531ms yt found {{ Length = 108 }}
					// X:\jsc.svn\examples\javascript\test\TestShadowForIFrame\TestShadowForIFrame\Application.cs
					//var yt1 = Native.document.querySelectorAll(" [class='youtube-player']");

					// <iframe width="420" height="315" src="https://www.youtube.com/embed/sJIh70IZua8" frameborder="0" allowfullscreen=""></iframe>

					// 503ms create iframe... {{ ztabIdString = null }}
					// what about jumping with files/uploads?
					Console.WriteLine("create iframe... " + new { ztabIdString });



					iframe = new IHTMLIFrame {
						//src = "about:blank"


						//new XElement("button", "did extension send us our code? " )

						new XElement("script", new XAttribute("src", url), " ")

					}.AttachTo(
					   Native.document.documentElement
					   );


					var yt1 = Native.document.querySelectorAll("iframe");

					Console.WriteLine("yt found " + new { yt1.Length });
					yt1.WithEach(
						  async e =>
						  {
							  //if (e == null)
							  // return;

							  var xiframe = (IHTMLIFrame)e;

							  //13ms yt found { { Length = 9 } }
							  //VM1190: 51533 515ms enter catch
							  //{
							  // mname = < 01ed > ldloca.s.try } ClauseCatchLocal:
							  // VM1190: 51533 515ms TypeError: Cannot read property 'src' of null


							  if (!xiframe.src.StartsWith("https://www.youtube.com/"))
							  {
								  return;
							  }

							  // can we interact, swap the videos?

							  var size = new { xiframe.clientWidth, xiframe.clientHeight };

							  var swap = new IHTMLDiv
							  {
								  //new IHTMLPre { xiframe.src },

								  //new IHTMLContent {  }
							  };

							  new IStyle(swap)
							  {
								  backgroundColor = "yellow",

								  width = size.clientWidth + "px",
								  height = size.clientHeight + "px",
								  overflow = IStyle.OverflowEnum.hidden

							  };

							  // https://code.google.com/p/dart/issues/detail?id=19561
							  // 27ms HierarchyRequestError: Failed to execute 'createShadowRoot' on 'Element': Author-created shadow roots are disabled for this element.
							  //swap.AttachTo(xiframe.shadow);

							  xiframe.ReplaceWith(swap);



							  var sh = new IHTMLDiv { }.AttachTo(swap.shadow);

							  var vid = xiframe.src.TakeUntilIfAny("?").SkipUntilOrEmpty("/embed/");




							  //						  Remote Address:[2a00: 1450:400f:802::100e]:443
							  //Request URL: https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg
							  //Request Method: GET
							  //Status Code: 404 OK


							  var thumbnail404 = $"https://img.youtube.com/vi/{vid}/0.jpg";
							  // lets look at the image. is the video removed?
							  // https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg

							  // http://stackoverflow.com/questions/22097747/getimagedata-error-the-canvas-has-been-tainted-by-cross-origin-data

							  //.AttachToHead();


							  new IStyle(sh)
							  {
								  width = size.clientWidth + "px",
								  height = size.clientHeight + "px",
								  overflow = IStyle.OverflowEnum.hidden,
								  position = IStyle.PositionEnum.relative,

								  backgroundImage = $"url('{thumbnail404}')",

							  };

							  //var info = new IHTMLPre { xiframe.src };
							  var info = new IHTMLPre { new { vid } };
							  // so we can later find it again...
							  lookup_info[thumbnail404] = info;

							  // assume its not missing until we know more
							  lookup_info_YTmissing[thumbnail404] = false;

							  info.AttachTo(sh);


							  new IStyle(info)
							  {
								  backgroundColor = "rgba(0,0,255, 0.5)",
								  color = "rgba(255,255,0, 0.9)",

								  left = "0px",
								  bottom = "0px",
								  right = "0px",
								  //height = size.clientHeight + "px",

								  position = IStyle.PositionEnum.absolute
							  };

							  // at this point we need to consult the extension as it can download the bytes

							  new { }.With(
								  async delegate
								  {
									  var xtabIdString = ztabIdString;
									  var xthumbnail404 = thumbnail404;

									  // 517ms about to jump to extension to inspect the damn image... {{ xthumbnail404 = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, xtabIdString = 608 }}
									  Console.WriteLine("about to jump to extension to inspect the damn image... " + new { xthumbnail404, xtabIdString });
									  // fixup?
									  await Task.Delay(1);

									  await default(HopToExtension);


									  Console.WriteLine("about to jump to extension to inspect the damn image... done " + new { xthumbnail404, xtabIdString });
									  // 43228ms about to jump to extension to inspect the damn image... done {{ xthumbnail404 = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, xtabIdString = 608 }}



									  // can we jump back once we know what it was?
									  var thumbnailImage = new IHTMLImage
									  {
										  src = xthumbnail404
									  };

									  await thumbnailImage.async.oncomplete;
									  var thumbnailBytes = await thumbnailImage.async.bytes;
									  var sw = Stopwatch.StartNew();
									  var crc = CRCExample.ActionScript.Crc32Helper.GetCrc32(thumbnailBytes);

									  // we only do strings at this point, not integers, we could do booleans tho...
									  var isYTMissing = Convert.ToString(0x9e47636d == crc);

									  var xtab = await chrome.tabs.get(tabId: Convert.ToInt32(xtabIdString));

									  //xthumbnail404 = https://img.youtube.com/vi/BZIeqnQ1rY0/0.jpg, isYTMissing = false, xtabIdString = 608, url = https://zproxy.wordpress.com/2015/04/05/thought-form-magicians/ }}
									  //  xthumbnail404 = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, isYTMissing = true, xtabIdString = 608, url = https://zproxy.wordpress.com/2015/04/05/thought-form-magicians/ }}

									  Console.WriteLine(">> " + new { xthumbnail404, isYTMissing, xtabIdString, xtab.url });

									  // can we jump back to the tab to color it red if missing?
									  // 43340ms >> {{ xthumbnail404 = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, isYTMissing = true, xtabIdString = 608 }}

									  //(HopToChromeTab)

									  // ok now we now what tab we are in but even if we jump back. we wont have a ref to the infobar?

									  await (HopToChromeTab)xtab;

									  Console.WriteLine(">> " + new { xthumbnail404, isYTMissing, xtabIdString } + " back in the tab?");

									  // would the old variables be reconnected for us?
									  // jumps should be able to resume an old startemachine.

									  lookup_info_YTmissing[xthumbnail404] = Convert.ToBoolean(isYTMissing);

									  var xinfo = lookup_info[xthumbnail404];

									  //xthumbnail404 = https://img.youtube.com/vi/BZIeqnQ1rY0/0.jpg, isYTMissing = false, xtabIdString = 744 }} back in the tab?

									  if (Convert.ToBoolean(isYTMissing))
									  {
										  // yikes. video pulled!
										  new IStyle(xinfo)
										  {
											  backgroundColor = "rgba(255,0,0, 0.7)",
										  };

										  new IHTMLSpan { " do we have a local copy?" }.AttachTo(xinfo);

										  // we should send udp to the archive server?
										  // if it has how can we load it up?

										  return;
									  }

									  new IStyle(xinfo)
									  {
										  backgroundColor = "rgba(255,255,0, 0.5)",
									  };



								  }
							  );

							  // https://www.youtube.com/embed/jQLNMljadyo?vers
							  // https://www.youtube.com/embed/M4RBW85J4Cg
							  // http://img.youtube.com/vi/<insert-youtube-video-id-here>/0.jpg



							  await sh.async.onmouseover;

							  // no reason to load it. its missing!
							  if (lookup_info_YTmissing[thumbnail404])
								  return;

							  xiframe.AttachTo(sh);
							  info.AttachTo(sh);

							  var copyToToolbar = new IHTMLButton { "+" }.AttachTo(info);


							  await copyToToolbar.async.onclick;
							  copyToToolbar.Orphanize();

							  //width = "128px",
							  //xiframe.style.transform = "scale(0.2)";

							  new IStyle(xiframe)
							  {
								  width = (128) + "px",
								  height = (96) + "px",
							  };

							  // This video contains content from WMG. It is restricted from playback on certain sites.
							  xiframe.AttachTo(
								//iframe.contentWindow.document.documentElement
								iframe.contentWindow.document.body
							  );



						  }
					 );




					Console.WriteLine("create iframe... done");


					//iframe.allowTransparency = true;
					// https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150423
					// __8__1 is null. why? a struct?
					//     b.__this.__8__1.scope = new ctor$vQEABrCB_bTmuL0jGQp_bnVw(b.__this._iframe_5__2);

					// oh crap. the container is initialized before await (HopToChromeTab)tab; thus lost due to context switch.
					var scope = new { iframe };

					//Console.WriteLine("iframe visible? " + new { scope });

					new IStyle(iframe)
					{
						borderWidth = "0",

						// wont animate?

						transition = "left 300ms linear",

						// dont want the white box while it loads..
						backgroundColor = "rgba(0, 0, 255, 0)",

						position = IStyle.PositionEnum.@fixed,


						//left = "1px",
						top = "32px",
						width = "128px",

						// animateIFrame
						// pre hide it
						left = "-120px",

						//height = "100px",

						// wont work on slashdot?
						//bottom = "3em"

						// can we be topmost?
						//zIndex = 30000
						zIndex = 1999999999

					};

					fixHeight(iframe);
					animateIFrame(iframe);

					//var __iframe = iframe;
					await iframe.async.onload;




					//new IStyle(iframe)
					//{
					//	backgroundColor = "rgba(0, 0, 255, 0.7)",
					//};

					Console.WriteLine("lets hop from tab context to iframe context... ");
					await (HopToIFrame)iframe;

					Console.WriteLine("lets hop from tab context to iframe context... done!");


					new IStyle(Native.document.body)
					{
						margin = "0px",
						//marginRight = "1em",

						padding = "0px",
						paddingRight = "1em",

						transition = "background-color 300ms linear",
						backgroundColor = "rgba(0, 0, 255, 0.1)",

						//border = "1px solid red"
					};




					var button4 = new IHTMLButton { "hop to parent, extension, app" }.AttachToDocument();

					new IStyle(button4)
					{
						display = IStyle.DisplayEnum.block
					};

					// not yet. need a new example
					button4.disabled = true;



					//Native.body.backgroundColor = "rgba(0, 0, 255, 0.7)";

					//var text3 = new IHTMLTextArea { value = "hey" }.AttachToDocument();

					// need to use static, as scope variables are being encapsulated, and due to context jumps we dont support it yet
					text3 = new IHTMLTextArea { value = "hey" }.AttachToDocument();
					text3.style.width = "100%";

					var button3 = new IHTMLButton { "hop to parent, extension" }.AttachToDocument();

					new IStyle(button3)
					{
						display = IStyle.DisplayEnum.block
					};

					button3.onclick += async delegate
					{
						// can we hop back?

						var data3 = text3.value;
						Console.WriteLine("enter button3 " + new { data3 });
						// 2602ms enter button3 {{ data3 = hey }}

						// why do we need this fake await?
						// cannot resume state otherwise?
						await Task.Delay(1);

						await default(HopToParent);


						var tab_title = Native.document.title;

						// 3105ms are strings being synchronized to iframe? {{ tab_title = IANA — IANA-managed Reserved Domains, data3 = null }}
						Console.WriteLine("are strings being synchronized from iframe? " + new { tab_title, data3 });

						/// 2926ms will hop back to extension!? can we resume later?
						await default(HopToExtension);

						//Native.window.alert("hi! i am back home! do we even know which tab we were in? did i get some data yet? " + new { tab_title });
						Console.WriteLine("hi! i am back home! do we even know which tab we were in? did i get some data yet? " + new { tab_title, data3 });
						// 13844ms hi! i am back home! do we even know which tab we were in? did i get some data yet? {{ tab_title = IANA — IANA-managed Reserved Domains }}

						// lets guess which tab we clicked on?
						var tt = await chrome.tabs.getCurrent();

						// https://developer.chrome.com/extensions/tabs
						// https://developer.chrome.com/extensions/windows
						// https://developer.chrome.com/extensions/processes

						//chrome.runtime.
						new chrome.Notification(
							title: new { data3, tt }.ToString()

						);


						//chrome.tabs.rel

						// can we do appwindow here or we need to jump out of extension?
					};


					var button2 = new IHTMLButton { "hop to parent" }.AttachToDocument();

					new IStyle(button2)
					{
						display = IStyle.DisplayEnum.block
					};

					button2.onclick += async delegate
					{
						// can we hop back?

						Console.WriteLine("enter button2");

						// why do we need this fake await?
						// cannot resume state otherwise?
						await Task.Delay(1);

						await default(HopToParent);


						var tab_title = Native.document.title;

						Console.WriteLine("are strings being synchronized to iframe? " + new { tab_title });


						// we are jumping back, yet into a new state machine.
						//Native.window.alert("hi! in a tab, in an extension! " + new
						//{
						//	Native.document.title
						//	,
						//	iframe
						//});

						// can we jump back? is the iframe awaiting for multiple jumps?
						await (HopToIFrame)iframe;

						Native.window.alert("hi! iframe, in a tab, in an extension! " + new { Native.document.title, tab_title });

						// ok. we now know how to
						// jump from extension to tab to iframe to tab to iframe

						// what about workers, and jumping back to extension?


						// but likely we did not jump to the same data?


					};

					var button1 = new IHTMLButton { "click me" }.AttachToDocument();

					new IStyle(button1)
					{
						display = IStyle.DisplayEnum.block
					};

					//new { }.With(
					//	async delegate
					//	{
					//		// stack variables not visible, why?
					//		while (await button1.async.onmouseover)
					//		{
					//			new IStyle(Native.document.body)
					//			{
					//				backgroundColor = "rgba(0, 0, 255, 0.8)",
					//			};

					//			await button1.async.onmouseout;

					//			new IStyle(Native.document.body)
					//			{
					//				backgroundColor = "rgba(0, 0, 255, 0.2)",
					//			};
					//		}
					//	}
					//);

					//oldschool as a workaround


					button1.onclick += delegate
					{
						Native.window.alert("hi! iframe, in a tab, in an extension! " + new { Native.document.title });

					};


					button1.onmouseover +=
						e =>
						{
							new IStyle(Native.document.body)
							{
								backgroundColor = "rgba(255, 0, 0, 0.9)",
							};

							e.stopPropagation();
						};

					button1.onmouseout +=
						delegate
						{
							new IStyle(Native.document.body)
							{
								backgroundColor = "rgba(0, 0, 255, 0.1)",
							};
						};


					// we are in iframe!
					Native.document.onmouseover +=
						delegate
						{
							new IStyle(Native.document.body)
							{
								backgroundColor = "rgba(0, 0, 255, 0.3)",
							};
						};

					Native.document.onmouseout +=
						delegate
						{
							new IStyle(Native.document.body)
							{
								backgroundColor = "rgba(0, 0, 255, 0.1)",
							};
						};




					//var f = new IHTMLButton { "in the frame! click to notify parent" }.AttachToDocument();

					//await default(HopToParent);


					// why need this stackfix?
					//var stackfix_iframe = iframe;

					//               new { }.With(
					//	async delegate
					//	{
					//		while (await Native.window.async.onresize)
					//		{
					//			stackfix_iframe.style.height = (Native.window.Height - 64) + "px";
					//		}
					//	}
					//);


					// X:\jsc.svn\examples\javascript\Test\TestHopFromIFrame\TestHopFromIFrame\Application.cs
					// can we jump?

					// <div class="player-video-title">Ariana Grande - One Last Time (Official)</div>

					//Native.document.title = "(" + Native.document.title + ")";

					// X:\jsc.svn\examples\javascript\xml\FindByClassAndObserve\FindByClassAndObserve\Application.cs

					// luckyly its only hidden... no need to await the element and find it later

					// <span id="eow-title" class="watch-title " dir="ltr" title="THORnews Weird Weather Watch! Wind Dragon inbound to USA Pacific Coast!">


					//var yt0 = Native.document.querySelectorAll(" [class='player-video-title']");
					//var yt1 = Native.document.querySelectorAll(" [class='watch-title ']");

					//yt0.Concat(yt1).WithEach(
					//	 async e =>
					//	 {
					//		 do
					//		 {
					//			 Native.document.title = e.innerText;

					//			 // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
					//			 // we would need to jump back here to do extension notification
					//			 // the jump back would be to another state machine tho
					//			 // we would need other ports opened?

					//			 Native.document.documentElement.style.borderLeft = "1em solid yellow";
					//			 for (int xi = 0; xi < 5; xi++)
					//			 {
					//				 Native.body.style.borderLeft = "1em solid yellow";
					//				 await Task.Delay(100);
					//				 Native.body.style.borderLeft = "1em solid black";
					//				 await Task.Delay(100);
					//			 }
					//			 Native.document.documentElement.style.borderLeft = "1em solid red";

					//			 // or actually instead of jumping back we need to send back progress?
					//		 }
					//		 while (await e.async.onmutation);
					//	 }
					// );

					// lets start monitoring
				};



				return;
			}
			#endregion

			// 420ms TypeError: Cannot read property 'url' of null

			Console.WriteLine("nop");

#if true


			#region inside iframe
			if (Native.window.parent != Native.window)
			{
				// X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
				// inside iframe

				new { }.With(
					async delegate
					{
						// start the handshake
						// we gain intellisense, but the type is partal, likely not respawned, acivated, initialized 
						//var m = await Native.window.parent.postMessageAsync<TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine>();

						//	new IHTMLPre {
						//			"inside iframe awaiting onmessage"
						//}.AttachToDocument();

						// first null jump

						//Native.window.parent.postMessage(r.shadowstate);

						var m = await Native.window.parent.postMessageAsync(default(TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine));

						Console.WriteLine("iframe got the first state...");
						// we can now send one hop back?
						InternalInvoke(m.data);
					}
				);

				return;
			}
			#endregion

#endif

			Console.WriteLine("nop");

			// we made the jump?
			//Native.body.style.borderLeft = "0em solid red";

			// yes we did. can we talk to the chrome extension?

			// lets do some SETI

			// The runtime.onMessage event is fired in each content script running in the specified tab for the current extension.

			// Severity	Code	Description	Project	File	Line
			//Error       'runtime.onMessage' is inaccessible due to its protection level ChromeExtensionHopToTabThenIFrame X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs 272

			// public static event System.Action<object, object, object> Message

			Action<object> PostToExtension = null;

			#region Connect
			chrome.runtime.Connect +=
				 port =>
				 {
					 Console.WriteLine("chrome.runtime.Connect " + new { port.name, port.sender });

					 // 8295ms will invoke sendResponse... done?? {{ message = jump! }}
					 //port.postMessage("jump! " + new { port.name, port.sender });

					 PostToExtension = xdata =>
					 {
						 // PostToExtension {{ xdata = [object Object] }}
						 Console.WriteLine("PostToExtension " + new { xdata });
						 //Console.WriteLine("PostToExtension " + new { xdata = JSON.stringify(xdata) });

						 port.postMessage(xdata);
					 };
				 };
			#endregion

			#region chrome.runtime.Message
			chrome.runtime.Message += (object message, chrome.MessageSender sender, IFunction sendResponse) =>
			{
				var s = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

				if (url != null)
				{
					Console.WriteLine("jumping back to tab for more? done");

					InternalInvoke(s);

					return;
				}

				Console.WriteLine("chrome.runtime.Message " + new { s.state, sender.id, code = s.code.Length });
				// at this point we can initialize hop to iframe since we have the code we can actually use?

				// 276ms xonmessage {{ state = 1, id = fkgibadjpabiongmgoeomdbcefhabmah, code = 3296612 }}

				#region url
				var aFileParts = new[] { s.code };
				var oMyBlob = new Blob(aFileParts, new { type = "text/javascript" });
				//var url = oMyBlob.ToObjectURL();
				url = URL.createObjectURL(oMyBlob);
				#endregion



				Console.WriteLine("will we want to jump back to extension?");

				HopToExtension.VirtualOnCompleted +=
					(that, continuation) =>
					{
						Console.WriteLine("will hop back to extension!? can we resume later?");

						var r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);

						// can we only send once?
						//Console.WriteLine("will invoke sendResponse... " + new { sendResponse });
						Console.WriteLine("will invoke sendResponse... ");
						//sendResponse.apply(null, r);

						//will invoke sendResponse...
						//(program):51533 1664ms enter catch
						//{
						//	mname = < 0154 > ldarg.0.try } ClauseCatchLocal:
						//	(program):51533 1664ms TypeError: Converting circular structure to JSON

						// planB

						PostToExtension(r.shadowstate);
					};


				InternalInvoke(s);



				//Task.Delay(1000).ContinueWith(
				//	delegate
				//	{
				//		sendResponse.apply(null, "response");
				//	}
				//);

			};
			#endregion


			//         Native.window.onmessage += e =>
			//{

			//};
		}