/// <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)
        {

            //            will skip DefineVersionInfoResource
            //2b5c:02:01:1e RewriteToAssembly error: System.NotSupportedException: Type 'xchrome.BCLImplementation.System.Net.Sockets.__TcpListener' was not completed.

            // Uncaught ReferenceError: kvYlVNrcg0qBT40xR_bUt6Q is not defined 

            // it does work, yet chrome server is a slow asset server for now..

#if false
            #region AtFormCreated
            FormStyler.AtFormCreated =
                 s =>
                 {
                     s.Context.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

                     var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDrag().AttachTo(s.Context.GetHTMLTarget());
                 };
            #endregion



            #region ChromeTCPServer
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                chrome.Notification.DefaultTitle = "Craft";
                chrome.Notification.DefaultIconUrl = new HTML.Images.FromAssets.Preview().src;

                ChromeTCPServer.TheServerWithStyledForm.Invoke(
                    AppSource.Text,
                    AtFormCreated: FormStyler.AtFormCreated
                );

                return;
            }
            #endregion



#endif



            // Process com.abstractatech.gamification.craft (pid 1456) has died.
            // http://stackoverflow.com/questions/7316680/process-has-died

            // http://zproxy.wordpress.com/2012/11/13/dos-warcraft/
            // load the shadow land


            // why does this not work??
            page.body.style.cursorImage = new severed();
            page.Preview.style.cursorImage = new guantlet();
            page.Avatar.style.cursorImage = new guantlet();

            // http://www.effectgames.com/effect/article.psp.html/joe/Old_School_Color_Cycling_with_HTML5
            // http://www.effectgames.com/demos/canvascycle/
            // http://productforums.google.com/forum/#!topic/chrome/hgxRgmT0INY
            // http://www.boutell.com/newfaq/creating/midi.html
            //new com.abstractatech.gamification.craft.HTML.Audio.FromAssets.intro().AttachToHead().play();

            // http://www.javascripter.net/faq/sound/play.htm

            new HTML.Audio.FromAssets.IntroWarII { loop = true, volume = 0.5 }.play();

            //new IHTMLObject
            //{
            //    data =
            //        new com.abstractatech.gamification.craft.HTML.Audio.FromAssets.intro().src
            //}.AttachToHead();

            //            <object data="mysong.mid">
            //<param name="loop" value="10"/>
            //If you're seeing this, you don't have a MIDI player
            //on your computer.
            //</object>


            // IStyleSheet.Default.AddRule("body", "cursor: url('" + new cursor().src + "'), auto;", 0);
            // 

            // do we have to use MIDI.js?
            //new HTML.Audio.FromAssets.Warcraft1_TitleTheme().play();

            #region OrcSounds
            var orc = new Func<Action>(
                delegate
                {
                    //                    I/ChromiumHTTPDataSourceSupport(  124): Request failed with status 4 and os_error -102
                    //I/chromium(27962): [INFO:CONSOLE(40699)] "Uncaught InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable.", source: http://192.168.43.7:18906/view-source (40699)

                    var nodes = new OrcSounds().AudioElements()

                        // will we run out of memory?
                        //.Take(2)

                        .ToArray();

                    nodes.WithEach(a => a.load());

                    return delegate
                    {
                        var r = new Random().Next();
                        var i = r % nodes.Length;

                        Console.WriteLine(new { i });

                        nodes[i].play();


                        var src = nodes[i].src;

                        nodes[i] = (IHTMLAudio)nodes[i].cloneNode(false);

                        //nodes[i].src = src;
                        //nodes[i].load();

                    };
                }
            )();
            #endregion


            page.Preview.onclick +=
                delegate
                {
                    orc();
                };

            // vb xlinq ..<img>


            #region arena
            // could run out of memory fast!
            var map = new Point(2048 * 3, 2048 * 2);

            var arena = new ArenaControl();

            arena.Layers.Canvas.style.backgroundColor = Color.FromGray(0);
            arena.SetLocation(Rectangle.Of(0, 0, Native.window.Width, Native.window.Height));
            arena.SetCanvasSize(map);

            arena.Control.AttachToDocument();


            page.header.AttachTo(
                arena.Layers.User
            );

            //arena.DrawTextToInfo("Craft", new Point(8, 8), Color.White);

            Native.window.onresize +=
                delegate
                {
                    arena.SetLocation(
                        Rectangle.Of(0, 0, Native.window.Width, Native.window.Height));

                    arena.SetCanvasPosition(
                        arena.CurrentCanvasPosition
                        );
                };
            #endregion

            //arena.CurrentCanvasPosition = 
            arena.SetCanvasViewCenter(
              new Point(
                  1048 + 2048,
                  1024 + 2048
              )
            );


            //{ X = -2645 } 
            //{ X = -2290 } 


            //Console.WriteLine(new { arena.CurrentCanvasPosition.X });
            Console.WriteLine(new { arena.GetCanvasViewCenter().X });

            new ScriptCoreLib.JavaScript.Runtime.Timer(
                delegate
                {
                    // two fingers?
                    if (arena.DragEngaged)
                        return;

                    if (arena.InSelectionMode)
                        return;



                    var pp = arena.GetCanvasViewCenter();

                    //Console.WriteLine(new { pp.X });

                    pp.X += 1;

                    //Console.WriteLine(new { pp.X });

                    arena.SetCanvasViewCenter(pp);
                }
            ).StartInterval(1000 / 5);

            var scalarx = 0;

            new WarcraftImages().ImageElements().Randomize()
                .Take(6)
                .WithEachIndex(
                (img, index) =>
                {
                    // we need 4x images. think retina displays.
                    Console.WriteLine(new { index });

                    img.InvokeOnComplete(
                        delegate
                        {
                            var context = new CanvasRenderingContext2D(img.width * 2, img.height * 2)
                            {
                                // http://phoboslab.org/log/html5
                                // not supported for IE
                                ImageSmoothingEnabled = false
                            };


                            context.drawImage(img, 0, 0, context.canvas.width, context.canvas.height);


                            var x = scalarx % map.X;
                            var y = (int)Math.Floor((float)scalarx / map.X) * context.canvas.height;

                            //Console.WriteLine(new { index, x, y });

                            context.canvas.AttachTo(arena.Layers.Canvas).style.SetLocation(
                                x, y
                            );

                            scalarx += context.canvas.width;
                        }
                    );

                    //img.AttachToDocument();
                }
            );
        }
        public Program(IHTMLElement placeholder)
        {
            // http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
            // http://www.quirksmode.org/js/doctypes.html
            // http://www.evolt.org/article/document_body_doctype_switching_and_more/17/30655/index.html

            // we do not want to see those scrollbars
            Native.Document.body.style.overflow = IStyle.OverflowEnum.hidden;

            // Preload Images
            foreach (var v in Frames.Harvester1)
            {
                var dummy = v.Image;
            }

            //Console.EnableActiveXConsole();

            var MyDudeHotRange = 24;
            var MyDudes = new List<Dude2>();
            var MySelectedDudes = new Dude2[] { };

            Session = new MySession();

            this.Session.IServer_EnterLobby(
                delegate(string e)
                {
                    var TheWorld = new MyGameWorld();

                    #region supporting user chat

                    var ChatBox = new LayeredTextBox();

                    Native.Document.onkeypress +=
                        delegate(IEvent ev)
                        {
                            if (ev.KeyCode == 'q') Console.WriteLine("Q");
                            if (ev.KeyCode == 'w') Console.WriteLine("W");
                            if (ev.KeyCode == 'e') Console.WriteLine("E");
                            if (ev.KeyCode == 'r')
                            {
                                var random_spawn_position = new __Type1
                                                            {
                                                                x = new System.Random().NextDouble() * 600,
                                                                y = new System.Random().NextDouble() * 400,
                                                            };

                                Console.WriteLine("random_spawn_position: " + random_spawn_position);

                                // Lets Spawn Something into the world
                            }

                            //Console.Log("onkeypress: " + new { KeyCode = ev.KeyCode });

                            if (!ChatBox.IsVisible)
                            {
                                if (ev.KeyCode == 't')
                                {
                                    ev.PreventDefault();

                                    Timer.DoAsync(
                                        delegate
                                        {
                                            ChatBox.ShowAndFocus();
                                        }
                                    );
                                }
                            }
                        };

                    #endregion

                    this.Session.ClientName = e;


                    var a = new ArenaControl();
                    var m = new ArenaMinimapControl();

                    a.Control.AttachToDocument();

                    a.Layers.Canvas.style.backgroundColor = Color.FromRGB(0, 0x80, 0);

                    // set the map to be somewhere left
                    a.SetLocation(Rectangle.Of(32, 32, 640, 480));


                    // set tha map canvas size to be something big
                    a.SetCanvasSize(new Point(8000, 8000));

                    #region DrawTextWithTimeout
                    System.Action<string, Color> DrawTextWithTimeout =
                                   delegate(string text, Color color)
                                   {
                                       var z = new IHTMLDiv(new ITextNode(text));

                                       z.style.color = color;
                                       z.style.backgroundColor = Color.Black;

                                       a.Layers.Info.appendChild(z);

                                       this.SessionTimer[TimerEvent.DelayOnce(9000)] =
                                           delegate
                                           {
                                               z.Dispose();
                                           };
                                   };
                    #endregion

                    this.SessionTimer[TimerEvent.DelayOnce(1000)] =
                       delegate
                       {
                           a.DrawTextToInfo("just some data", new Point(46, 246), Color.Black);
                           a.DrawTextToInfo("just some data", new Point(45, 245), Color.Yellow);

                           DrawTextWithTimeout("hello world", Color.Red);
                       };



                    var data = new List<Pair<Rectangle, Color>>();

                    #region minimap


                    m.Zoom.Validate += delegate
                    {
                        if (a.CurrentCanvasSize.X > a.CurrentCanvasSize.Y)
                        {
                            var w = m.CurrentLocation.Width / a.CurrentCanvasSize.X;

                            if (m.Zoom.Value < w)
                                m.Zoom.Value = w;
                        }
                        else
                        {
                            var h = m.CurrentLocation.Height / a.CurrentCanvasSize.Y;

                            if (m.Zoom.Value < h)
                                m.Zoom.Value = h;
                        }
                    };


                    m.Zoom.Changed += delegate
                    {
                        m.Layers.Canvas.removeChildren();

                        m.SetCanvasSize(a.CurrentCanvasSize * m.Zoom.Value);
                        m.SetSelectionLocation(a.CanvasView * m.Zoom.Value);
                        m.MakeSelectionVisible();


                        var data_array = data.ToArray();

                        foreach (var v in data_array)
                        {
                            var r = v.A;
                            var c = v.B;

                            m.DrawRectangleToCanvas(r * m.Zoom.Value, c);
                        }
                    };

                    m.Control.AttachToDocument();

                    m.SetLocation(Rectangle.Of(690, 50, 200, 200));


                    #endregion

                    #region DrawRectangle
                    Action<Rectangle, Color> DrawRectangleLocal =
                        delegate(Rectangle r, Color c)
                        {
                            var p = new Pair<Rectangle, Color>(r, c);

                            data.Add(p);

                            a.DrawRectangleToCanvas(r, c);
                            m.DrawRectangleToCanvas(r * m.Zoom.Value, c);
                        };



                    this.Session.OnIClient_DrawRectangle += delegate(Message._IClient_DrawRectangle p)
                    {
                        var r = new Rectangle
                                {
                                    Left = p.rect.Left,
                                    Top = p.rect.Top,
                                    Width = p.rect.Width,
                                    Height = p.rect.Height,
                                };

                        DrawRectangleLocal(r, p.color);
                    };


                    Action<Rectangle, Color> DrawRectangle =
                        delegate(Rectangle r, Color c)
                        {
                            DrawRectangleLocal(r, c);

                            this.Session.IServer_DrawRectangle(r, c);
                        };

                    #endregion

                    #region SpawnHarvester
                    Action<Point, double> SpawnHarvester_Local =
                        delegate(Point Location, double Direction)
                        {
                            // add new dude
                            var dude = CreateHarvester();

                            dude.Direction = Direction;
                            dude.Zoom.StaticZoom = 1;
                            dude.TeleportTo(Location.X, Location.Y);

                            dude.Control.AttachTo(a.Layers.Canvas);

                            MyDudes.Add(dude);
                        };

                    this.Session.OnIClient_SpawnHarvester += 
                        ev => SpawnHarvester_Local(ev.Location, (ev.Direction / 32d));

                    Action<Point, double> SpawnHarvester =
                        (Location, Direction) =>
                        {
                            SpawnHarvester_Local(Location, Direction);
                            this.Session.IServer_SpawnHarvester(Location, (Direction * 32).ToInt32());
                        };

                    //(Location, Direction) =>
                    //{
                    //    SpawnHarvester_Local(Location, Direction);
                    //};
                    #endregion

                    a.SelectionClick += delegate(Point p, IEvent ev)
                    {
                        Console.WriteLine("SelectionClick_1");

                        if (ev.ctrlKey)
                        {
                            SpawnHarvester(p, (Math.PI * 2).Random());

                            // DrawRectangle(p.WithMargin(a.SelectionMinimumSize * 2), Color.Green);
                        }
                        else
                        {
                            var Selection = MyDudes.Where(v => v.CurrentLocation.GetRange(p) < MyDudeHotRange).ToArray();

                            if (Selection.Length == 0)
                            {
                                MySelectedDudes.ForEach(v => v.WalkTo(p));
                            }
                            else
                            {
                                MySelectedDudes.ForEach(v => v.IsSelected = false);
                                MySelectedDudes = Selection;
                                MySelectedDudes.ForEach(v => v.IsSelected = true);
                            }

                        }
                    };

                    a.MouseMove +=
                        point =>
                        {
                            foreach (var v in MyDudes)
                            {
                                v.IsHot = v.CurrentLocation.GetRange(point) < MyDudeHotRange;
                            }
                        };

                    a.ApplySelection += delegate(Rectangle r, IEvent ev)
                    {
                        if (ev.ctrlKey)
                        {
                            DrawRectangle(r, RandomColor);
                        }
                        else
                        {
                            MySelectedDudes.ForEach(v => v.IsSelected = false);
                            MySelectedDudes = MyDudes.Where(v => r.Contains(v.CurrentLocation)).ToArray();
                            MySelectedDudes.ForEach(v => v.IsSelected = true);
                        }
                    };

                    a.CanvasViewChanged += delegate(Rectangle p)
                    {
                        m.SetSelectionLocation(p * m.Zoom.Value);
                        m.MakeSelectionVisible();
                    };

                    a.SetCanvasPosition(Point.Zero);

                    m.SelectionCenterChanged += delegate(Point p)
                    {
                        a.SetCanvasViewCenter(p / m.Zoom.Value);
                    };

                    m.Zoom.SetValue(0);

                    //chatbox.style.SetLocation(32, 480 - 32, 650, 22);
                    //chatbox.style.height = "1em";
                    //chatbox.attachToDocument();



                    ChatBox.SetLocation(Rectangle.Of(0, 440, 640, 22));
                    a.Layers.Info.appendChild(ChatBox.Control);

                    ChatBox.Layers.Canvas.style.backgroundColor = Color.Yellow;
                    ChatBox.Layers.Canvas.style.Opacity = 0.8;

                    ChatBox.Layers.Text.style.color = Color.White;

                    ChatBox.Hide();



                    ChatBox.Send += delegate(string text)
                    {
                        DrawTextWithTimeout(text, Color.White);

                        this.Session.IServer_TalkToOthers(text);
                    };



                    this.Session.OnIClient_DisplayNotification += x => DrawTextWithTimeout(x.text, x.color);


                    // put some elements on the canvas
                    //DrawRectangleLocal(Rectangle.Of(48, 48, 128, 64), Color.Green);
                    //DrawRectangleLocal(Rectangle.Of(48, 128, 128, 64), Color.Gray);
                    //DrawRectangleLocal(Rectangle.Of(400, 300, 128, 64), Color.Black);
                    //DrawRectangleLocal(Rectangle.Of(400, 500, 128, 64), 0xff5566);
                    //DrawRectangleLocal(Rectangle.Of(700, 600, 128, 64), 0x3f5466);


                    #region game units

                    var ai = new ArenaInfo();

                    ai.Arena = a;
                    ai.Minimap = m;

                    #region hidden
                    /*
                    {
                        var mcy = new ArenaUnit();

                        mcy.Color = Color.Red;
                        mcy.Owner = ai;
                        mcy.Title = "My Construction Yard Unit";


                        mcy.SetLocation(new Point(64, 64));
                        mcy.SetSize(new Point(72, 72));

                        // put the unit on the canvas
                        ai.Arena.Layers.Canvas.appendChild(mcy.Control);

                        // update its location
                        mcy.UpdateControlLocation();

                        // remeber that we have such a unit
                        ai.Units.Add(mcy);
                    }
                    */

                    /*

                    {

                        var mcy = new ArenaUnit();

                        mcy.Health.Max = 2000;
                        mcy.Health.Current = 1500;


                        mcy.Color = Color.Red;
                        mcy.Owner = ai;
                        mcy.Title = "My Construction Yard Unit 3";

                        mcy.IsSelectable = true;


                        mcy.SetLocation(new Point(250, 200));
                        var mfx = fx.Settings.ConstructionYard;

                        mcy.SetSize(mfx.Size);

                        mfx.ShowFrame(mcy.Control, 12);


                        // put the unit on the canvas
                        ai.Arena.Layers.Canvas.appendChild(mcy.Control);

                        // update its location
                        mcy.UpdateControlLocation();

                        // remeber that we have such a unit
                        ai.Units.Add(mcy);
                    }


                    {

                        var mcy = new ArenaUnit();

                        mcy.Health.Max = 2000;
                        mcy.Health.Current = 1500;


                        mcy.Color = Color.Red;
                        mcy.Owner = ai;
                        mcy.Title = "My Construction Yard Unit 3";

                        mcy.IsSelectable = true;


                        mcy.SetLocation(new Point(250, 300));
                        var mfx = fx.Settings.ConstructionYard;

                        mcy.SetSize(mfx.Size);

                        mfx.ShowFrame(mcy.Control, 12);


                        // put the unit on the canvas
                        ai.Arena.Layers.Canvas.appendChild(mcy.Control);

                        // update its location
                        mcy.UpdateControlLocation();

                        // remeber that we have such a unit
                        ai.Units.Add(mcy);
                    }*/
                    #endregion

                    m.Zoom.Changed +=
                        delegate
                        {
                            // redraw all units to the minimap
                            ai.DrawToMinimap();
                        };

                    #endregion

                    a.SelectionClick +=
                        delegate(Point p, IEvent ev)
                        {
                            ai.SelectUnits(p);
                        };

                    a.ApplySelection +=
                        delegate(Rectangle r, IEvent ev)
                        {
                            ai.SelectUnits(r);
                        };

                    ai.DrawToMinimap();
                }
            );
        }