/*global window: false */
var tdb = tdb || {},       // the tinyDB system for persistence
    data,      // abstract data representation of a form
    zero,      // initial default data for each object
    view,      // renders an XHTML (pre)view of abstract data
    grid,      // renders an XHTML grid-view of a data table
    edit,      // provides the logic for editing the abstract data
    keep,      // provides the logic for storing and retrieving data
    wrap;      // initializes the application, handles miscellaneous events

    zero =  {
    B: { A: "", B: "", C: "Yes", D: [ ], F: "No", G: "No", Z: "new" },
    B2: { R: "" },
    C: { A: "", B: "", C: "Yes", D: [ ], F: "", G: "Draft", H: "Yes", I: "No", J: "1",  Z: "new" },
    C2: {A: "", D: [ ] },
    C3: {A: "", F: "", R: "" },
    D: {A: "", F: "No", Z: "new"},
    E: {A: "", D: [ ], Z: "new"},
    E2: {A: "", B: "", F: "", G: "", H: "No"},
    F: { A: "", D: [ ], R: "", Z: "new" } };

/** The module renders data structures to XHTML using DOM manipulation.
 *  The key aspect is assigning an id attribute to each clickable element
 *  such that the event handler can launch the proper editor and find the
 *  data objects that are to be edited.
 */
view = (function () {
    "use strict";
    var selected,
        ge = document.getElementById,    // aliases to simplify code
        ce = document.createElement,
        ctn = document.createTextNode;
    
    // purge HTML DOM node of all child nodes
    function purge(node) { var c;
        for (c = node.firstChild; c; c = node.firstChild) {
            node.removeChild(c); } }

    function hiLite(id) {
        var node = ge(id);
        if (node) {
            node.style.backgroundColor = '#444488';
            node.style.color = 'white'; } }

    // event handler for interactive elements of (pre)view
    function handle(e) {
        e = e || event;
        var src = e.srcElement || e.target;
        selected = src.id;
        edit.launch(src); }

    function doComment() {
        var div = ce('div'),
            inp = ce('input');
        inp.type = 'text';
        inp.className = 'commentBox';
        div.appendChild(inp);
        return div; }

    function doNumber() {
        var div = ce('div'),
            inp = ce('input'),
            span = ce('span');
        inp.type = 'text';
        inp.className = 'numberBox';
        div.appendChild(inp);
        span.appendChild(ctn(' Comment:'));
        div.appendChild(span);
        inp = ce('input');
        inp.className = 'shortComment';
        div.appendChild(inp);
        return div; }

    function doText() {
        var div = ce('div'),
            inp = ce('textarea');
        inp.className = 'freeTextBox';
        inp.cols = 68;
        inp.rows = 4;
        div.appendChild(inp);
        return div; }

    function doTable(id, obj) {
        var inp, c, r, row, name,
            hdrl = data.E[obj.R],
            tbl = ce('table'),
            tr = tbl.insertRow(),
            td = tr.insertCell();
        if (!hdrl) {hdrl = {D: []}; } 
        for (c in hdrl.D) {
            td = tr.insertCell();
            td.className = 'header';
            td.id = id + '_' + c;
            td.onclick = handle;
            td.style.cursor = 'pointer'; 
            td.appendChild(ctn(hdrl.D[c].F || '___')); }
//        if (!obj.D) {obj['D'] = []; } 
        for (r in obj.D) {
            row = data.D[obj.D[r]];
            tr = tbl.insertRow();
            td = tr.insertCell();
            td.className = 'leftHdr';
            name = id + '_X_' + r;
            td.id = name;
            td.onclick = handle;
            td.style.cursor = 'pointer'; 
            td.appendChild(ctn(row.A || '_____'));
            for (c in hdrl.D) {
                td = tr.insertCell();
                inp = ce('input');
                if (row.F === 'Yes') {
                    inp.type = 'checkbox'; }
                else {
                    inp.type = 'radio';
                    inp.name = name; }
                td.appendChild(inp); } }
        return tbl; }

    function doList(id, obj, mul) {
        var i, lbl, inp, div = ce('div'),
            name = id;
        for (i in obj.D) {
            lbl = ce('span');
            lbl.id = id + '_' + i;
            lbl.onclick = handle;
            lbl.style.cursor = 'pointer'; 
            inp = ce('input');
            if (mul === 'No') {
                inp.name = name;
                inp.type = 'radio'; }
            else {
                inp.type = 'checkbox'; }
            lbl.appendChild(inp);
            lbl.appendChild(ctn((obj.D[i].A || '_____') + '\u00a0 \u00a0'));
            div.appendChild(lbl);
        }
        return div; }

    function doQuestion(id, obj, tr) {
        var td = tr.insertCell();
        td.id = id;
        td.onclick = handle;
        td.style.cursor = 'pointer'; 
        td.className = 'qLabel';
        switch(obj.E) {
        case 'query':
            if (obj.A) {
                td.appendChild(ctn(obj.A || '_____'));    // override
                obj = data.D[obj.R]; }
            else {
                obj = data.D[obj.R];
                td.appendChild(ctn(obj.A || '_____')); }
            td = tr.insertCell();
            td.className = 'qContent';
            alert(JSON.stringify(obj));
            switch(obj.E) {
            case 'comment':
                td.appendChild(doComment());
                break;
            case 'number':
                td.appendChild(doNumber());
                break;
            case 'text':
                td.appendChild(doText());
                break;
            case 'list':
                td.appendChild(doList(id, data.E[obj.R], obj.F));
                break;
            default:
                break; 
            }
            break; 
        case 'table':
            if (obj.A) {
                td.appendChild(ctn(obj.A || '_____'));    // override
                obj = data.F[obj.R]; }
            else {
                obj = data.F[obj.R];
                td.appendChild(ctn(obj.A || '_____')); }
            td = tr.insertCell();
            td.className = 'qContent';
            alert(JSON.stringify(obj));
            td.appendChild(doTable(id, obj));
            break;
        default:
            break;
        }
    }
/*
    function doQuestion(id, obj, tr) {
        var td = tr.insertCell();
        td.id = id;
        td.onclick = handle;
        td.style.cursor = 'pointer'; 
        td.className = 'qLabel';
        if (obj.A) {
            td.appendChild(ctn(obj.A || '_____'));    // override
            obj = data.D[obj.R]; }
        else {
            obj = data.D[obj.R];
            td.appendChild(ctn(obj.A || '_____')); }
        td = tr.insertCell();
        td.className = 'qContent';
        alert(JSON.stringify(obj));
        switch(obj.E) {
        case 'comment':
            td.appendChild(doComment());
            break;
        case 'number':
            td.appendChild(doNumber());
            break;
        case 'text':
            td.appendChild(doText());
            break;
        case 'list':
            td.appendChild(doList(id, data.E[obj.R], obj.F));
            break;
        case 'table':
            td.appendChild(doTable(id, obj));
            break;
        default:
            break; } }
*/
    function doQSet(id, obj, tbl) {
        var i, tr = tbl.insertRow(),
            td = tr.insertCell();
        td.id = id;
        td.setAttribute('colspan', '2');
        td.onclick = handle;
        td.style.cursor = 'pointer'; 
        td.appendChild(ctn(obj.A || '_____'));
        td.className = 'qSetLabel';
        for (i in obj.D) {
            tr = tbl.insertRow();
            doQuestion(id + '_' + i, obj.D[i], tr); }
        return tbl; }

    function doSection(id, obj) {
        var i, sect = ce('fieldset'),
            lbl = ce('legend'),
            tbl = ce('table');
        lbl.id = id;
        lbl.onclick = handle;
        lbl.style.cursor = 'pointer'; 
        lbl.appendChild(ctn(obj.A || '_____'));
        lbl.className = 'sectionLabel';
        sect.appendChild(lbl);
        tbl.className = "section";
        for (i in obj.D) {
            tbl = doQSet(id + '_' + i, obj.D[i], tbl); }
        sect.appendChild(tbl);
        return sect; }

    function doFormLabel(id, obj) {
        var n = ce('h1');
        n.id = id;
        n.className = 'formLabel';
        n.onclick = handle;
        n.style.cursor = "pointer"; 
        n.appendChild(ctn(obj.A || '_____'));
        return n; }

    function doForm(id, obj) {
        var i, child,
            node = ce('div'),
            lbl = doFormLabel(id, obj);
        node.appendChild(lbl);
        for (i in obj.D) {
            child = data.C[obj.D[i]];
            child = doSection(id + '_' + i, child);
            node.appendChild(child); }
        return node; }

    return {
        select: function (id) {
            selected = id; },

        refresh: function () {
            var html, ws = ge('workspace');
            purge(ws);
            if (data.B.length === 1) {
                html = doForm('id', data.B[0]); } 
            else if (data.C.length === 1) {
                html = doSection('id_0', data.C[0]); }
            if (html) {ws.appendChild(html); }
            if (selected) {
                hiLite(selected);
                edit.locate(selected); } } }; }());

edit = (function () {
    "use strict";
    var active,                // id of open editor pop-up
        top, left,             // position for editor
        dbo,                   // array of objects, increasing depth
        arr,                   // array of arrays for cursor
        map;                   // corresponding array of positions

    function walkMap() {
        var len = map.length;                  // map is created by launch
        arr = [];                              // array of arrays
        dbo = [];                              // array of data objects
        dbo[0] = data.B[0];                    // form
        arr[0] = dbo[0].D;                     // Section-pointers
        if (len === 0) {return 'edForm'; }
        dbo[1] = data.C[arr[0][map[0]]];       // section object
        arr[1] = dbo[1].D;                     // QSets
        if (len === 1) {return 'edSect'; }
        dbo[2] = arr[1][map[1]];               // qset
        arr[2] = dbo[2].D;                     // Questions
        if (len === 2) {return 'edQSet'; }
        dbo[3] = arr[2][map[2]];               // question
        switch(dbo[3].E) {                     // question type
        case 'comment':
            dbo[4] = data.D[dbo[3].R];         // query
            return 'edComment';
        case 'number':
            dbo[4] = data.D[dbo[3].R];         // query
            return 'edNumber';
        case 'text':
            dbo[4] = data.D[dbo[3].R];         // query
            return 'edText';
        case 'list':
            dbo[4] = data.D[dbo[3].R];         // query
            dbo[5] = data.E[dbo[4].R];         // response list
            arr[3] = dbo[5].D;                 // Responses
            if (len === 3) {return 'edRList'; }
            dbo[6] = arr[3][map[3]];           // response
            return 'edResponse';
        case 'table':
            dbo[4] = data.F[dbo[3].R];         // query table
            dbo[5] = data.E[dbo[4].R];         // header list
            arr[3] = dbo[5].D;                 // headers
            arr[4] = dbo[4].D;                 // rows
            if (len === 3) {return 'edTable'; }
            dbo[6] = arr[3][map[3]];           // the header
            if (len === 4) {return 'edHeader'; }
            dbo[7] = data.D[arr[4][map[4]]];           // the row
            return 'edRow';
        default:
            break; } }

    function idify(map) {
        if (map.length === 0) {return 'id'; }
        return 'id_'  + map.join('_'); }

    function mapify(id) {
        var i, map = id.split('_');
        map.shift();                           // remove prefix
        for (i in map) {
            map[i] = isNaN(map[i]) ? 'X' : +map[i]; }
        return map; }

    function getRadioValue(name) {
        var i, grp = document.getElementsByName(name),
            len = grp.length;
        for (i = 0; i < len; i = i +1) {
            if (grp[i].checked) { return grp[i].value; } } }

    function locate(src) {
        top = src.offsetTop;
        if (src.tagName === 'TD') {
            src = src.parentNode.parentNode;
            top = top + src.parentNode.offsetTop; }
        left = document.documentElement.offsetWidth - 560; }

    function hide(id) {
        var wnd = document.getElementById(id);
        wnd.style.display = 'none'; }

    function show(id) {
        var wnd = document.getElementById(id);
        wnd.style.display = 'block'; }

    function popup(id) {
        var node = document.getElementById(id);
        if (active) {hide(active); }
        active = id;
        node.style.top = top;
        node.style.left = left;
        node.style.display = 'block';
        window.scrollTo(0, top); }

    function close(id) {
        hide(id || active);
        active = null; 
        view.select(null);
        view.refresh(); }

    function read(wnd) {
        var ctrl, id, opts, i, j, k;
        for (i in dbo) {
            for (j in dbo[i]) {
                id = wnd + '_' + i + '_' + j;
                ctrl = document.getElementById(id);
                if (ctrl) {
                    if (ctrl.tagName === 'SELECT') {
                        opts = ctrl.options;
                        for (k = 0; k < opts.length; k = k + 1) {
                            if (dbo[i][j] === opts[k].value) {
                                ctrl.selectedIndex = k; } } }
                    else {ctrl.value = dbo[i][j]; } } } } }

    function open(id, id2) {
        var node;
        popup(id);
        read(id);
        view.select(idify(map));
        view.refresh();
        node = document.getElementById(id2);
        if (node) {node.focus(); } }

    function update(e) {
        e = e || event;
        var src = e.srcElement || e.target,
            dst = src.id.split('_');
        dbo[dst[1]][dst[2]] = src.value;
        view.refresh(); }

    function newSection() {
        data.C.push(wrap.clone(zero.C));       // make new section
        arr[0].push(data.C.length - 1);        // add ptr to section array
        map.push(arr[0].length -1);            // map[0] = section ptr
        dbo.push(data.C[arr[0][map[0]]]);      // dbo[1] = the section
        arr.push(dbo[1].D); }                  // arr[1] = QSet array

    return {
        close: close,
        update: update,
        hide: hide,
        show: show,

        keyDown: function (e) {
            e = e || event;
            if (e.keyCode === 13) {update(e); } },

        start: function () {
            data = {B: [], C: [], D: [], E: [], F: []};
            dbo = []; arr = []; map = [];
            top = 100;
            left = document.documentElement.offsetWidth - 560;
            popup('ed_start'); },

        begin: function() {
            var task = getRadioValue('task');
            switch(task) {
            case '1':
                data.B[0] = wrap.clone(zero.B);
                dbo.push(data.B[0]);
                arr.push(dbo[0].D);
//                view.select('id_');
                view.refresh();
                open('edForm', 'edForm_0_A');
                break;
            case '2':
                break;
            case '3':
                data.C[0] = wrap.clone(zero.C);
                dbo = [[{}], data.C[0]];
                arr = [[0], dbo[1].D];
                view.refresh();
                open('edSect');
                break;
            case '4':
                break;
            default:
                break; } },

        nextSection: function() {
            if (map[0] < arr[0].length -1) {
                map[0] = map[0] + 1; }
            else {
                dbo.pop(); arr.pop(); map.pop();
                newSection(); }
            open('edSect', 'edSect_1_A'); },
        
        addSection: function () {
            newSection();
            open('edSect', 'edSect_1_A'); },

        addQSet: function () {
            arr[1].push(wrap.clone(zero.C2));      // make new QSet in array
            map.push(arr[1].length - 1);           // map[1] = QSet ptr
            dbo.push(arr[1][map[1]]);              // dbo[2] = the QSet object
            arr.push(dbo[2].D);                    // arr[2] = Question array
            view.select(idify(map));
            view.refresh(); 
            open('edQSet'); },

        addQuestion: function () {
            var ctrl = document.getElementById('edQSet_type');
            arr[2].push(wrap.clone(zero.C3));      // make new Question in array
            map.push(arr[2].length - 1);           // map[2] = Question ptr
            dbo.push(arr[2][map[2]]);              // dbo[3] = the Question object
            switch(ctrl.value) {
            case 'list':
                this.addList();
                break;
            case 'table':
                this.addTable();
                break;
            case 'comment':
                this.addComment();
                break;
            case 'number':
                this.addNumber();
                break;
            case 'text':
                this.addText();
                break;
            default:
                break; } },

        addList: function () {
            dbo[3].E = 'query';                 // question type = query
            data.D.push(wrap.clone(zero.D));   // new query object in D
            dbo[3].R = data.D.length - 1;      // question points to query
            dbo.push(data.D[dbo[3].R]);        // dbo[4] = the Query object
            dbo[4].E = 'list';                 // query type = list
            data.E.push(wrap.clone(zero.E));   // make new Response List in E
            dbo[4].R = data.E.length - 1;      // query points to RList
            dbo.push(data.E[dbo[4].R]);        // dbo[5] = the List object
            arr.push(dbo[5].D);                // arr[3] = the Response array
            map.push(arr[3].length - 1);       // map[3] = Response ptr
            view.select(idify(map));
            view.refresh();
            open('edRList'); },

        addResponse: function () {
            arr[3].push(wrap.clone(zero.E2));  // make new Response in array
            dbo.push(arr[3][arr[3].length - 1]); // dbo[6] = the Response object
            view.select(idify(map));
            view.refresh(); 
            open('edResponse'); },

        addTable: function () {
            dbo[3].E = 'table';                // question type = table
            data.F.push(wrap.clone(zero.F));   // new Table object in F
            dbo[3].R = data.F.length - 1;      // question points to Table
            dbo[4] = data.F[dbo[3].R];         // dbo[4] = the Table object
            open('edPreTable'); },

        addTable2: function () {
            data.E.push(wrap.clone(zero.E));   // new Header List object
            dbo[4].R = data.E.length - 1;      // Table points to Header List
            dbo.push(data.E[dbo[4].R]);             // dbo[5] = Header List object
            arr.push(dbo[5].D);                // arr[3] = the column array
            arr.push(dbo[4].D);                // arr[4] = the row array (ptr)
            view.select(idify(map));
            view.refresh();
            open('edTable'); },

        addRowCol: function () {
            var i, task = getRadioValue('addRC');
            if (task === 'col') {
                dbo[6] = wrap.clone(zero.E2);      // dbo[6] = new Header object
                arr[3].push(dbo[6]);               // add to column array
                map[3] = arr[3].length -1;
                view.select(idify(map));
                view.refresh();
                open('edHeader'); }
            else {
                data.D.push(wrap.clone(zero.D));   // new row (Query)
                i = data.D.length -1;
                dbo[7] = data.D[i];                // dbo[7] = the Row
                arr[4].push(i);                    // add ptr to row array
                map[3] = 'X';
                map[4] = arr[4].length -1;
                dbo[7].E = 'list';                 // query type is list
                dbo[7].R = dbo[4].R;               // all rows ==> Header List
                view.select(idify(map));
                view.refresh();
                open('edRow'); } },

        nextRow: function () {
            var i;
            if (map[4] < arr[4].length -1) {
                map[4] = map[4] + 1; }
            else {
                data.D.push(wrap.clone(zero.D));   // new row (Query)
                i = data.D.length -1;
                dbo[7] = data.D[i];                // dbo[7] = the Row
                arr[4].push(i);                    // add ptr to row array
                dbo[7].E = 'list';                 // query type is list
                dbo[7].R = dbo[4].R; }             // all rows ==> Header List
            view.select(idify(map));
            view.refresh();
            open('edRow'); },

        addComment: function () {
            dbo[3].E = 'query';                // question type = query
            data.D.push(wrap.clone(zero.D));   // new query object in D
            dbo[3].R = data.D.length - 1;      // question points to query
            dbo[4] = data.D[dbo[3].R];         // dbo[4] = the Query object
            dbo[4].E = 'comment';              // query type = comment
            view.select(idify(map));
            view.refresh();
            open('edComment'); },

        addNumber: function () {
            dbo[3].E = 'query';                // question type = query
            data.D.push(wrap.clone(zero.D));   // new query object in D
            dbo[3].R = data.D.length - 1;      // question points to query
            dbo[4] = data.D[dbo[3].R];         // dbo[4] = the Query object
            dbo[4].E = 'number';               // query type = number
            view.select(idify(map));
            view.refresh();
            open('edNumber'); },

        addText: function () {
            dbo[3].E = 'query';                // question type = query
            data.D.push(wrap.clone(zero.D));   // new query object in D
            dbo[3].R = data.D.length - 1;      // question points to query
            dbo[4] = data.D[dbo[3].R];         // dbo[4] = the Query object
            dbo[4].E = 'text';                 // query type = text
            view.select(idify(map));
            view.refresh();
            open('edText'); },

        up: function (n) {
            var tmp, my = arr[n], loc = map[n];
            if (loc > 0) {
                tmp = my.splice(loc, 1);
                loc = loc - 1;
                my.splice(loc, 0, tmp[0]);
                map[n] = loc;
                view.select(idify(map));
                view.refresh(); } },

        down: function (n) {
            var tmp, my = arr[n], loc = map[n];
            if (loc < my.length - 1) {
                tmp = my.splice(loc, 1);
                loc = loc + 1;
                my.splice(loc, 0, tmp[0]);
                map[n] = loc;
                view.select(idify(map));
                view.refresh(); } },

        remove: function (n) {
            var my = arr[n];
            if (my.length > 0) {
                if (confirm('Delete this object?')) {
                    my.splice(map[n], 1);
                    view.refresh();
                    close(); } } },

        locate: function (id) {
            var dst = document.getElementById(id);
            if (dst) {locate(dst); } },

        launch: function (src) {
            locate(src);
//            alert(src.id);
            map = mapify(src.id);
            open(walkMap());
            view.refresh(); } }; }());

keep = (function () {
    "use strict";
    var work, cache;

    /** The "load" functions are used to load the "cache" object from
     *  file storage.
     */ 
    function load(dict) {
        var r, data,
            msg = {action: "load", book: "dict", sheet: dict};
        data = tdb.post(msg);
        cache[dict] = [];
        for (r in data) {
            cache[dict].push(JSON.parse(data[r])); } }

    /** The "save" functions (save, write, append) are used to move
     *  data from the "data" object into file storage (via "work"). 
     */
    function append(n, dict) {
        var obj = work[dict][n],
            msg = {action: "next", book: "dict", sheet: dict, data: ""};
        obj.Z = tdb.post(msg);
        msg.action = "append";
        msg.data = JSON.stringify(obj);
        tdb.post(msg); }

    function write(n, dict) {
        var obj = work[dict][n],
            msg = {action: "write", book: "dict", sheet: dict, row: "", data: ""};
        msg.row = obj.Z;
        msg.data = JSON.stringify(obj);
        tdb.post(msg); }

    function save(n, dict) {
        if (work[dict][n].Z === 'new') {
            append(n, dict);                       // append if new
            data[dict][n].Z = work[dict][n].Z; }   // no longer 'new'
        else if (work[dict][n].W === 1) {
            write(n, dict); }                      // write if not new
        data[dict][n].W = 0; }                     // wipe the smudge

    function saveQuery(n) {
        var obj = work.D[n];
        if (obj.E === 'list') {
            save(obj.R, 'E');
            obj.R = work.E[obj.R].Z; }             // (Query => List)
        save(n, 'D'); }

    function saveTable(n) {
        var i, obj = work.F[n];
        save(obj.R, 'E');
        obj.R = work.E[obj.R].Z;                   // (Header => List)
        for (i in obj.D) {
            saveQuery(obj.D[i]);
            obj.D[i] = work.D[obj.D[i]].Z; }       // (List => Query)
        save(n, 'F'); }

    function saveSection(n) {
        var q, i, j, obj = work.C[n];
        for (i in obj.D) {                         // (Q Sets)
            for (j in obj.D[i].D) {                // (Questions)
                q = obj.D[i].D[j];
                switch (q.E) {
                case 'query':
                    saveQuery(q.R);
                    q.R = work.D[q.R].Z;           // (Ques => Query)
                    break;
                case 'table':
                    saveTable(q.R);
                    q.R = work.F[q.R].Z;           // (Ques => Table)
                    break;
                default:
                    break; } } }
        save(n, 'C'); }

    function saveForm() {
        var i, obj = work.B[0];                    // The Form
        for (i in obj.D) {
            saveSection(obj.D[i]);
            obj.D[i] = work.C[obj.D[i]].Z; }       // (Form => Section)
        save(0, 'B'); }

    /** The "push" functions are used to build the "data" object for a given
     *  form from the "cache" so that it can be viewed and edited.
     */
    function push(dict, obj) {
        data[dict].push(obj);
        return data[dict].length - 1;
    }

    function pushQuery(n) {
        var obj = cache.D[n];
        if (obj.E === 'list') {
            obj.R = push(obj.R, 'E');  }
        return push(n, 'D');
    }

    function pushTable(n) {
    }

    function pushSection(n) {
        var q, i, j, 
           obj = wrap.clone(cache.C[n]);
        for (i in obj.D) {                         // (Q Sets)
            for (j in obj.D[i].D) {                // (Questions)
                q = obj.D[i].D[j];
                switch (q.E) {
                case 'query':
                    pushQuery(q.R);
                    q.R = work.D[q.R].Z;           // (Ques => Query)
                    break;
                case 'table':
                    pushTable(q.R);
                    q.R = work.F[q.R].Z;           // (Ques => Table)
                    break;
                default:
                    break; }
            } 
        }
    }

    function pushForm(n) {
        var i, r, obj = wrap.clone(cache.B[n]);
        for (i in obj.D) {
            r = pushSection(obj.D[i]);
            obj.D[i] = r; }
        push('B', obj); }

    return {
        saveForm: function () {
            work = wrap.clone(data);
            saveForm(); },

        saveSection: function (n) {
            work = wrap.clone(data);
            saveSection(n); },

        saveTable: function (n) {
            work = wrap.clone(data);
            saveTable(n); },

        saveQuery: function (n) {
            work = wrap.clone(data);
            saveQuery(n); },

        saveList: function (n) {
            work = wrap.clone(data);
            save(n, 'E'); },

        loadCache: function () {
            cache = {};
            cache['B'] = load('B');
            cache['C'] = load('C');
            cache['D'] = load('D');
            cache['E'] = load('E');
            cache['F'] = load('F');
        }
    };
}());

wrap = (function () {
    "use strict";
    var testdata = {
    B: [ { A: "Form Name", D: [ 0 ], Z: "new" } ],
    C: [ { A: "Section", D: [ {A: "QSet", D: [
         { A: "Question 1", E: "query", R: 0 },
         { A: "", E: "query", R: 1 },
         { A: "TABLE", E: "table", R: 0 },
         { A: "", E: "query", R: 5},
         { A: "", E: "query", R: 6},
         { A: "", E: "query", R: 7} ] } ], Z: "new" } ],
    D: [ { A: "Query 1", E: "list", F: "No", R: 0, Z: "new" },
         { A: "Query 2", E: "list", F: "Yes", R: 0, Z: "new" },
         { A: "HIV", E: "list", F: "No", R: 1, Z: "new" },
         { A: "Hepatitis B", E: "list", F: "No", R: 1, Z: "new" },
         { A: "VDRL", E: "list", F: "Yes", R: 1, Z: "new" },
         { A: "Chief Complaint", E: "comment", Z: "new"},
         { A: "Interim History", E: "text", Z: "new"},
         { A: "How many?", E: "number", Z: "new"} ],
    E: [ { A: "Response List", D: [
         { A: "Option 1" },
         { A: "Option 2" },
         { A: "Option 3" } ], Z: "new" },
         { A: "Header List", D: [
         { A: "Positive", B: "Y", F: "Pos" },
         { A: "Negative", B: "N", F: "Neg" },
         { A: "Unknown", B: "U", F: "Unk" } ], Z: "new" } ],
    F: [ { A: "Query Group", D: [2, 3, 4 ], R: 1, Z: "new" } ] };

    function getCSSRule(name) {
        var i, rules = document.styleSheets[0].rules;
        for (i = 0; i < rules.length; i = i + 1) {
            if (rules[i].selectorText === name) {
                return rules[i]; } }
        return false; }

    function bindEditCtrls() {
        var ctrl, i, list;
        list = document.getElementsByTagName('INPUT');
        for (i = 0; i < list.length; i = i + 1) {
            ctrl = list[i];
            if (ctrl.getAttribute('type') === 'text') {
                ctrl.onblur = edit.update;
                ctrl.onkeydown = edit.keyDown; } }
        list = document.getElementsByTagName('SELECT');
        for (i = 0; i < list.length; i = i + 1) {
            ctrl = list[i];
            ctrl.onchange = edit.update; }
        ctrl = document.getElementById('edQSet_type');
        ctrl.onchange = null; }

    return {
        changeUserType: function(e) {
            e = e || event;
            var ctrl = e.srcElement || e.target,
            rule = getCSSRule('.detail');
            if (rule) {
                if (ctrl.value === 'detail') {
                    rule.style.display = 'table-row';
                    ctrl = document.getElementById('app_user2');
                    ctrl.checked = 'true';
                    ctrl = document.getElementById('ed_user2');
                    ctrl.checked = 'true';
                } else {
                    rule.style.display = 'none'; 
                    ctrl = document.getElementById('app_user1');
                    ctrl.checked = 'true';
                    ctrl = document.getElementById('ed_user1');
                    ctrl.checked = 'true';
                     } } },
        clone: function (obj) {
            return JSON.parse(JSON.stringify(obj)); },

        run: function () {
            bindEditCtrls();
            tdb.init();
//            data = testdata;
//            view.refresh();
        } }; }());
window.onload = wrap.run;

