static public IEnumerable <T> AsEnumerable <T>(this GoogleGearsFactory.Database db, string command, Type e)
        {
            return
                (new DynamicEnumerable <T>
            {
                DynamicGetEnumerator = delegate
                {
                    var rs = db.execute(command);
                    bool dirty = false;
                    T c = default(T);

                    return
                    new DynamicEnumerator <T>
                    {
                        // yet another bug within the compiler...
                        // we need to wrap this action, because the method is native
                        DynamicDispose = () => rs.close(),
                        DynamicMoveNext = delegate
                        {
                            if (dirty)
                            {
                                rs.next();
                            }

                            dirty = true;

                            return rs.isValidRow().Aggregate(
                                valid =>
                            {
                                c = (T)Activator.CreateInstance(e);

                                for (int i = 0; i < rs.fieldCount(); i++)
                                {
                                    var n = rs.fieldName(i);
                                    var f = e.GetField(n);

                                    if (f == null)
                                    {
                                        throw new Exception("A known field is missing for the activated object. Check the implementation for Activator.CreateInstance.");
                                    }

                                    f.SetValue(c, rs.field(i));
                                }
                            }
                                );
                        },
                        DynamicCurrent = delegate
                        {
                            return c;
                        }
                    };
                }
            });
        }
        static public void DeleteAndInsert <T>(this GoogleGearsFactory.Database db, string table, T value) where T : ISerializedObject
        {
            if (value.VirtualId == null)
            {
                throw new Exception("VirtualId is null");
            }


            db.execute("delete from " + table + " where Id = ?", value.VirtualId);
            db.Insert(table, value);
        }
        static public void Insert(this GoogleGearsFactory.Database db, string table, object e)
        {
            var w = new global::System.Text.StringBuilder();

            w.Append("insert into ");
            w.Append(table);
            w.Append("(");

            var t = e.GetType();
            var f = t.GetFields();

            for (int i = 0; i < f.Length; i++)
            {
                if (i > 0)
                {
                    w.Append(",");
                }

                w.Append(f[i].Name);
            }

            w.Append(") values (");

            for (int i = 0; i < f.Length; i++)
            {
                if (i > 0)
                {
                    w.Append(",");
                }

                w.Append("?");
            }
            w.Append(")");

            var command = w.ToString();
            var values  = f.Select(i => i.GetValue(e)).ToArray();

            db.execute(command, values);

            //db.execute("insert into Demo (Phrase, Timestamp) values (?, ?)", textfield.value, IDate.Now.getTime());
        }
        //public const string Alias = "Class1";
        //public const string DefaultData = "Class1Data";

        /// <summary>
        /// Creates a new control
        /// </summary>
        /// <param name="DataElement">The hidden data element</param>
        public GoogleGearsSimple()
        {
            // this ctor creates a new div which has a text and a button element
            // on mouseover over the color text is changed
            // on pressing the button the next message in text element is displayed
            IHTMLDiv Control = new IHTMLDiv();

            Control.AttachToDocument();

            Func <string, string, IHTMLElement> link = (href, text) => new IHTMLDiv(new IHTMLAnchor(href, text));


            Control.appendChild(link("http://gears.google.com/", "Google Gears"));
            Control.appendChild(link("http://code.google.com/apis/gears/samples/hello_world_database.html", "Google Example # 1"));

            Control.appendChild(new IHTMLElement(IHTMLElement.HTMLElementEnum.h3, "This page uses Google Gears to record your entries on the local disk. If you navigate away and revisit this page, all your data will still be here. Try it!"));

            // http://code.google.com/apis/gears/samples/hello_world_database.html

            GoogleGearsFactory.Database db = null;

            try
            {
                db = new GoogleGearsFactory.Database();
            }
            catch (Exception exc)
            {
                var err = new IHTMLCode(exc.Message);

                err.style.color = Color.Red;


                Control.appendChild(err);
            }

            IStyleSheet.Default.AddRule(".odd").style.backgroundColor  = Color.FromGray(0xa0);
            IStyleSheet.Default.AddRule(".even").style.backgroundColor = Color.FromGray(0xef);

            if (db != null)
            {
                db.open("demo1");
                db.execute(@"
    create table if not exists Demo
    (Phrase varchar(255), Timestamp int)
            ");

                var textfield = new IHTMLInput(HTMLInputTypeEnum.text, "text1", "");

                var btnadd     = new IHTMLButton("Add new entry");
                var btnrefresh = new IHTMLButton("Refresh");
                var btnclear   = new IHTMLButton("Clear");

                Control.appendChild(textfield, btnadd, btnclear, btnrefresh,

                                    new IHTMLCode(GoogleGearsFactory.Default.getBuildInfo())

                                    );



                var list = new IHTMLElement(IHTMLElement.HTMLElementEnum.ol);

                Control.appendChild(list);

                var read = default(Action);

                read = delegate
                {
                    //from i in Demo
                    //select new { Phrase, Timestamp }
                    //order by Timestamp desc

                    list.removeChildren();

                    Func <string, IHTMLElement> AddItem =
                        text => new IHTMLElement(IHTMLElement.HTMLElementEnum.li, text).Aggregate(v => list.appendChild(v));



                    // this could be rewritten as an expression once they are supported by jsc

                    int counter = 0;

                    var query = from Data in db.AsEnumerable <DemoDataEntity>(
                        "select * from Demo order by Timestamp desc",
                        typeof(DemoDataEntity)
                        )
                                // let ListItem = AddItem(Data.Timestamp + " - " + Data.Phrase)
                                select new __Type2 {
                        ListItem = AddItem(Data.Timestamp + " - " + Data.Phrase), Data = Data
                    };

                    foreach (var v in query)
                    {
                        counter++;
                        var vx = v;


                        if (counter % 2 == 0)
                        {
                            v.ListItem.className = "odd";
                        }
                        else
                        {
                            v.ListItem.className = "even";
                        }

                        #region -
                        var btndel = new IHTMLButton("-");

                        btndel.style.color = Color.Red;

                        btndel.onclick +=
                            delegate
                        {
                            db.execute("delete from Demo where Timestamp = ?", vx.Data.Timestamp);

                            read();
                        };
                        #endregion

                        #region +
                        var btnclone = new IHTMLButton("+");

                        btnclone.style.color = Color.Blue;

                        btnclone.onclick +=
                            delegate
                        {
                            db.Insert("Demo", vx.Data);


                            read();
                        };
                        #endregion

                        v.ListItem.insertBefore(btnclone, v.ListItem.firstChild);
                        v.ListItem.insertBefore(btndel, v.ListItem.firstChild);
                    }


                    #region raw
                    //var rs = db.execute("select * from Demo order by Timestamp desc");

                    //while (rs.isValidRow())
                    //{
                    //    var xt = typeof(DemoDataEntity);
                    //    var xx = (DemoDataEntity)Activator.CreateInstance(xt);

                    //    for (int i = 0; i < rs.fieldCount(); i++)
                    //    {
                    //        xt.GetField(rs.fieldName(i)).SetValue(xx, rs.field(i));
                    //    }

                    //    AddItem(xx.Timestamp + " - " + xx.Phrase);

                    //    rs.next();
                    //}

                    //rs.close();
                    #endregion
                };

                btnclear.onclick +=
                    delegate
                {
                    db.execute("delete from Demo");

                    read();
                };

                btnadd.onclick +=
                    delegate
                {
                    db.Insert("Demo",
                              new DemoDataEntity
                    {
                        Phrase    = textfield.value,
                        Timestamp = IDate.Now.getTime()
                    }
                              );

                    //db.execute("insert into Demo (Phrase, Timestamp) values (?, ?)", textfield.value, IDate.Now.getTime());

                    textfield.value = "";

                    read();
                };

                btnrefresh.onclick +=
                    delegate
                {
                    read();
                };

                read();
            }


            // not array
            // is object
            // no prototype
        }