/// <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)
        {
            Native.body.Clear();

            // X:\jsc.svn\examples\javascript\p2p\RTCDataChannelExperiment\RTCDataChannelExperiment\Application.cs

            // http://caniuse.com/#feat=rtcpeerconnection
            // http://iswebrtcreadyyet.com/

            new IHTMLPre
            {
                new { flightcheck = "are you using chrome40? open on android first?",
                Native.window.navigator.userAgent
                }
            }.AttachToDocument();

            // X:\jsc.svn\examples\javascript\p2p\RTCDataChannelExperiment\RTCDataChannelExperiment\Application.cs

            new { }.With(
                async delegate
                {
                    // X:\jsc.svn\examples\javascript\p2p\RTCICELobby\RTCICELobby\Application.cs

                    new IHTMLPre { "preparing..." }.AttachToDocument();


                    // first check if we can just anwser and offer?
                    #region GetOffer remotePeerConnection
                    await base.GetOffer();

                    if (base.sdpOffer != null)
                    {
                        #region backgroundColor
                        // indexer this case lets be blue

                        //Native.body.style.backgroundColor = "#‎747D9C‬";
                        // cannot set background color via hex? wtf?
                        //Native.body.style.background = "#‎747D9C‬";

                        // X:\jsc.svn\examples\javascript\css\test\TestBackgroundBlu\TestBackgroundBlu\Application.cs
                        var rgb = new { r = 0x74, g = 0x7d, b = 0x9c };

                        //var background = "rgba(\{rgb.r}, \{rgb.g}, \{rgb.b}, 1.0)";
                        var background = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", 1.0)";
                        new IHTMLPre { new { background } }.AttachToDocument();

                        //Native.body.style.background = "rgb(\{(0x‎74)}, \{0x7D}, \{0x9C})‬";
                        //Native.body.style.background = background;
                        Native.body.style.backgroundColor = background;
                        #endregion


                        //new IHTMLPre { "anwsering to offer...... " }.AttachToDocument();
                        new IHTMLPre { "anwsering to offer...... " + new { sdpCandidates = base.sdpOffer.sdpCandidates.Count } }.AttachToDocument();

                        var remotePeerConnection = new RTCPeerConnection(null, null);

                        #region onicecandidate
                        // onICE: It returns locally generated ICE candidates; so you can share them with other peer(s).
                        remotePeerConnection.onicecandidate += e =>
                        {
                            if (e.candidate == null)
                                return;
                            // onicecandidate: {{ sdpMLineIndex = 0, candidate = candidate:630834096 1 tcp 1518214911 192.168.43.252 0 typ host tcptype active generation 0 }}
                            new IHTMLPre { "remotePeerConnection.onicecandidate: " + new {

                                e.candidate.candidate,
                                e.candidate.sdpMLineIndex,
                                e.candidate.sdpMid
                            } }.AttachToDocument();



                            //remotePeerConnection.onicecandidate: { { candidate = candidate:3890619490 1 udp 2122255103 2001::9d38:6abd: 1474:3b35: 3f57:d403 52152 typ host generation 0, sdpMLineIndex = 0, sdpMid = audio } }
                            //remotePeerConnection.onicecandidate: { { candidate = candidate:3890619490 1 udp 2122255103 2001::9d38:6abd: 1474:3b35: 3f57:d403 52152 typ host generation 0, sdpMLineIndex = 1, sdpMid = data } }
                            //remotePeerConnection.onicecandidate: { { candidate = candidate:1796882240 1 udp 2122194687 192.168.43.252 52153 typ host generation 0, sdpMLineIndex = 0, sdpMid = audio } }
                            //remotePeerConnection.onicecandidate: { { candidate = candidate:1796882240 1 udp 2122194687 192.168.43.252 52153 typ host generation 0, sdpMLineIndex = 1, sdpMid = data } }

                            base.sdpAnwser.sdpCandidates.Add(
                                // need to send all 3 fields over..
                                new DataRTCIceCandidate
                                {
                                    candidate = e.candidate.candidate,
                                    sdpMLineIndex = e.candidate.sdpMLineIndex,
                                    sdpMid = e.candidate.sdpMid
                                }
                            );
                        };
                        #endregion


                        #region remotePeerConnection.ondatachannel
                        remotePeerConnection.ondatachannel = new Action<RTCDataChannelEvent>(
                            async (RTCDataChannelEvent e) =>
                            {
                                var mcounter = 0;
                                var data = default(XElement);
                                new IHTMLPre { () => "enter  remotePeerConnection.ondatachannel " + new { e.channel.label, mcounter, data } }.AttachToDocument();

                                var cur = new MyCursor();
                                cur.AttachToDocument();

                                e.channel.onmessage += ee =>
                                {
                                    // will we ever get a message?
                                    mcounter++;
                                    data = XElement.Parse("" + ee.data);

                                    var CursorX = (int)data.Attribute(nameof(IEvent.CursorX));
                                    var CursorY = (int)data.Attribute(nameof(IEvent.CursorY));

                                    cur.style.SetLocation(
                                        CursorX,
                                        CursorY
                                       );

                                };

                                // we should now get the data?
                                //return;

                                // http://stackoverflow.com/questions/15324500/creating-webrtc-data-channels-after-peerconnection-established
                                // too late?
                                new IHTMLPre { "remotePeerConnection.createDataChannel sendDataChannel2...... " }.AttachToDocument();

                                //var sendDataChannel2 = remotePeerConnection.createDataChannel("sendDataChannel2", new { reliable = false });
                                var sendDataChannel2 = await remotePeerConnection.openDataChannel("sendDataChannel2", new { reliable = false });

                                // will it be opened? seems so. what about the other one?
                                new IHTMLPre { () => "sendDataChannel2.onopen " + new { sendDataChannel2.label } }.AttachToDocument();

                                //sendChannel.send("hi!");

                                var mmmcounter = 0;



                                #region onmousemove
                                Native.document.body.ontouchmove +=
                                        re =>
                                        {
                                            var n = new { re.touches[0].clientX, re.touches[0].clientY };

                                            re.preventDefault();

                                            mmmcounter++;

                                            sendDataChannel2.send(
                                                new XElement("sendDataChannel2",
                                                    new XAttribute(nameof(mmmcounter), "" + mmmcounter),
                                                    new XAttribute(nameof(IEvent.CursorX), "" + n.clientX),
                                                    new XAttribute(nameof(IEvent.CursorY), "" + n.clientY)
                                                ).ToString()
                                            );


                                        };


                                Native.document.onmousemove +=
                                    re =>
                                    {
                                        mmmcounter++;

                                        sendDataChannel2.send(
                                            new XElement("sendDataChannel2",
                                                new XAttribute(nameof(mmmcounter), "" + mmmcounter),
                                                new XAttribute(nameof(IEvent.CursorX), "" + re.CursorX),
                                                new XAttribute(nameof(IEvent.CursorY), "" + re.CursorY)
                                            ).ToString()

                                        //new { mmcounter, e.CursorX, e.CursorY }.ToString()
                                        );
                                    };
                                #endregion

                            }
                        );
                        #endregion

                        var desc = new RTCSessionDescription(new { sdp = sdpOffer.sdp, type = "offer" });

                        new IHTMLPre { "remotePeerConnection setRemoteDescription..." }.AttachToDocument();
                        await remotePeerConnection.setRemoteDescription(desc);

                        new IHTMLPre { "createAnswer..." }.AttachToDocument();
                        var a = await remotePeerConnection.createAnswer();

                        base.sdpAnwser = new DataWithCandidates
                        {
                            sdp = a.sdp
                        };



                        new IHTMLPre { "setLocalDescription..." }.AttachToDocument();
                        await remotePeerConnection.setLocalDescription(a);


                        new IHTMLPre { () => "awaiting for any sdpAnwserCandidates... " + new { base.sdpAnwser.sdpCandidates.Count } + " atleast connect to local hotspot" }.AttachToDocument();

                        while (!base.sdpAnwser.sdpCandidates.Any())
                            await Task.Delay(1000 / 15);

                        new IHTMLPre { "Anwser... " + new { base.sdpAnwser.sdpCandidates.Count } }.AttachToDocument();

                        await base.Anwser();

                        new IHTMLPre { "Anwser... done. await ondatachannel?" }.AttachToDocument();

                        #region addIceCandidate
                        new IHTMLPre { "addIceCandidate..." }.AttachToDocument();
                        foreach (var c in base.sdpOffer.sdpCandidates)
                        {
                            var cc = new RTCIceCandidate(new { c.candidate, c.sdpMLineIndex, c.sdpMid });

                            //if (c.sdpMid == "audio" || c.candidate.Contains("::"))
                            if (c.sdpMid == "audio")
                            {
                                new IHTMLPre { "skip audio remotePeerConnection addIceCandidate... " + new { c.candidate, c.sdpMLineIndex, c.sdpMid } }.AttachToDocument();
                            }
                            else if (c.candidate.Contains("::"))
                            {
                                new IHTMLPre { "skip ip6 remotePeerConnection addIceCandidate... " + new { c.candidate, c.sdpMLineIndex, c.sdpMid } }.AttachToDocument();
                            }
                            else
                            {
                                new IHTMLPre { "remotePeerConnection addIceCandidate... " + new { c.candidate, c.sdpMLineIndex, c.sdpMid } }.AttachToDocument();
                                await remotePeerConnection.addIceCandidate(cc);
                            }

                        }
                        new IHTMLPre { "addIceCandidate... done. awaiting sendChannel.onopen.." }.AttachToDocument();
                        #endregion


                        await new TaskCompletionSource<object>().Task;
                    }
                    #endregion



                    //await new IHTMLButton { "lets go" }.AttachToDocument().async.onclick;

                    // we also have the crypto private key avaiable if this is https

                    //
                    // https://hacks.mozilla.org/2013/07/webrtc-and-the-early-api/
                    // http://www.webrtc.org/web-apis/chrome
                    // RTP data channels will be capped at 64 kbps, to prevent uncontrolled use of bandwidth.
                    // https://groups.google.com/forum/#!topic/discuss-webrtc/y2A97iCByTU
                    // If you use RTP data channels in your application, with the b= modifier, you should work on migrating to SCTP data channels immediately
                    // Failed to construct 'RTCPeerConnection': Malformed constraints object.
                    //var localPeerConnection = new RTCPeerConnection(null, new { RtpDataChannels = true });
                    var localPeerConnection = new RTCPeerConnection(null, null);

                    //{
                    //    // https://www.webrtc-experiment.com/docs/how-to-use-rtcdatachannel.html#sctp-chrome
                    //    mandatory = new
                    //    {
                    //        OfferToReceiveAudio = false,
                    //        OfferToReceiveVideo = false
                    //        //,
                    //        //RtpDataChannels = true
                    //    }
                    //}
                    //);


                    #region onicecandidate
                    // no events without a call to openDataChannel ?
                    // onICE: It returns locally generated ICE candidates; so you can share them with other peer(s).
                    localPeerConnection.onicecandidate += e =>
                    {
                        if (e.candidate == null)
                            return;

                        // onicecandidate: {{ sdpMLineIndex = 0, candidate = candidate:630834096 1 tcp 1518214911 192.168.43.252 0 typ host tcptype active generation 0 }}
                        new IHTMLPre { "localPeerConnection.onicecandidate: " + new {
                                e.candidate.candidate,
                                e.candidate.sdpMLineIndex,
                                 e.candidate.sdpMid
    }
}.AttachToDocument();



                        //remotePeerConnection.onicecandidate: { { candidate = candidate:3890619490 1 udp 2122255103 2001::9d38:6abd: 1474:3b35: 3f57:d403 52152 typ host generation 0, sdpMLineIndex = 0, sdpMid = audio } }
                        //remotePeerConnection.onicecandidate: { { candidate = candidate:3890619490 1 udp 2122255103 2001::9d38:6abd: 1474:3b35: 3f57:d403 52152 typ host generation 0, sdpMLineIndex = 1, sdpMid = data } }
                        //remotePeerConnection.onicecandidate: { { candidate = candidate:1796882240 1 udp 2122194687 192.168.43.252 52153 typ host generation 0, sdpMLineIndex = 0, sdpMid = audio } }
                        //remotePeerConnection.onicecandidate: { { candidate = candidate:1796882240 1 udp 2122194687 192.168.43.252 52153 typ host generation 0, sdpMLineIndex = 1, sdpMid = data } }

                        base.sdpCandidates.Add(
                    // need to send all 3 fields over..
                    new DataRTCIceCandidate
                    {
                        candidate = e.candidate.candidate,
                        sdpMLineIndex = e.candidate.sdpMLineIndex,
                        sdpMid = e.candidate.sdpMid
                    }
                );
                    };
                    #endregion


                    //var nn = default(object);
                    //var reliable = nn != null;

                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150301
                    new { }.With(
                        async delegate
                        {
                            var sendChannel = await localPeerConnection.openDataChannel("sendDataChannel", new { reliable = false });

                            // await async.onopen
                            new IHTMLPre { () => "sendChannel.onopen " + new { sendChannel.label, sendChannel.protocol, sendChannel.reliable } }.AttachToDocument();

                            //sendChannel.send("hi!");

                            var mmcounter = 0;



                            #region onmousemove
                            Native.document.body.ontouchmove +=
                           e =>
                           {
                               var n = new { e.touches[0].clientX, e.touches[0].clientY };

                               e.preventDefault();

                               mmcounter++;

                               sendChannel.send(
                                                   new XElement("sendDataChannel",
                                                       new XAttribute(nameof(mmcounter), "" + mmcounter),
                                                       new XAttribute(nameof(IEvent.CursorX), "" + n.clientX),
                                                       new XAttribute(nameof(IEvent.CursorY), "" + n.clientY)
                                                   ).ToString()
                                               );


                           };


                            Native.document.onmousemove +=
                                e =>
                                {
                                    mmcounter++;

                                    sendChannel.send(
                                        new XElement("sendDataChannel",
                                            new XAttribute(nameof(mmcounter), "" + mmcounter),
                                            new XAttribute(nameof(IEvent.CursorX), "" + e.CursorX),
                                            new XAttribute(nameof(IEvent.CursorY), "" + e.CursorY)
                                        ).ToString()

                                    //new { mmcounter, e.CursorX, e.CursorY }.ToString()
                                    );
                                };
                            #endregion
                        }
                   );

                    #region ondatachannel
                    localPeerConnection.ondatachannel = new Action<RTCDataChannelEvent>(
                        (RTCDataChannelEvent e) =>
                        {
                            var mcounter = 0;
                            var data = default(XElement);
                            new IHTMLPre { () => "enter  localPeerConnection.ondatachannel " + new { e.channel.label, mcounter, data } }.AttachToDocument();

                            var cur = new MyCursor();
                            cur.AttachToDocument();

                            e.channel.onmessage += ee =>
                            {
                                mcounter++;
                                data = XElement.Parse("" + ee.data);

                                var CursorX = (int)data.Attribute(nameof(IEvent.CursorX));
                                var CursorY = (int)data.Attribute(nameof(IEvent.CursorY));

                                cur.style.SetLocation(
                                                                    CursorX,
                                                                    CursorY
                                                                   );

                            };


                        }
                    );
                    #endregion

                    new IHTMLPre { "localPeerConnection.createOffer..." }.AttachToDocument();
                    var o = await localPeerConnection.createOffer();

                    new IHTMLPre { "localPeerConnection.setLocalDescription..." }.AttachToDocument();
                    await localPeerConnection.setLocalDescription(o);

                    base.sdpAdvert = o.sdp;

                    new IHTMLPre { () => "awaiting for any sdpCandidates... " + new { base.sdpCandidates.Count } + " (atleast connect to local hotspot, openDataChannel)" }.AttachToDocument();

                    // cannot wait for candidates before we do openDataChannel
                    while (!base.sdpCandidates.Any())
                        await Task.Delay(1000 / 15);

                    new IHTMLPre { "letting the server know we made a new offer... " + new { base.sdpCandidates.Count } }.AttachToDocument();

                    await base.Offer();

                    new IHTMLPre { "letting the server know we made a new offer... done. open a new tab! even on android?" }.AttachToDocument();

                    var sw = Stopwatch.StartNew();
                    var counter = 0;

                    // lets have a new status line
                    // using
                    new IHTMLPre { () => "awaiting for answer " + new { counter, sw.Elapsed } }.AttachToDocument();

                    // now poll the server, for any other offers?
                    while (this.sdpAnwser == null)
                    {
                        await Task.Delay(5000);
                        await base.CheckAnswer();
                        counter++;
                    }

                    // end using

                    new IHTMLPre { "localPeerConnection.setRemoteDescription..." }.AttachToDocument();

                    await localPeerConnection.setRemoteDescription(new RTCSessionDescription(new { base.sdpAnwser.sdp, type = "answer" }));

                    #region addIceCandidate
                    new IHTMLPre { "addIceCandidate..." }.AttachToDocument();
                    foreach (var c in base.sdpAnwser.sdpCandidates)
                    {
                        var cc = new RTCIceCandidate(new { c.candidate, c.sdpMLineIndex, c.sdpMid });

                        //if (c.sdpMid == "audio" || c.candidate.Contains("::"))
                        if (c.sdpMid == "audio")
                        {
                            new IHTMLPre { "skip audio localPeerConnection addIceCandidate... " + new { c.candidate, c.sdpMLineIndex, c.sdpMid } }.AttachToDocument();
                        }
                        else if (c.candidate.Contains("::"))
                        {
                            new IHTMLPre { "skip ip6 localPeerConnection addIceCandidate... " + new { c.candidate, c.sdpMLineIndex, c.sdpMid } }.AttachToDocument();
                        }
                        else
                        {
                            new IHTMLPre { "localPeerConnection addIceCandidate... " + new { c.candidate, c.sdpMLineIndex, c.sdpMid } }.AttachToDocument();
                            await localPeerConnection.addIceCandidate(cc);
                        }

                    }
                    #endregion


                    // https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/readyState

                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150301
                    new IHTMLPre { "awaiting localPeerConnection.openDataChannel... will it get stuck? sometimes?" }.AttachToDocument().style.color = "red";

                    //Task.WaitAny

                    //var sendChannel = localPeerConnection.createDataChannel("sendDataChannel", new { reliable = false });
                    //var sendChannel = await asendchannel;




                    // wtf?
                    // reliable false makes it work?

                }
            );


        }
        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151202/rtc
        // https://diafygi.github.io/webrtc-ips/

        /// <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)
        {
            // http://caniuse.com/#feat=rtcpeerconnection
            // http://iswebrtcreadyyet.com/

            new IHTMLPre
            {
                new { flightcheck = "are you using chrome40? open on android first?",
                Native.window.navigator.userAgent
                }
            }.AttachToDocument();

            // X:\jsc.svn\examples\javascript\p2p\RTCDataChannelExperiment\RTCDataChannelExperiment\Application.cs

            new { }.With(
                async delegate
                {
                    // X:\jsc.svn\examples\javascript\p2p\RTCICELobby\RTCICELobby\Application.cs

                    new IHTMLPre { "preparing..." }.AttachToDocument();

                    // first check if we can just anwser and offer?
                    #region GetOffer
                    await base.GetOffer();

                    if (!string.IsNullOrEmpty(sdpOffer))
                    {
                        new IHTMLPre { "anwsering and offer......" }.AttachToDocument();

                        var remotePeerConnection = new RTCPeerConnection(null, null);

                        #region onicecandidate
                        // onICE: It returns locally generated ICE candidates; so you can share them with other peer(s).
                        remotePeerConnection.onicecandidate += e =>
                        {
                            if (e.candidate == null)
                                return;
                            // onicecandidate: {{ sdpMLineIndex = 0, candidate = candidate:630834096 1 tcp 1518214911 192.168.43.252 0 typ host tcptype active generation 0 }}
                            new IHTMLPre { "remotePeerConnection.onicecandidate: " + new {

                                e.candidate.candidate,
                                e.candidate.sdpMLineIndex,
                                e.candidate.sdpMid
                            } }.AttachToDocument();

                            base.sdpAnwserCandidates.Add(e.candidate.candidate);
                        };
                        #endregion

                        #region ondatachannel
                        remotePeerConnection.ondatachannel = new Action<RTCDataChannelEvent>(
                            (RTCDataChannelEvent e) =>
                            {
                                // gearvr never gets here?

                                var mcounter = 0;
                                var data = default(XElement);
                                new IHTMLPre { () => "enter  remotePeerConnection.ondatachannel " + new { e.channel.label, mcounter, data } }.AttachToDocument();

                                var cur = new MyCursor();
                                cur.AttachToDocument();

                                e.channel.onmessage += ee =>
                                {
                                    mcounter++;
                                    data = XElement.Parse("" + ee.data);

                                    var CursorX = (int)data.Attribute("CursorX");
                                    var CursorY = (int)data.Attribute("CursorY");
                                    //var CursorX = (int)data.Attribute(nameof(IEvent.CursorX));
                                    //var CursorY = (int)data.Attribute(nameof(IEvent.CursorY));

                                    cur.style.SetLocation(
                                        CursorX,
                                        CursorY
                                       );

                                };


                            }
                        );
                        #endregion

                        var desc = new RTCSessionDescription(new { sdp = sdpOffer, type = "offer" });

                        new IHTMLPre { "setRemoteDescription..." }.AttachToDocument();
                        await remotePeerConnection.setRemoteDescription(desc);

                        new IHTMLPre { "createAnswer..." }.AttachToDocument();
                        var a = await remotePeerConnection.createAnswer();

                        new IHTMLPre { "setLocalDescription..." }.AttachToDocument();
                        await remotePeerConnection.setLocalDescription(a);

                        base.sdpAnwser = a.sdp;

                        new IHTMLPre { () => "awaiting for any sdpAnwserCandidates... " + new { base.sdpAnwserCandidates.Count } }.AttachToDocument();

                        while (!base.sdpAnwserCandidates.Any())
                            await Task.Delay(1000 / 15);

                        new IHTMLPre { "Anwser... " + new { base.sdpAnwserCandidates.Count } }.AttachToDocument();

                        await base.Anwser();

                        // gearvr never gets past this?
                        new IHTMLPre { "Anwser... done. await ondatachannel? gearvr stops here?" }.AttachToDocument();

                        // enter  remotePeerConnection.ondatachannel { label = sendDataChannel, mcounter = 335

                        // this will never return.
                        await new TaskCompletionSource<object>().Task;
                    }
                    #endregion

                    // we also have the crypto private key avaiable if this is https
                    var localPeerConnection = new RTCPeerConnection(null, null);


                    #region onicecandidate
                    // onICE: It returns locally generated ICE candidates; so you can share them with other peer(s).
                    localPeerConnection.onicecandidate += e =>
                    {
                        if (e.candidate == null)
                            return;

                        // onicecandidate: {{ sdpMLineIndex = 0, candidate = candidate:630834096 1 tcp 1518214911 192.168.43.252 0 typ host tcptype active generation 0 }}
                        new IHTMLPre { "localPeerConnection.onicecandidate: " + new {
                                e.candidate.candidate,
                                e.candidate.sdpMLineIndex,
                                 e.candidate.sdpMid
                            } }.AttachToDocument();

                        base.sdpCandidates.Add(e.candidate.candidate);
                    };
                    #endregion



                    var sendChannel = localPeerConnection.createDataChannel("sendDataChannel", new { reliable = false });

                    // await async.onopen
                    #region onopen
                    sendChannel.onopen = new Action(
                        async delegate
                        {
                            new IHTMLPre { () => "sendChannel.onopen " + new { sendChannel.label } }.AttachToDocument();

                            //sendChannel.send("hi!");

                            var mmcounter = 0;



                            Native.document.body.ontouchmove +=
                                    e =>
                                    {
                                        var n = new { e.touches[0].clientX, e.touches[0].clientY };

                                        e.preventDefault();

                                        mmcounter++;

                                        sendChannel.send(
                                            new XElement("sendDataChannel",
                                                new XAttribute("mmcounter", mmcounter),
                                                new XAttribute("CursorX", "" + n.clientX),
                                                new XAttribute("CursorY", "" + n.clientY)

                                                //    new XAttribute(nameof(mmcounter), mmcounter),
                                            //new XAttribute(nameof(IEvent.CursorX), "" + n.clientX),
                                            //new XAttribute(nameof(IEvent.CursorY), "" + n.clientY)
                                            ).ToString()
                                        );


                                    };


                            Native.document.onmousemove +=
                                e =>
                                {
                                    mmcounter++;

                                    sendChannel.send(
                                        new XElement("sendDataChannel",
                                        //new XAttribute(nameof(mmcounter), mmcounter),
                                        //new XAttribute(nameof(IEvent.CursorX), "" + e.CursorX),
                                        //new XAttribute(nameof(IEvent.CursorY), "" + e.CursorY)

                                              new XAttribute("mmcounter", mmcounter),
                                            new XAttribute("CursorX", "" + e.CursorX),
                                            new XAttribute("CursorY", "" + e.CursorY)
                                        ).ToString()

                                    //new { mmcounter, e.CursorX, e.CursorY }.ToString()
                                    );
                                };
                        }
                    );
                    #endregion


                    new IHTMLPre { "createOffer..." }.AttachToDocument();
                    var o = await localPeerConnection.createOffer();

                    new IHTMLPre { "setLocalDescription..." }.AttachToDocument();

                    await localPeerConnection.setLocalDescription(o);

                    base.sdp = o.sdp;

                    new IHTMLPre { () => "awaiting for any sdpCandidates... " + new { base.sdpCandidates.Count } }.AttachToDocument();

                    while (!base.sdpCandidates.Any())
                        await Task.Delay(1000 / 15);

                    new IHTMLPre { "letting the server know we made a new offer... " + new { base.sdpCandidates.Count } }.AttachToDocument();

                    await base.Offer();

                    new IHTMLPre { "letting the server know we made a new offer... done. open a new tab! even on android, gearvr?" }.AttachToDocument();


                    var sw = Stopwatch.StartNew();
                    var counter = 0;

                    // lets have a new status line

                    // using
                    new IHTMLPre { () => "awaiting for answer " + new { counter, sw.Elapsed } }.AttachToDocument();

                    // now poll the server, for any other offers?
                    while (string.IsNullOrEmpty(this.sdpAnwser))
                    {
                        await Task.Delay(5000);
                        await base.CheckAnswer();
                        counter++;
                    }

                    // end using

                    new IHTMLPre { "setRemoteDescription..." }.AttachToDocument();

                    await localPeerConnection.setRemoteDescription(new RTCSessionDescription(new { sdp = base.sdpAnwser, type = "answer" }));

                    new IHTMLPre { "addIceCandidate..." }.AttachToDocument();
                    foreach (var candidate in base.sdpAnwserCandidates)
                    {
                        var c = new RTCIceCandidate(new { candidate, sdpMLineIndex = 0, sdpMid = "data" });

                        new IHTMLPre { "addIceCandidate... " + new { candidate } }.AttachToDocument();

                        await localPeerConnection.addIceCandidate(c);
                    }
                    new IHTMLPre { "addIceCandidate... done. awaiting sendChannel.onopen.." }.AttachToDocument();
                }
            );



        }