var isOpera = navigator.userAgent.indexOf("Opera") > -1;
var isSafari = navigator.userAgent.indexOf("Safari") > -1;
var isWebKit = navigator.userAgent.indexOf("WebKit") > -1;
var isFirefox = navigator.userAgent.indexOf("Firefox") > -1;
var isFirefoxWin = isFirefox && navigator.userAgent.indexOf("Windows") > -1;
var isFirefoxMac = isFirefox && navigator.userAgent.indexOf("Mac") > -1;
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {
    var ffversion = new Number(RegExp.$1)
}
var isFirefox35 = (ffversion == 3.5);
var isFirefox36 = (ffversion == 3.6);

var isExplorer = navigator.userAgent.indexOf("MSIE") > -1;
var isExploder = isExplorer;
var isExplorerWin = isExploder && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1
var isExplorer6 = navigator.userAgent.indexOf("MSIE 6") > -1;
var isExplorer7 = navigator.userAgent.indexOf("MSIE 7") > -1;
var isExplorer8 = navigator.userAgent.indexOf("MSIE 8") > -1;
var isExplorer8Up = isExploder && !isExplorer6 && !isExplorer7;
var fireOnObj;

var SNWebUI_NamingContainerHashTable = null;

Array.prototype.indexOf = function(value) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == value) return i;
    }
    return -1;
}
Array.prototype.contains = function(value) {
    return this.indexOf(value) != -1;
}

String.prototype.isEmpty = function(find, replace) {
    return this.trim() == "";
}
String.prototype.replaceAll = function(find, replace) {
    return this.split(find).join(replace);
}
String.prototype.trim = function() {
    var match = /\s*(.*?)\s*/.exec(this);
    return match[1];
}

document.getElementByServerId = function(id) {
    var obj = document.getElementById(id);
    if (!isUndefined(obj)) return obj;
    if (!isUndefined(SNWebUI_NamingContainerHashTable)) {
        if (SNWebUI_NamingContainerHashTable.containsKey(id)) return document.getElementById(SNWebUI_NamingContainerHashTable.get(id));
    }
    return obj;
}

var Hashtable = function(keysArray, valuesArray) {
    this.keys = new Array();
    this.values = new Array();

    if ((!isUndefined(keysArray) && isUndefined(valuesArray)) || (isUndefined(keysArray) && !isUndefined(valuesArray))) throw "Both keys and values array must be defined.";
    if (!isUndefined(keysArray) && !isUndefined(valuesArray)) {
        if (keysArray.length != valuesArray.length) throw "Keys array and values array must be the same length.";
        for (var i = 0; i < keysArray.length; i++) this.set(keysArray[i], valuesArray[i]);
    }
}
Hashtable.prototype.add = function(key, value) {
    if (key == null) throw "Key cannot be null.";
    if (this.keys.indexOf(key) > -1) throw "Key exists in the collection already.";
    this.keys[this.keys.length] = key;
    this.values[key] = value;
    this.length = this.keys.length;
}
Hashtable.prototype.set = function(key, value) {
    if (key == null) throw "Key cannot be null.";
    if (this.keys.indexOf(key) == -1) this.add(key, value);
    else this.values[key] = value;
}
Hashtable.prototype.clear = function() {
    this.keys = new Array();
    this.values = new Array();
    this.length = 0;
}
Hashtable.prototype.containsKey = function(key) {
    return this.keys.indexOf(key) > -1;
}
Hashtable.prototype.get = function(key) {
    return this.values[key];
}
Hashtable.prototype.remove = function(key) {
    if (this.keys.indexOf(key) == -1) throw "Key does not exists in the collection.";
    this.values[key] = null;
    var index = this.keys.indexOf(key);
    this.keys.splice(index, 1);
}
Hashtable.prototype.size = function() {
    return this.keys.length;
}

var Tracer = function(width, height, left, top) {
    this.width = width || 500;
    this.height = height || 500;
    this.left = left || (document.body.offsetWidth - this.width - 23);
    this.top = top || (document.body.offsetHeight - this.height - 13);

    this.body = document.createElement('div');
    this.body.style.border = "#000 1px solid";
    this.body.style.clear = "both";
    this.body.style.padding = "2px";
    this.body.style.width = this.width + 'px';
    this.body.style.height = this.height + 'px';
    this.body.style.position = 'absolute';
    this.body.style.top = this.top + 'px';
    this.body.style.left = this.left + 'px';

    this.output = document.createElement('div');
    this.output.style.color = "#f00";
    this.output.style.textAlign = "left";
    this.output.style.width = (this.width - 4) + 'px';
    this.output.style.height = (this.height - 22) + 'px';
    this.output.style.overflow = 'scroll';

    var btn = document.createElement('button');
    btn.output = this.output;
    btn.innerHTML = "Clear";
    btn.onclick = function() { this.output.innerHTML = ''; }

    this.body.appendChild(btn);
    this.body.appendChild(this.output);
    document.body.appendChild(this.body);
}
Tracer.prototype.setWidth = function(value) {
    this.width = value;
    this.body.style.width = this.width;
}
Tracer.prototype.setWidth = function(value) {
    this.height = value;
    this.body.style.height = this.height;
}
Tracer.prototype.writeLine = function(message) {
    var div = document.createElement('DIV');
    div.innerHTML = message;
    this.body.childNodes[1].appendChild(div);
    div.scrollIntoView()
}

function convertToObject(objOrString) {
    if (typeof (objOrString) == "string") {
        var result = null;
        try {
            result = eval(objOrString);
        } catch (e) { }
        if (isUndefined(result)) result = document.getElementByServerId(objOrString);
        if (!isUndefined(result)) return result;
    }
    return objOrString;
}

function copyValueTo(obj, id) {
    var destination = convertToObject(id);
    if (!isUndefined(obj) && !isUndefined(destination)) destination.value = obj.value;
}

function createTable(numRows, numCells, rowHeights, cellWidths) {
    var tbl = document.createElement("TABLE");
    if (!isUndefined(rowHeights) && !isUndefined(cellWidths)) tbl.style.tableLayout = "fixed";
    for (var i = 0; i < numRows; i++) {
        var row = tbl.insertRow(i);
        for (var j = 0; j < numCells; j++) {
            var cell = row.insertCell(j);
            if (!isUndefined(rowHeights)) {
                if (!isExploder || (isExploder && rowHeights[i] > 0)) cell.height = rowHeights[i];
            }
            if (!isUndefined(cellWidths)) {
                if (!isExploder || (isExploder && cellWidths[j] > 0)) cell.width = cellWidths[j];
            }
        }
    }
    return tbl;
}

function fireEventOnObject(obj, relatedObj, eventName) {
    obj = convertToObject(obj);
    relatedObj = convertToObject(relatedObj);

    if (fireOnObj == relatedObj) {
        fireOnObj = null;
        return;
    }

    fireOnObj = obj;

    if (isExploder) obj.fireEvent(eventName);
    else {
        var evt = document.createEvent("MouseEvents");
        if (eventName.substring(0, 2) == "on") eventName = eventName.substring(2);

        evt.initMouseEvent(eventName, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        obj.dispatchEvent(evt);
    }
}

function getCookie(name) {
    if (document.cookie.length > 0) {
        var index = document.cookie.indexOf(name + "=")
        if (index != -1) {
            index = index + name.length + 1;
            ends = document.cookie.indexOf(";", index)
            if (ends == -1) ends = document.cookie.length;
            return unescape(document.cookie.substring(index, ends))
        }
    }
    return null;
}

function getChildNodeCount(obj) {
    var curr = 0;
    for (var i = 0; i < obj.childNodes.length; i++) {
        if (obj.childNodes[i].nodeType == 3) continue;
        curr++;
    }
    return curr;
}

function getChildNode(obj, index) {
    var curr = 0;
    for (var i = 0; i < obj.childNodes.length; i++) {
        if (obj.childNodes[i].nodeType == 3) continue;
        if (curr == index) return obj.childNodes[i];
        curr++;
    }
    return null;
}

function getFileExtension(path) {
    return path.substring(path.lastIndexOf("."), path.length);
}

function getOffsetLeftFromBody(obj) {
    obj = convertToObject(obj);
    if (isUndefined(obj) || obj == null) return 0;
    var temp = obj;
    var result = temp.offsetLeft;
    if (temp.tagName == "TABLE" && temp.align == "center") result = 0; //this needs to be looked at in detail
    while (temp.offsetParent != null) {
        temp = temp.offsetParent;
        result += temp.offsetLeft;
    }
    return result;
}

function getOffsetTopFromBody(obj) {
    obj = convertToObject(obj);
    if (isUndefined(obj) || obj == null) return 0;
    var temp = obj;
    var result = temp.offsetTop;
    while (temp.offsetParent.tagName != 'BODY') {
        temp = temp.offsetParent;
        result += temp.offsetTop;
    }
    return result;
}

function getOffsetParentOfType(obj, tagName) {
    if (obj == null) return null;
    if (isUndefined(obj)) return null;
    if (isUndefined(obj.tagName)) return null;
    while (obj.parentNode != null) {
        if (obj.parentNode.tagName.toUpperCase() == tagName.toUpperCase()) return obj.parentNode;
        obj = obj.parentNode;
    }
    return null;
}

function getRectangle(obj) {
    if (isUndefined(obj)) return null;
    if (isUndefined(obj.tagName)) return null;
    var ix = getOffsetLeftFromBody(obj);
    var iy = getOffsetTopFromBody(obj);
    var iw = obj.offsetWidth;
    var ih = obj.offsetHeight;
    return { x: ix, y: iy, width: iw, height: ih };
}

function hookupEvent(control, eventType, functionString, isPrefix) {
    if (isUndefined(isPrefix)) isPrefix = true;
    var ev;
    eval("ev = control." + eventType + ";");
    if (typeof (ev) == "function") {
        ev = ev.toString();
        ev = ev.substring(ev.indexOf("{") + 1, ev.lastIndexOf("}"));
    }
    else ev = "";

    var func;
    if (navigator.appName.toLowerCase().indexOf('explorer') > -1) {
        if (isPrefix) func = new Function(functionString + " " + ev);
        else func = new Function(ev + " " + functionString);
    }
    else {
        if (isPrefix) func = new Function("event", functionString + " " + ev);
        else func = new Function("event", ev + " " + functionString);
    }
    eval("control." + eventType + " = " + func);
}

function isUndefined(obj) {
    if (typeof (obj) == "undefined") return true;
    return obj == null;
}

function registerNonIEFocusSetActiveElement() {
    if (!isExploder) document.addEventListener("focus", setActiveElementHandler, false);
}

function registerNonIEClickSetActiveElement() {
    if (!isExploder) document.addEventListener("click", setActiveElementHandler, false);
}

function setCookie(name, value, expires) {
    if (isUndefined(expires)) {
        expires = new Date();
        expires.setDate(expires.getDate() + 365);
    }
    document.cookie = name + "=" + escape(value) + ";expires=" + expires.toGMTString();
}

function setOpacity(obj, opacity) {
    obj = convertToObject(obj);
    obj.opacity = opacity;
    if (isFirefox || isSafari) obj.style.opacity = opacity / 100;
    else if (isExploder) obj.style.filter = "alpha(opacity=" + opacity + ")";
}

function setActiveElementHandler(event) {
    document.activeElement = (event.target.nodeType == Node.TEXT_NODE) ? event.target.parentNode : event.target;
}

function setObjectFloat(obj, value) {
    if (isExploder) obj.style.styleFloat = value;
    else obj.style.cssFloat = value;
}

function swapImage(imageObj, imageUrl) {
    imageObj = convertToObject(imageObj);

    var usesAlphaImageFilter = isExplorer6 && (imageObj.style.cssText.indexOf('DXImageTransform.Microsoft.AlphaImageLoader') > -1 || imageObj.parentNode.style.cssText.indexOf('DXImageTransform.Microsoft.AlphaImageLoader') > -1);

    //alert(usesAlphaImageFilter);

    if (isUndefined(imageUrl)) imageUrl = imageObj.originalSrc;
    else {
        if (isUndefined(imageObj.originalSrc)) {
            if (!usesAlphaImageFilter) imageObj.originalSrc = imageObj.src;
            else imageObj.originalSrc = isUndefined(imageObj.filters['DXImageTransform.Microsoft.AlphaImageLoader']) ? imageObj.parentNode.filters['DXImageTransform.Microsoft.AlphaImageLoader'].src : imageObj.filters['DXImageTransform.Microsoft.AlphaImageLoader'].src;
        }
    }
    if (usesAlphaImageFilter) {
        if (imageObj.parentNode.filters['DXImageTransform.Microsoft.AlphaImageLoader'])
            imageObj.parentNode.filters['DXImageTransform.Microsoft.AlphaImageLoader'].src = imageUrl;
        else if (imageObj.filters['DXImageTransform.Microsoft.AlphaImageLoader'])
            imageObj.filters['DXImageTransform.Microsoft.AlphaImageLoader'].src = imageUrl;
    }
    else imageObj.src = imageUrl;
}


function toggleErrorDetails(anchor, id) {
    var r = convertToObject(id);
    if (r.style.display == 'none') {
        r.style.display = '';
        anchor.innerHTML = 'Hide details';
    }
    else {
        r.style.display = 'none';
        anchor.innerHTML = 'Show details';
    }
}

function toggleHeaderRowSiblingDisplay(clickee) {
    var table = clickee.parentNode.parentNode.parentNode.parentNode; //img->cell->row->tbody->table
    if (isExplorer && typeof (clickee.isExpanded) == "string") clickee.isExpanded = clickee.isExpanded == 'True';
    else if (typeof (clickee.isExpanded) == "undefined") clickee.isExpanded = clickee.getAttribute('isExpanded') == 'True';
    var args = toggleHeaderRowSiblingDisplay.arguments;
    for (var i = 1; i < args.length; i++) {
        var index = parseInt(args[i]);
        table.rows[index].style.display = clickee.isExpanded ? 'none' : '';
    }
    clickee.isExpanded = !clickee.isExpanded;
    clickee.src = clickee.isExpanded ? minusImageUrl : plusImageUrl;
    clickee.title = clickee.isExpanded ? 'Click to collapse' : 'Click to Expand';
}

function toggleSelectVisibility(state) {
    var selects = document.getElementsByTagName('SELECT');
    for (var i = 0; i < selects.length; i++) {
        if (isUndefined(selects[i].xvisibility)) selects[i].xvisibility = selects[i].style.visibility;
        selects[i].style.visibility = state ? selects[i].xvisibility : 'hidden';
    }
}


