
//RE for getting prefix and namespace from sparqls
//re = /\s*(\w*):\s*<(\S*)>/;
//var prefLinesRE = /PREFIX.*/g;
//re = /\s*(\w*):\s*<(\S*)>\s*/g;



String.prototype.trim = function () {
    return this .replace(/^\s + |\s + $/g, "");
}

String.prototype.stripSlash = function() {
        if (this.charAt(this.length -1 ) == '/') {
            return this.slice(0, -1);
        } 
        return this;    
    }

var util = {
    
    /********************
    *
    * Creating Things
    *
    *************************/
 
    makeLiteral : function (string, lang, dt) {
        var returnObj = {  type: 'literal' };
        returnObj.value = '' + string;
        if (lang) {
            returnObj.lang = lang;
        }
        if (dt) {
            dt = this .expandPrefix(dt);
            returnObj.datatype = dt;
        }
        return returnObj;
    },
    
    makeURI : function (uri) {
        uri = this .expandPrefix(uri);
        var returnObj = {
            type: 'uri'
        };
        returnObj.value = uri;
        return returnObj;
    },
    
    makeCheckbox: function (isChecked, cssClass) {
        var inp = document.createElement('input');
        inp.setAttribute('class', cssClass);
        inp.setAttribute('type', 'checkbox');
        inp.checked = isChecked;
        return inp;
    },
    
    
    
    makeEditButton: function () {
        var button = document.createElement('button');
        button.appendChild(document.createTextNode('Edit'));
        button.onclick = function (event) {
            var target = event.target;
            var parent = target.parentNode;
            parent.editAction();
        };
        return button;
    },
    
    makeOKButton: function () {
        var button = document.createElement('button');
        button.appendChild(document.createTextNode('OK'));
        button.onclick = function (event) {
            var target = event.target;
            var parent = target.parentNode;
            parent.okAction();
        };
        return button;
    },

    createHelpSpan: function(helpObj) {
        var hSpan = document.createElement('span');
        hSpan.appendChild(document.createTextNode('(?)') );
        hSpan.setAttribute('class', 'help');
        hSpan.helpObj = helpObj;
        hSpan.onclick = ui.toggleHelp;
        hSpan.setAttribute('title', 'Help about ' + helpObj.label);
        return hSpan;
    },
    
    
    createSelect : function (label, pred, optionsGraph, isRequired , multi,  size) {
        var pDiv = document.createElement('div');
        pDiv.gatherData = gatherSelectedToContextSubject;
        var h = document.createElement('h1');
        
        if(isRequired) {
            var reqdSpan = document.createElement('span');
            reqdSpan.setAttribute('class', 'required');
            reqdSpan.appendChild(document.createTextNode('*') );
            pDiv.appendChild(reqdSpan);
        }
        
        h.appendChild(document.createTextNode(label) );
        pDiv.appendChild(h);
        pDiv.pred = pred;
        var resSelect = document.createElement('select');
        resSelect.multiple = multi;
        resSelect.size = (size) ? size : 5 ;
        resSelect.pred = pred;
        
        for (var s in optionsGraph.subjects) {
            var newOption = document.createElement('option');
            newOption.value = s;
            
            newOption.appendChild(document.createTextNode(optionsGraph.subjects[s].getTitle() ) );
            newOption.pred = pred;
            resSelect.appendChild(newOption);
            
        }
        pDiv.appendChild(resSelect);
        return pDiv;
    },
    
    
    createBasicInput : function (label, pred, isRequired) {
        var div = document.createElement('div');
        div.gatherData = gatherValueToContextSubject;
        div.setAttribute('class', 'lookupInput');

        div.pred = pred;
        //var h = document.createElement('h1');
        var p = document.createElement('p');
        p.appendChild(document.createTextNode(label));
        
        if(isRequired) {
            var reqdSpan = document.createElement('span');
            reqdSpan.setAttribute('class', 'required');
            reqdSpan.appendChild(document.createTextNode('*') );
            p.appendChild(reqdSpan);
        }
        
        div.appendChild(p);
        
        var inp = document.createElement('input');
        inp.setAttribute('type', 'text');
        inp.onkeypress = util.fireGoButton;
        p.appendChild(inp);
        return div;
    },
    
    createInputCheckBox : function (label, pred, isRequired, helpObj) {
        var div = document.createElement('div');
        div.gatherData = gatherValueToContextSubject;
        div.setAttribute('class', 'checkboxInput');
        div.pred = pred;

        div.appendChild(util.makeCheckbox(false, 'inputcheckbox') );

        var p = document.createElement('p');
        p.appendChild(document.createTextNode(label));
        p.appendChild(util.createHelpSpan(helpObj) );
        if(isRequired) {
            var reqdSpan = document.createElement('span');
            reqdSpan.setAttribute('class', 'required');
            reqdSpan.appendChild(document.createTextNode('*') );
            p.appendChild(reqdSpan);
        }
        
        div.appendChild(p);
        
        var inp = document.createElement('input');
        inp.setAttribute('type', 'text');
        p.appendChild(inp);
        return div;    
    },
    
    createPaletteDiv : function () {
        var paletteDiv = document.createElement('div');
        paletteDiv.setAttribute('class', 'palette');
        paletteDiv.gatherData = gatherPassThrough;
        return paletteDiv;
    },
    
    createPaletteResultsContainer : function () {
        var pResContainer = document.createElement('div');
        pResContainer.setAttribute('class', 'paletteResults');
        return pResContainer;
    },
    
    createCanvasDiv : function () {
        var cDiv = document.createElement('div');
        cDiv.setAttribute('class', 'canvasResults');
        return cDiv;
    },
    
    createTab : function () {
        var tDiv = document.createElement('div');
        tDiv.setAttribute('class', 'tab');
        return tDiv;
    },
    
    
    
    
    empty: function (div) {
        if (div.childNodes && (div.childNodes != null)) {
            while (div.childNodes.length != 0) {
                
                div.removeChild(div.firstChild);
            }
        }
    },
    
    fireGoButton: function(event) {
    
        if (event.keyCode == 13) {
            var bttn = this.parentNode.getElementsByTagName('button')[0];
            if (bttn) {
                bttn.click();
            } 
        }
    }, 
    /*********************
    *
    * Conversions
    *
    **********************/
    
    
    //TODO
    //see about X-browser way.  this might make it FF only (though I'm not sure a care, given my audience)
    makeSubjectClone : function (s) {
        var jsonSrc = s.json.toSource();
        return new Subject(eval(jsonSrc));
    },
    
    isbn13To10: function (isbn13) {
        //TODO rremove dashes and spaces when it is input.
        
        isbn10 = isbn13.slice(3, - 1);
        
        checksum = 0;
        weight = 10;
        for (var i = 0; i < 10; i++) {
            dig = isbn10.charAt(i);
            checksum += dig * weight;
            weight--;
        }
        
        checksum = 11 - (checksum % 11);
        if (checksum == 10) {
            isbn10 += "X";
        } else if (checksum == 11) {
            isbn10 += "0";
        } else {
            isbn10 += checksum;
        }
        return isbn10;
    },
    
    subjectToObject: function (s) {
        var newObj = { };
        newObj.type = 'uri';
        newObj.value = s.subject;
        return newObj;
    },
    

    /***********************
    *
    * Object Comparison
    *
    ************************/
    
    
    //TODO:  not sure I'm still using this!
    getDeeperObj: function (o1, o2) {
        //see if they're really deep equal
        if (this .objectsEqual(o1, o2, true)) {
            return false;
        }
        
        
        //a bit sloppy here-- if the lang or datatypes are different, that should be handled as an error in the original data
        if (o1.lang && o2.lang) {
            return false;
        }
        if (o1.datatype && o2.datatype) {
            return false;
        }
        //use the tertiary operator, stupid
        if (o1.lang || o2.lang) {
            if (o1.lang) {
                return o1;
            }
            if (o2.lang) {
                return o2;
            }
        }
        
        if (o1.datatype || o2.datatype) {
            if (o1.datatype) {
                return o1;
            }
            if (o2.datatype) {
                return o2;
            }
        }
    },
    
    
    objectsEqual: function (o1, o2, deep) {
        
        if (deep) {
            if ((o1.value == o2.value) && ((o1.datatype == o2.datatype) && (o1.lang == o2.lang))) {
                return true;
            }
        } else {
            if (o1.value == o2.value) {
                return true;
            }
        }
        return false;
    },
    
    
    /**************************
    *
    * Namespace mapping and URI manipulation
    *
    ******************************/
    

    
    queryPrefixes2NSMap: function (string) {
        //first, get an array of the PREFIX lines
        
        var re = /\s*(\w*):\s*<(\S *)>/;
        var prefLinesRE = /PREFIX. * /g;
        var prefixLines = string.match(prefLinesRE);
        for (var i in prefixLines) {
            var matches = prefixLines[i].match(re);
            this .addNSMap(matches[1], matches[2]);
        }
    },
    
    
    contractURI: function (uri) {
        for (var prefix in this .nsMap) {
            var parts = uri.split(this .nsMap[prefix]);
            if (parts.length == 2) {
                var contracted = prefix + ':' + parts[1];
                return contracted;
            }
        }
        return uri;
    },
    
    
    expandPrefix: function (toexpand) {
        
        var split = toexpand.split(':');
        for (prefix in this .nsMap) {
            if (prefix == split[0]) {
                return this .nsMap[prefix] + split[1];
            }
        }
        return toexpand;
    },
    addNSMap: function (ns, expanded) {
        this .nsMap[ns] = expanded;
    },
    
    nsMap: {
        rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
        sioc: 'http://rdfs.org/sioc/ns#',
        foaf: 'http://xmlns.com/foaf/0.1/',
        dc: 'http://purl.org/dc/elements/1.1/',
        dcterms: 'http://purl.org/dc/terms/',
        rdfs: 'http://www.w3.org/2000/01/rdf-schema#',
        tagging: 'http://www.holygoat.co.uk/owl/redwood/0.1/tags/',
        dctypes: 'http://purl.org/dc/dcmitype/',
        xsd: 'http://www.w3.org/2001/XMLSchema#',
        bibo: 'http://purl.org/ontology/bibo/',
        skos: 'http://www.w3.org/2004/02/skos/core#',
        //geg: 'http://ravendesk.org/giantedugraph/'
        geg:  'http://www.ravendesk.org/giantedugraph#'
    }
};







/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/

MIGHT GO AWAY!
*
**/

var Base64 = {
    
    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    
    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        
        input = Base64._utf8_encode(input);
        
        while (i < input.length) {
            
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
            
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) |(chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) |(chr3 >> 6);
            enc4 = chr3 & 63;
            
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            
            output = output +
            this ._keyStr.charAt(enc1) + this ._keyStr.charAt(enc2) +
            this ._keyStr.charAt(enc3) + this ._keyStr.charAt(enc4);
        }
        
        return output;
    },
    
    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
        
        input = input.replace(/[^A-Za-z0-9\ + \/\=]/g, "");
        
        while (i < input.length) {
            
            enc1 = this ._keyStr.indexOf(input.charAt(i++));
            enc2 = this ._keyStr.indexOf(input.charAt(i++));
            enc3 = this ._keyStr.indexOf(input.charAt(i++));
            enc4 = this ._keyStr.indexOf(input.charAt(i++));
            
            chr1 = (enc1 << 2) |(enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) |(enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            
            output = output + String.fromCharCode(chr1);
            
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        
        output = Base64._utf8_decode(output);
        
        return output;
    },
    
    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g, "\n");
        var utftext = "";
        
        for (var n = 0; n < string.length; n++) {
            
            var c = string.charCodeAt(n);
            
            if (c < 128) {
                utftext += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            } else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        
        return utftext;
    },
    
    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
        
        while (i < utftext.length) {
            
            c = utftext.charCodeAt(i);
            
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if ((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) |(c2 & 63));
                i += 2;
            } else {
                c2 = utftext.charCodeAt(i + 1);
                c3 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) |((c2 & 63) << 6) |(c3 & 63));
                i += 3;
            }
        }
        
        return string;
    }
}



