/// <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 = null)
        {
            //            1b90:01:01 0046:0009 My.Solutions.Pages.Templates.Application create interface WebGLDopamineMolecule.AssetsLibrary::WebGLDopamineMolecule.HTML.Pages.IDefault
            //{ Location =
            // assembly: X:\jsc.svn\examples\javascript\My.Solutions.Pages.Templates\My.Solutions.Pages.Templates\bin\Debug\WebGLDopamineMolecule.exe
            // type: WebGLDopamineMolecule.Application, WebGLDopamineMolecule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
            // offset: 0x0587
            //  method:Void .ctor(WebGLDopamineMolecule.HTML.Pages.IDefault) }
            //1b90:01:01 RewriteToAssembly error: System.MissingMethodException: Method not found: 'Void ScriptCoreLib.JavaScript.DOM.IWindow.add_onframe(System.Action)'.

            glMatrix ref1;
            THREE.Color ref0;


            var h = Native.document.location.hash;


            // are we running as a clone?
            // if so our location hash should be stored as html.

            Native.document.getElementsByTagName("link").Select(k => (IHTMLLink)k).Where(k => k.rel == "location").ToList().ForEach(
                location =>
                {
                    //  href = file:///X:/temp/Spiral.htm#WebGLSpiral 

                    location.href.SkipUntilLastOrEmpty("#").With(
                        href =>
                        {
                            if (h == "")
                            {
                                h = "#" + href;
                            }

                        }
                    );
                }
            );



            DiagnosticsConsole.ApplicationContent.BindKeyboardToDiagnosticsConsole();


            Console.WriteLine("Templates loaded... " + new { Native.document.location, h });

            //{
            //    var html = new global::wolfenstein4kTemplate.HTML.Pages.DefaultPage();
            //    html.Container.AttachToDocument();
            //    new global::wolfenstein4kTemplate.Application(html);
            //}

            Action LoadEmAll = delegate { };

            var cc = new IHTMLCenter().AttachToDocument();
            cc.style.lineHeight = "0px";



            var cutoff = 480;

            #region iframe
            Action<int, int, double, IHTMLImage, string> iframe = (iwidth, iheight, maxextra, preview, alias) =>
            {
                // media selector?
                if (alias == "")
                {

                }

                var c = new IHTMLDiv().AttachTo(cc);

                //c.style.backgroundColor = JSColor.Black;
                c.style.display = IStyle.DisplayEnum.inline_block;
                c.style.position = IStyle.PositionEnum.relative;
                c.style.SetSize(iwidth, iheight);

                IHTMLElement content = preview;

                preview.style.SetLocation(0, 0);
                preview.AttachTo(c);
                preview.style.cursor = IStyle.CursorEnum.pointer;
                preview.title = "Click to activate, doubleclick to enlarge";

                var HasFocus = false;
                var HasMouse = false;


                Action content_SetExtraSize = delegate
                {

                };
                #region SetExtraSize
                var SetExtraSize = NumericEmitter.OfDouble(
                  (extrasizef, yy) =>
                  {

                      var extrasize = System.Convert.ToInt32(iwidth * extrasizef * 0.5);


                      content_SetExtraSize = delegate
                      {
                          content.style.zIndex = extrasize;




                          if (HasFocus)
                              content.style.boxShadow = "0px 0px " + (extrasize) + "px 0px rgba(255, 255, 0, 1)";
                          else
                              content.style.boxShadow = "0px 0px " + (extrasize) + "px 0px rgba(0, 0, 255, 1)";

                          //box-shadow: 0px 0px 70px 0px rgba(0, 0, 0, 1);

                          content.style.SetLocation(
                                System.Convert.ToInt32(iwidth * extrasizef * -0.5),
                              System.Convert.ToInt32(iheight * extrasizef * -0.5),
                              System.Convert.ToInt32(iwidth * (1 + extrasizef)),
                              System.Convert.ToInt32(iheight * (1 + extrasizef))
                          );
                      };

                      content_SetExtraSize();
                  }
              );
                #endregion


                #region HasMouse
                c.onmouseover +=
                 delegate
                 {
                     HasMouse = true;

                     if (HasFocus)
                         return;

                     SetExtraSize(maxextra, 0);
                 };




                c.onmouseout +=
                    delegate
                    {
                        HasMouse = false;

                        if (HasFocus)
                            return;

                        SetExtraSize(0, 0);
                    };
                #endregion


                #region Activate
                Action Activate =
                    delegate
                    {
                        // can we also do groups?

                        //preview.Orphanize();

                        var a = new IHTMLIFrame
                        {
                            width = iwidth,
                            height = iheight,
                            frameBorder = "0",
                            scrolling = "no",
                            allowFullScreen = true
                        }.AttachTo(c);

                        preview.style.Opacity = 0.7;


                        a.style.SetLocation(0, 0);



                        #region HasFocus
                        a.onload +=
                            delegate
                            {
                                //Native.Window.alert(
                                //    new {

                                //        a.contentWindow.performance.timing.connectStart,
                                //        a.contentWindow.performance.timing.loadEventStart,
                                //    }
                                //);

                                a.contentWindow.onblur +=
                                    delegate
                                    {
                                        HasFocus = false;
                                        if (HasMouse)
                                            SetExtraSize(maxextra * 1, 0);
                                        else
                                            SetExtraSize(0, 0);
                                    };

                                a.contentWindow.onfocus +=
                                    delegate
                                    {
                                        HasFocus = true;
                                        SetExtraSize(maxextra * 1.1, 0);
                                    };

                                if (HasMouse)
                                    a.contentWindow.focus();

                                new Timer(
                                    delegate
                                    {
                                        preview.FadeOut();

                                        new Timer(
                                          delegate
                                          {

                                              content = a;
                                              content_SetExtraSize();
                                          }
                                      ).StartTimeout(300);
                                    }
                                ).StartTimeout(1000);


                            };
                        #endregion



                        a.contentWindow.document.location.replace(alias);

                        //a.tabIndex = 1;





                    };

                LoadEmAll +=
                    delegate
                    {
                        if (Activate == null)
                            return;

                        Activate();
                        Activate = null;
                    };

                c.onclick +=
                    delegate
                    {
                        if (Activate == null)
                            return;

                        Activate();
                        Activate = null;

                        // unsubscribe event;
                    };
                #endregion






                SetExtraSize(0, 0);

            };
            #endregion



            #region y
            Action<string, Action, IHTMLImage> y =
                (alias, yield, preview) =>
                {
                    if (h == "")
                        if (Native.window.Width > cutoff)
                            iframe(96, 96, 3, preview, alias);
                        else
                            iframe(32, 32, 3, preview, alias);
                    else if (h == alias)
                        if (yield != null)
                            yield();
                };
            #endregion

            // jsc cannot handle multiple delegates on the same statement yet.


            y("#WebGLDopamineMolecule", () => new WebGLDopamineMolecule.Application(), new WebGLDopamineMolecule.HTML.Images.FromAssets.Preview());
            y("#WebGLEthanolMolecule", () => new WebGLEthanolMolecule.Application(), new WebGLEthanolMolecule.HTML.Images.FromAssets.Preview());
            y("#WebGLYomotsuTPS", () => new WebGLYomotsuTPS.Application(), new WebGLYomotsuTPS.HTML.Images.FromAssets.Preview());
            y("#WebGLYomotsuMD2Model", () => new WebGLYomotsuMD2Model.Application(), new WebGLYomotsuMD2Model.HTML.Images.FromAssets.Preview());
            y("#WebGLSphereRayTrace", () => new WebGLSphereRayTrace.Application(), new WebGLSphereRayTrace.HTML.Images.FromAssets.Preview());
            //y("#WebGLFireballExplosion", () => new WebGLFireballExplosion.Application(), new WebGLFireballExplosion.HTML.Images.FromAssets.Preview());
            y("#WebGLChocolux", () => new WebGLChocolux.Application(), new WebGLChocolux.HTML.Images.FromAssets.Preview());
            //y("#WebGLPuls", () => new WebGLPuls.Application(), new WebGLPuls.HTML.Images.FromAssets.Preview());
            y("#WebGLCelShader", () => new WebGLCelShader.Application(), new WebGLCelShader.HTML.Images.FromAssets.Preview());
            y("#WebGLClouds", () => new WebGLClouds.Application(), new WebGLClouds.HTML.Images.FromAssets.Preview());
            y("#WebGLCone", () => new WebGLCone.Application(), new WebGLCone.HTML.Images.FromAssets.Preview());
            y("#WebGLShaderDisturb", () => new WebGLShaderDisturb.Application(), new WebGLShaderDisturb.HTML.Images.FromAssets.Preview());
            y("#WebGLDynamicTerrainTemplate", () => new WebGLDynamicTerrainTemplate.Application(), new WebGLDynamicTerrainTemplate.HTML.Images.FromAssets.Preview());
            y("#WebGLEscherDrosteEffect", () => new WebGLEscherDrosteEffect.Application(), new WebGLEscherDrosteEffect.HTML.Images.FromAssets.Preview());
            y("#WebGLInvade", () => new WebGLInvade.Application(), new WebGLInvade.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson01", () => new WebGLLesson01.Application(), new WebGLLesson01.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson02", () => new WebGLLesson02.Application(), new WebGLLesson02.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson03", () => new WebGLLesson03.Application(), new WebGLLesson03.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson04", () => new WebGLLesson04.Application(), new WebGLLesson04.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson05", () => new WebGLLesson05.Application(), new WebGLLesson05.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson06", () => new WebGLLesson06.Application(), new WebGLLesson06.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson07", () => new WebGLLesson07.Application(), new WebGLLesson07.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson08", () => new WebGLLesson08.Application(), new WebGLLesson08.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson09", () => new WebGLLesson09.Application(), new WebGLLesson09.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson10", () => new WebGLLesson10.Application(), new WebGLLesson10.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson11", () => new WebGLLesson11.Application(), new WebGLLesson11.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson12", () => new WebGLLesson12.Application(), new WebGLLesson12.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson13", () => new WebGLLesson13.Application(), new WebGLLesson13.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson14", () => new WebGLLesson14.Application(), new WebGLLesson14.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson15", () => new WebGLLesson15.Application(), new WebGLLesson15.HTML.Images.FromAssets.Preview());
            y("#WebGLLesson16", () => new WebGLLesson16.Application(), new WebGLLesson16.HTML.Images.FromAssets.Preview());
            y("#WebGLNyanCat", () => new WebGLNyanCat.Application(), new WebGLNyanCat.HTML.Images.FromAssets.Preview());
            y("#WebGLPlanetGenerator", () => new WebGLPlanetGenerator.Application(), new WebGLPlanetGenerator.HTML.Images.FromAssets.Preview());
            y("#WebGLSimpleCubic", () => new WebGLSimpleCubic.Application(), new WebGLSimpleCubic.HTML.Images.FromAssets.Preview());
            y("#SpiderModel", () => new SpiderModel.Application(), new SpiderModel.HTML.Images.FromAssets.Preview());
            y("#WebGLWindWheel", () => new WebGLWindWheel.Application(), new WebGLWindWheel.HTML.Images.FromAssets.Preview());
            y("#WebGLTunnel", () => new WebGLTunnel.Application(), new WebGLTunnel.HTML.Images.FromAssets.Preview());
            y("#WebGLSpiral", () => new WebGLSpiral.Application(), new WebGLSpiral.HTML.Images.FromAssets.Preview());

            y("#WebGLCannonPhysicsEngine", () => new WebGLCannonPhysicsEngine.Application(), new WebGLCannonPhysicsEngine.HTML.Images.FromAssets.Preview());
            y("#WebGLBossHarvesterByOutsideOfSociety", () => new WebGLBossHarvesterByOutsideOfSociety.Application(), new WebGLBossHarvesterByOutsideOfSociety.HTML.Images.FromAssets.Preview());
            y("#WoodsXmasByRobert", () => new WoodsXmasByRobert.Application(), new WoodsXmasByRobert.HTML.Images.FromAssets.Preview());
            //y("#WebGLBeachballsByDoob", () => new WebGLBeachballsByDoob.Application(), new WebGLBeachballsByDoob.HTML.Images.FromAssets.Preview());

            y("#WebGLCity", () => new WebGLCity.Application(), new WebGLCity.HTML.Images.FromAssets.Preview());

            // glMatrix
            y("#WebGLHand", () => new WebGLHand.Application(), new WebGLHand.HTML.Images.FromAssets.Preview());
            y("#WebGLSpadeWarrior", () => new WebGLSpadeWarrior.Application(), new WebGLSpadeWarrior.HTML.Images.FromAssets.Preview());

            if (h == "")
            {
                var maxextra = 3;
                var iwidth = 96;
                var iheight = 96;


                if (Native.window.Width > cutoff)
                {
                    iframe(iwidth, iheight, maxextra, new HTML.Images.FromAssets.Preview(), "");
                    //iframe(iwidth, iheight, maxextra, new HTML.Images.FromAssets.Preview(), "");

                    new IHTMLButton { innerText = "Fullscreen" }.With(
                        btn =>
                        {
                            btn.style.position = IStyle.PositionEnum.absolute;
                            btn.style.left = "1em";
                            btn.style.bottom = "1em";

                            btn.onclick +=
                                  delegate
                                  {
                                      Native.Document.body.requestFullscreen();
                                  };


                        }
                    ).AttachToDocument();

                    new IHTMLButton { innerText = "Load Em All" }.With(
                        btn =>
                        {
                            btn.style.position = IStyle.PositionEnum.absolute;
                            btn.style.right = "1em";
                            btn.style.bottom = "1em";

                            btn.onclick +=
                                delegate
                                {
                                    btn.Orphanize();

                                    LoadEmAll();
                                };
                        }
                    ).AttachToDocument();
                }
                else
                {
                    iwidth = 32;
                    iheight = 32;
                }

                #region ApplyMargins
                Action ApplyMargins = delegate
                {
                    if (Native.window.Width < cutoff)
                    {
                        cc.style.margin = "0px";
                    }
                    else
                    {
                        cc.style.margin = "3%";
                        cc.style.marginTop = "10%";
                    }
                };

                ApplyMargins();

                Native.window.onresize +=
                    delegate
                    {
                        ApplyMargins();
                    };
                #endregion

                #region requestFullscreen
                Native.Document.body.ondblclick +=
                    delegate
                    {
                        //if (IsDisposed)
                        //    return;

                        // http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/

                        Native.Document.body.requestFullscreen();

                        //AtResize();
                    };
                #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)
        {
            // what if cache does not have our package, if we are a new project?
            // packages.config
            // <package id="Abstractatech.JavaScript.CODE128" version="1.0.0.0" targetFramework="net40" />
            // "C:\Users\Arvo\AppData\Local\NuGet\Cache\Abstractatech.JavaScript.CODE128.1.0.0.0.nupkg"



            {
                var data = new { foo = "text" }.ToString();


                data.ToCode128(
                    height: 20,
                    yield:
                        img =>
                        {
                            var c = new IHTMLCenter().AttachToDocument();

                            img.AttachTo(c);

                            new IHTMLBreak { }.AttachTo(c);
                            new IHTMLCode { innerText = data }.AttachTo(c).style.fontSize = "x-small";
                        }
                );
            }


            {
                var data = "1234567890";


                data.ToCode128(
                    height: 20,
                    yield:
                        img =>
                        {
                            var c = new IHTMLCenter().AttachToDocument();

                            img.AttachTo(c);
                            new IHTMLBreak { }.AttachTo(c);
                            new IHTMLCode { innerText = data }.AttachTo(c).style.fontSize = "x-small";
                        }
                );
            }

            IStyleSheet.Default.AddRule(".foo",
                r =>
                {
                    r.style.border = "1px solid black";
                    r.style.margin = "2em";
                }
            );

            Native.document.getElementsByClassName("foo").ToArray().WithEach(
                x =>
                {
                    (x.getAttribute("data-value") as string).With(
                        data =>
                        {
                            data.ToCode128(
                                  height: 20,
                                  yield:
                                      img =>
                                      {
                                          var c = new IHTMLCenter().AttachTo(x);

                                          img.AttachTo(c);
                                          new IHTMLBreak { }.AttachTo(c);
                                          new IHTMLCode { innerText = data }.AttachTo(c).style.fontSize = "x-small";
                                      }
                              );
                        }
                    );
                }
            );
        }
		/// <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(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)
        {
            #region IsRightScreen || IsLeftScreen
            var IsRightScreen = Native.Document.location.hash == "#/RightScreen";
            var IsLeftScreen = Native.Document.location.hash == "#/LeftScreen";

            if (IsRightScreen || IsLeftScreen)
            {
                if (IsRightScreen)
                {
                    "Right Screen".ToDocumentTitle();
                }

                if (IsLeftScreen)
                {
                    "Left Screen".ToDocumentTitle();
                }

                Native.Document.body.Clear();

                var a = new CSSTransform3DFPSBlueprint.HTML.Pages.App();

                a.Container.AttachToDocument();


                var hud = new IHTMLDiv().AttachToDocument();

                hud.style.position = IStyle.PositionEnum.absolute;
                hud.style.left = "0px";
                hud.style.top = "0px";
                hud.style.right = "0px";
                //hud.style.height = "2em";
                hud.style.zIndex = 1000;
                hud.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
                hud.style.color = JSColor.White;

                var c = new IHTMLCenter { innerText = Native.Document.location.hash }.AttachTo(hud);

                new CSSTransform3DFPSBlueprint.Application().Initialize(a,
                   x =>
                   {
                       // we know that we are packaging this sub page 
                       // in our web app
                       x.floorplan.deskCube22.LeftWallSource = "/__Templates";
                       x.floorplan.deskCube22.LeftWallSourceAutoLoad = true;


                       var w = CSSTransform3DFPSBlueprint.Application.window;


                       var du = true;
                       var qx = new delta();
                       var qy = new delta();
                       var qz = new delta();
                       var qp = new delta();

                       x.AfterKeystateChange +=
                        delegate
                        {
                            var data = new XElement("keyState",
                                new XAttribute("w", "" + w.keyState.forward),
                                new XAttribute("s", "" + w.keyState.backward),
                                new XAttribute("a", "" + w.keyState.strafeleft),
                                new XAttribute("d", "" + w.keyState.straferight)
                            );

                            Native.Window.opener.With(
                                parent =>
                                {
                                    //c.innerText = data.ToString();

                                    parent.postMessage(data.ToString());
                                }
                            );

                        };

                       x.AfterCameraRotationChange +=
                           delegate
                           {
                               var data = new XElement("viewport.camera.rotation",
                                   new XAttribute("x", "" + w.viewport.camera.rotation.x),
                                   new XAttribute("y", "" + w.viewport.camera.rotation.y),
                                   new XAttribute("z", "" + w.viewport.camera.rotation.z)
                               );

                               Native.Window.opener.With(
                                   parent =>
                                   {
                                       //c.innerText = data.ToString();

                                       parent.postMessage(data.ToString());
                                   }
                               );

                           };

                       Func<string, bool> bool_Parse =
                           xx =>
                           {
                               return xx.ToLower() == "true";
                           };

                       Native.Window.onmessage +=
                            e =>
                            {
                                var data = XElement.Parse("" + e.data);

                                #region shared.perspective
                                if (data.Name.LocalName == "shared.perspective")
                                {
                                    w.viewport.node.style.width = "200%";

                                    if (IsRightScreen)
                                    {
                                        w.viewport.node.style.marginLeft = "-100%";

                                    }


                                    CSSTransform3DFPSBlueprint.Application.window.viewport.node.style.marginTop = "-25%";
                                    w.viewport.node.style.height = "150%";






                                    //if (IsRightScreen)
                                    //{
                                    //}
                                }
                                #endregion

                                var hasupdate = true;

                                if (data.Name.LocalName == "keyState")
                                {
                                    w.keyState.forward = bool_Parse(data.Attribute("w").Value);
                                    w.keyState.backward = bool_Parse(data.Attribute("s").Value);
                                    w.keyState.strafeleft = bool_Parse(data.Attribute("a").Value);
                                    w.keyState.straferight = bool_Parse(data.Attribute("d").Value);


                                }


                                if (data.Name.LocalName == "viewport.camera.rotation")
                                {
                                    new
                                    {
                                        x = int.Parse(data.Attribute("x").Value),
                                        y = int.Parse(data.Attribute("y").Value),
                                        z = int.Parse(data.Attribute("z").Value)
                                    }.With(
                                        r =>
                                        {
                                            w.viewport.camera.rotation.x = r.x;
                                            w.viewport.camera.rotation.y = r.y;
                                            w.viewport.camera.rotation.z = r.z;

                                        }
                                    );
                                }

                                if (data.Name.LocalName == "ChangeRotationBy")
                                {
                                    new
                                    {
                                        x = int.Parse(data.Attribute("x").Value),
                                        y = int.Parse(data.Attribute("y").Value),
                                    }.With(
                                        r =>
                                        {
                                            w.viewport.camera.rotation.x -= r.y;
                                            w.viewport.camera.rotation.z += r.x;

                                        }
                                    );
                                }


                                if (data.Name.LocalName == "range")
                                {
                                    qx.newvalue = int.Parse(data.Attribute("x").Value);
                                    qy.newvalue = int.Parse(data.Attribute("y").Value);
                                    qz.newvalue = int.Parse(data.Attribute("z").Value);
                                    var s = int.Parse(data.Attribute("s").Value) / 50.0;

                                    s *= s;
                                    s *= s;

                                    qp.newvalue = int.Parse(data.Attribute("p").Value);

                                    if (du)
                                    {
                                        qx.oldvalue = qx.newvalue;
                                        qy.oldvalue = qy.newvalue;
                                        qz.oldvalue = qz.newvalue;
                                        qp.oldvalue = qp.newvalue;
                                        du = false;
                                    }
                                    else
                                    {
                                        hasupdate = false;

                                        if (qx.newvalue != qx.oldvalue)
                                        {
                                            qx.dx = qx.newvalue - qx.oldvalue;
                                            qx.oldvalue = qx.newvalue;
                                            w.viewport.camera.rotation.x -= qx.dx * 0.2 * s;
                                            hasupdate = true;
                                        }

                                        if (qy.newvalue != qy.oldvalue)
                                        {
                                            qy.dx = qy.newvalue - qy.oldvalue;
                                            qy.oldvalue = qy.newvalue;

                                            var newy = w.viewport.camera.rotation.y - qy.dx * 0.1 * s;

                                            //Console.WriteLine(
                                            //     new
                                            //     {
                                            //         w.viewport.camera.rotation.y,
                                            //         newy
                                            //     }
                                            //);

                                            // { y = 0.09999999999999937, newy = -6.38378239159465e-16 }
                                            //-6.38378239159465e-16
                                            // small values cause an anomaly?
                                            if (Math.Abs(newy) < 0.05)
                                                w.viewport.camera.rotation.y = 0;
                                            else
                                                w.viewport.camera.rotation.y = newy;
                                            hasupdate = true;
                                        }

                                        if (qz.newvalue != qz.oldvalue)
                                        {
                                            qz.dx = qz.newvalue - qz.oldvalue;
                                            qz.oldvalue = qz.newvalue;
                                            w.viewport.camera.rotation.z -= qz.dx * 0.5 * s;
                                            hasupdate = true;
                                        }


                                        if (qp.newvalue != qp.oldvalue)
                                        {
                                            //qz.dx = qz.newvalue - qz.oldvalue;
                                            qp.oldvalue = qp.newvalue;
                                            w.viewport.node.style.perspective = "" + (500 + qp.newvalue * 4 * s);
                                            hasupdate = true;
                                        }
                                    }



                                }

                                //c.innerText = new { data, dx, newvalue, oldvalue }.ToString();

                                if (hasupdate)
                                    c.innerText = data.ToString();


                                //oldvalue = newvalue;
                                //w.viewport.camera.rotation.x -= e.movementY / 2;

                            };
                   }
               );




                return;
            }
            #endregion

            Action range_onchange = delegate
            {
            };

            #region bind
            Action<IHTMLButton, string, Action<IWindow, XElement>> bind =
                (btn, hash, yield) =>
                {
                    btn.onclick +=
                        delegate
                        {
                            btn.disabled = true;

                            var w = Native.Window.open(
                                hash,
                                "_blank",
                                400,
                                300,
                                false
                            );

                            w.focus();

                            w.onload +=
                                delegate
                                {
                                    Action onchange =
                                        delegate
                                        {


                                            //                       JellyworldExperiment.DualView.Application+<>c__DisplayClassc+<>c__DisplayClass14+<>c__DisplayClass16+<>c__DisplayClass18
                                            //script: error JSC1000: Method: <.ctor>b__7, Type: JellyworldExperiment.DualView.Application+<>c__DisplayClassc+<>c__DisplayClass14+<>c__DisplayClass16+<>c__DisplayClass18; emmiting failed : System.ArgumentNullException: Value cannot be null.
                                            //   at jsc.ILFlowStackItem.InlineLogic(   )
                                            //   at  .    .    ( ?   ,    , ILInstruction , ILFlowStackItem )
                                            //   at  .    .    ( ?   ,    , ILInstruction , ILFlowStackItem )
                                            //   at  . ?  .    (   , ILInstruction , ILFlowStackItem[] , Int32 , MethodBase )

                                            var xml = new XElement("range",
                                              new XAttribute("x", page.range_x.value),
                                              new XAttribute("y", page.range_y.value),
                                              new XAttribute("z", page.range_z.value),
                                              new XAttribute("s", page.range_s.value),
                                              new XAttribute("p", page.range_p.value)
                                          );

                                            w.postMessage(xml.ToString());

                                        };

                                    onchange();

                                    page.range_x.onchange +=
                                        delegate
                                        {
                                            onchange();
                                        };
                                    page.range_y.onchange +=
                                        delegate
                                        {
                                            onchange();
                                        };
                                    page.range_z.onchange +=
                                        delegate
                                        {
                                            onchange();
                                        };
                                    page.range_s.onchange +=
                                     delegate
                                     {
                                         onchange();
                                     };

                                    page.range_p.onchange +=
                                        delegate
                                        {
                                            onchange();
                                        };

                                    range_onchange += onchange;

                                    Native.Window.onmessage +=
                                         e =>
                                         {
                                             if (e.source != w)
                                                 return;

                                             var data = XElement.Parse("" + e.data);

                                             yield(w, data);

                                         };

                                    yield(w, null);
                                };
                        };


                };
            #endregion

            #region do bind
            var wLeftScreen = default(IWindow);
            var wRightScreen = default(IWindow);

            bind(page._LeftScreen, "#/LeftScreen",
                (w, data) =>
                {
                    if (wLeftScreen == null)
                    {
                        wLeftScreen = w;

                        w.onbeforeunload +=
                            delegate
                            {
                                page._LeftScreen.innerText = "closed";
                            };

                        Native.Window.onbeforeunload +=
                            delegate
                            {
                                wLeftScreen.close();
                            };
                    }


                    if (data != null)
                    {
                        page._LeftScreen.innerText = data.ToString();

                        if (wRightScreen != null)
                        {
                            wRightScreen.postMessage(data.ToString());
                        }
                    }
                }
            );

            bind(page._RightScreen, "#/RightScreen",
                (w, data) =>
                {
                    if (wRightScreen == null)
                    {
                        wRightScreen = w;

                        w.onbeforeunload +=
                             delegate
                             {
                                 page._RightScreen.innerText = "closed";
                             };


                        Native.Window.onbeforeunload +=
                            delegate
                            {
                                wRightScreen.close();
                            };
                    }

                    if (data != null)
                    {
                        page._RightScreen.innerText = data.ToString();


                        if (wLeftScreen != null)
                        {
                            wLeftScreen.postMessage(data.ToString());
                        }
                    }
                }
            );
            #endregion

            page._SharedPerspective.onclick +=
                delegate
                {
                    var data = new XElement("shared.perspective", "dummy");

                    if (wLeftScreen != null)
                        wLeftScreen.postMessage(data.ToString());

                    if (wRightScreen != null)
                        wRightScreen.postMessage(data.ToString());


                };

            forward = false;
            backward = false;
            strafeleft = false;
            straferight = false;

            this.AfterKeystateChange =
                delegate
                {
                    var data = new XElement("keyState",
                           new XAttribute("w", "" + forward),
                           new XAttribute("s", "" + backward),
                           new XAttribute("a", "" + strafeleft),
                           new XAttribute("d", "" + straferight)
                       );

                    Console.WriteLine("AfterKeystateChange: " + data);

                    if (wLeftScreen != null)
                        wLeftScreen.postMessage(data.ToString());

                    if (wRightScreen != null)
                        wRightScreen.postMessage(data.ToString());

                };

            ChangeRotationBy =
                (x, y) =>
                {
                    var data = new XElement("ChangeRotationBy",
                        new XAttribute("x", "" + x),
                        new XAttribute("y", "" + y)
                    );

                    Console.WriteLine("AfterKeystateChange: " + data);

                    if (wLeftScreen != null)
                        wLeftScreen.postMessage(data.ToString());

                    if (wRightScreen != null)
                        wRightScreen.postMessage(data.ToString());
                };

            #region onkeydown
            Native.Document.body.onkeydown += e =>
            {
                //Console.WriteLine(new { e.KeyCode });

                if (e.KeyCode == (int)Keys.W)
                    forward = true;
                if (e.KeyCode == (int)Keys.S)
                    backward = true;
                if (e.KeyCode == (int)Keys.A)
                    strafeleft = true;
                if (e.KeyCode == (int)Keys.D)
                    straferight = true;

                if (AfterKeystateChange != null)
                    AfterKeystateChange();
            };

            Native.Document.body.onkeyup += e =>
            {
                if (e.KeyCode == (int)Keys.W)
                    forward = false;
                if (e.KeyCode == (int)Keys.S)
                    backward = false;

                if (e.KeyCode == (int)Keys.A)
                    strafeleft = false;
                if (e.KeyCode == (int)Keys.D)
                    straferight = false;

                if (AfterKeystateChange != null)
                    AfterKeystateChange();
            };
            #endregion

            #region FaceDetectedAt

            var attimer = false;
            ScriptCoreLib.JavaScript.Runtime.Timer t = null;

            FaceDetectedAt =
                (Left, Top, Width, Height) =>
                {
                    page.SimulateFace.disabled = true;

                    var f = new { Left, Top, Width, Height };


                    if (t != null)
                        t.Stop();

                    t = new ScriptCoreLib.JavaScript.Runtime.Timer(
                        delegate
                        {
                            attimer = true;
                            FaceDetectedAt(Left, Top, Width, Height);
                        }
                    );

                    t.StartInterval(1000 / 100);

                    page.range_x.value = "" + (100 - Math.Max(0, (100 * f.Top / (Native.Window.Height - f.Height))).Min(100));

                    //Console.WriteLine(new { f, page.range_x.value });

                    var range_y_old = int.Parse(page.range_y.value);
                    var range_z_old = int.Parse(page.range_z.value);
                    var range_z_new =
                        (int)(100.0 * f.Left / (Native.Window.Width - f.Width)).Max(0).Min(100);

                    page.range_z.value = "" + range_z_new;

                    if (range_z_old == range_z_new)
                    {
                        if (attimer)
                        {
                            attimer = false;

                            if (range_y_old != 50)
                            {
                                if (range_y_old > 50)
                                    page.range_y.value = "" + (int)(range_y_old - 1);
                                else
                                    page.range_y.value = "" + (int)(range_y_old + 1);
                            }
                        }
                    }
                    else
                    {
                        //var range_y_new = (Math.Sign(range_z_old - range_z_new) * 4 + range_y_old).Min(100).Max(0);

                        //page.range_y.value = "" + range_y_new;
                    }


                    range_onchange();
                };
            #endregion


            Native.Document.body.onmousedown +=
                e =>
                {
                    if (e.Element != page.AskForDragPermission)
                        if (e.Element != Native.Document.body)
                        {
                            return;
                        }

                    e.preventDefault();

                    Native.Document.body.requestPointerLock();
                };

            Native.Document.body.onmousemove +=
                e =>
                {
                    if (Native.Document.pointerLockElement != Native.Document.body)
                        return;


                    this.ChangeRotationBy(
                        e.movementX,
                        e.movementY
                    );

                };

            Native.Document.body.onmouseup +=
               e =>
               {
                   if (Native.Document.pointerLockElement != Native.Document.body)
                       return;

                   Native.Document.exitPointerLock();
               };


            page.SimulateFace.onclick +=
                delegate
                {
                    page.SimulateFace.disabled = true;

                    new Form { Text = "Simulated Face Detection" }.With(
                        f =>
                        {
                            f.LocationChanged +=
                                delegate
                                {
                                    FaceDetectedAt(f.Left, f.Top, f.Width, f.Height);
                                };

                            f.SizeChanged +=
                                delegate
                                {
                                    FaceDetectedAt(f.Left, f.Top, f.Width, f.Height);
                                };

                        }
                    ).Show();


                };
        }
        // publish this method under ScriptCoreLib.Extensions for 50€, hide everything else that needs to go along..
        // async supported yet?

        // [IHTMLMeta.AttachToHead(http-equiv: "X-UA-Compatible", content: "IE=10")]
        public static /* async */ void ToCode128(this string data, int width = 2, int height = 50, Action<IHTMLImage> yield = null)
        {
            // for IE web browser control we would also need this:
            // <meta http-equiv="X-UA-Compatible" content="IE=10" />

            // load only once?
            // IE never fires ?
            new Abstractatech.JavaScript.CODE128.Design.CODE128().Content.AttachToDocument().onload +=
             delegate
             {

                 var options =
                              new
                              {
                                  width,
                                  height,

                                  quite = 10
                              };


                 // idl?

                 // dynamic?
                 //dynamic xx = new object();
                 //var xxx = new xx();

                 var encoder = new IFunction("e", "return new CODE128(e)").apply(null, data);

                 var binary = (string)new IFunction("e", "return e.encoded()").apply(null, encoder);


                 var ctx = new CanvasRenderingContext2D();
                 var canvas = ctx.canvas;

                 //Set the width and height of the barcode
                 canvas.width = binary.Length * options.width + 2 * options.quite;
                 canvas.height = options.height;

                 //Paint the canvas white
                 ctx.fillStyle = "#fff";
                 ctx.fillRect(0, 0, canvas.width, canvas.height);

                 //Creates the barcode out of the encoded binary
                 for (var i = 0; i < binary.Length; i++)
                 {

                     var x = i * options.width + options.quite;

                     if (binary[i] == '1')
                     {
                         ctx.fillStyle = "#000";
                     }
                     else
                     {
                         ctx.fillStyle = "#fff";
                     }

                     ctx.fillRect(x, 0, options.width, options.height);
                 }

                 //Grab the dataUri from the canvas
                 var uri = canvas.toDataURL("image/png");


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

                 var img = new IHTMLImage { src = uri };


                 yield(img);

             };

        }
        /// <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 data = "1234";


            data.ToCode128(
                height: 20,
                yield:
                    img =>
                    {
                        var c = new IHTMLCenter().AttachToDocument();

                        img.AttachTo(c);
                        new IHTMLBreak { }.AttachTo(c);
                        new IHTMLCode { innerText = data }.AttachTo(c).style.fontSize = "x-small";
                    }
            );



        }