st_quotetool = this.st_quotetool || {};
st_quotetool.calls = st_quotetool.calls || {};
st_quotetool.seq = st_quotetool.seq || 0;

st_quotetool.Layout = function() {
    // regionType -> [elementId, elementId, ...]
    this.map = {};

    this.addRegion = function(id, type) {
        this.initType(type);
        this.map[type].push(id);
    }

    this.toJSON = function() {
        var types = new Array();
        for (var type in this.map)
            types.push(type);
        return '[' + types.join(',') + ']';
    }

    this.initType = function(type) {
        if (!this.map[type]) {
            this.map[type] = new Array();
            this.map[type].contains = function(value) {
                for (var i in this)
                    if (this[i] == value)
                        return true;
                return false;
            };
        }
    }

    this.absorb = function(other) {
        for (var type in other.map) {
            this.initType(type);
            for (var otheri in other.map[type]) {
                var otherId = other.map[type][otheri];
                if (!this.map[type].contains(otherId))
                    this.map[type].push(otherId);
            }
        }
    }

    this.getBiggestRegions = function() {
        var types = new Array();
        for (var type in this.map)
            types.push(type);

        types.sort();
        if (types)
            return this.map[types[0]];
    }
}

st_quotetool.layout = st_quotetool.layout || new st_quotetool.Layout();

st_quotetool.call = function(path, args) {
    args = args || {};
    args.layout = args.layout || this.layout.toJSON();
    args.JSONCallback = args.JSONCallback || 'st_quotetool.onResponse';
    args.JSONErrorHandler = args.JSONErrorHandler || 'st_quotetool.onError';

    var reqId = args['reqId'] || (args['reqId'] = ++this.seq);

    if (st_quotetool.baseURL)
    {
        path = st_quotetool.baseURL + path;
        if ( !args.baseURL)
            args.baseURL = st_quotetool.baseURL;
    }

    path += path.match(/\?/) ? '&' : '?';
    path += this.toQueryString(args);
    var script = document.createElement('script');
    script.src = this.base + path;
    script.type = 'text/javascript';
    
    this.calls[reqId] = script;
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(script);
}

st_quotetool.cancelRequests = function() {
    for (var i in this.calls) {
        if (this.calls[i]) {
            var script = this.calls[i];
            script.parentNode.removeChild(script);
            this.calls[i] = undefined;
        }
    }
}

st_quotetool.onResponse = function(arg) {
    if (!(arg && arg.reqId && this.calls[arg.reqId])) return;
    this.calls[arg.reqId] = undefined;

    if (arg.categories)
        this.onCategories(arg.categories);
    if (arg.style) 
        this.onStyle(arg.style);
    if (arg.layout)
        this.onLayout(arg.layout);
    if (arg.messages)
        this.onMessages(arg.messages);
    else {
        // no new messages. Make sure 
        // there are no errant masks lying around
        for (var type in this.layout.map) {
            for (var i in this.layout.map[type]) {
                var id = this.layout.map[type][i];
                var region = document.getElementById(id);
                if (!region) continue;
                var el = this.findFirstChildWithClass(region, 'st_quoteTool');
                if (!el) continue;
                this.unmask(el);
            }
        }
    }
}

st_quotetool.onCategories = function(categories) {
    this.categories = categories;
}

st_quotetool.onStyle = function(style) {
    var el = document.createElement('style');
    el.type = 'text/css';
    
    // for IE
    if (el.styleSheet)
        el.styleSheet.cssText = style;
    else
        el.appendChild(document.createTextNode(style));

    document.getElementsByTagName('head')[0].appendChild(el);
}

st_quotetool.onLayout = function(layout) {
    for (var type in layout) {
        var regions = this.layout.map[type];
        if (!(regions && layout[type])) continue;

        for (var i in regions) {
            var container = document.getElementById(regions[i]);
            if (!container) continue;
            container.innerHTML = layout[type];

            // process forms
            var forms = container.getElementsByTagName('form');
            for (var j in forms) {
                var form = forms[j];

                if (form == undefined || !form.action || form.action == undefined) continue;
                if (this.hasClass(form, 'nojson'))
                    continue;

                form._onsubmit = form.onsubmit;
                form.onsubmit = function() {
                    if (this._onsubmit && !this._onsubmit())
                        return false;
                    st_quotetool.submitForm(this);
                    return false;
                };

                // prepopulate fields
                var queryMap = this.getQueryMap();
                for (var j=0; j < form.elements.length; j++){
                    var el = form.elements[j];
                    if (!(el.name && queryMap[el.name])) continue;
                    // TODO: handle different kinds of element types
                    el.value = escape(queryMap[el.name]);
                }

                // initialize category selectors
                if (!this.categories) continue;
                var divs = form.getElementsByTagName('div');
                for (var j in divs) {
                    if (divs[j] == undefined || (divs[j].className != 'st_quote_category'))
                        continue;
                    new this.CategorySelector(divs[j], form, this.categories);
                }
            }

            // process links
            var links = container.getElementsByTagName('a');
            for (var j in links) {
                var link = links[j];
                if (!link) continue;
                if (this.hasClass(link, 'nojson')) {
                    link.target = this.target;
                    continue;
                }
                if (!link.href) continue;
                link._href = link.href;
                link._onclick = link.onclick;
                link.href = 'javascript:void(0)';
                link.onclick = function() {
                    if (this._onclick) {
                        var b = this._onclick();
                        if (!b)
                            return false;
                    }
                    try {
                        st_quotetool.setLoading(this);
                        st_quotetool.call(this._href);
                    } catch (err) {
                        st_quotetool.unmask(this);
                    }
                    return false;
                };
            }

            //process poppers and detailers
            var divs = container.getElementsByTagName('div');
            for (var j in divs)
            {
                var div = divs[j];
                if (!div) continue;
                if (this.hasClass(div, 'st_quoteTool_popper') && div.innerHTML)
                {
                    div._content = div.innerHTML;
                    div.innerHTML = '';
                    div.onmouseover = function() { this.className = 'st_quoteTool_popper_hover'; };
                    div.onmouseout = function() { this.className = 'st_quoteTool_popper'; };
                    div.onclick = function() {
                        if (this._content) {
                            var contentel = st_quotetool.formatPopupContent('Details', this._content, 'info');
                            st_quotetool.openPopup(this, contentel);
                        }
                    };
                }
                else if (this.hasClass(div, 'st_quoteTool_popper2') && div.innerHTML && div.childNodes)
                {

                    var contentNode;
                    var replacementNode;
                    for (var n = 0; n < div.childNodes.length; n++)
                    {
                        var child = div.childNodes[n];
                        if ( this.hasClass(child, 'st_quoteTool_popper2_content'))
                        {
                            contentNode = child;
                        }
                        else if (this.hasClass(child, 'st_quoteTool_popper2_replacement'))
                        {
                            replacementNode = child;
                        }
                        if ( contentNode != undefined && replacementNode != undefined)
                            break;
                    }
                    var popperTitle = div.getAttribute("popper_title");
                    if ( popperTitle == undefined)
                        popperTitle = 'Details';
                    var popperType = div.getAttribute("popper_type");
                    if ( popperType == undefined)
                        popperType = 'info';

                    replacementNode._content = contentNode.innerHTML;
                    div.removeChild(contentNode);
                    replacementNode.onclick = function() {
                        if (this._content) {
                            var contentel = st_quotetool.formatPopupContent(popperTitle, this._content, popperType);
                            st_quotetool.openPopup(this, contentel, false);
                        }
                    };
                    div.parentNode.replaceChild(replacementNode, div);
                }
                else if (this.hasClass(div, 'st_quoteTool_detailer'))
                {
                    div._content = div.innerHTML;
                    div._container = container;
                    if (div.title)
                        div.innerHTML = div.title;
                    else
                        div.innerHTML = 'details';
                    div.onmouseover = function(){this.className = 'st_quoteTool_detailer_hover';};
                    div.onmouseout = function(){this.className = 'st_quoteTool_detailer';};
                    div.onclick = function(e) {
                        var newContent = document.createElement('div')
                        newContent.innerHTML = this._content;
                        st_quotetool.swapContent(this._container, newContent, true);
                    };
                }
            }
        }
    }
}

st_quotetool.formatPopupContent = function(title, content, type) {
    var wrapper = document.createElement('div');
    wrapper.className = type + 'Wrapper';

    var closer = document.createElement('div');
    closer.appendChild(document.createTextNode('X'));
    closer.className = type + 'Close';
    closer.onclick = function() { st_quotetool.unmask(this) };

    if (title) {
        var header = document.createElement('div');
        header.appendChild(document.createTextNode(title))
        header.className = type + 'Title';
    }

    var body = document.createElement('div');
    body.innerHTML = content;
    body.className = type + 'Cnt';

    wrapper.appendChild(closer);
    wrapper.appendChild(header);
    wrapper.appendChild(body);
    return wrapper;
}

st_quotetool.onMessages = function(messages) {
    var message = messages[0];
    regions = this.layout.getBiggestRegions();
    for (i in regions)
    {
        var el = document.getElementById(regions[i]);
        if (el)
        {
            el = this.findFirstChildWithClass(el, 'st_quoteTool');
            var contentel = this.formatPopupContent('Error', message, 'error');
            if (el) this.openPopup(el, contentel);
        }
    }
}

st_quotetool.swapContent = function(el, newContent, addbacklink) {
    el.style.width = (el.innerWidth || el.clientWidth) + 'px';
    var transwrap = document.createElement('div');
    transwrap.style.position = 'relative';
    transwrap.style.width = el.style.width;
    transwrap.style.height = (el.innerHeight || el.clientHeight) + 'px';
    transwrap.style.display = 'block';

    var oldContent = document.createElement('div');
    oldContent.style.opacity = 1;
    oldContent.style.position = 'absolute';
    oldContent.style.top = 0;
    oldContent.style.left = 0;
    transwrap.appendChild(oldContent);

    newContent.style.position = 'absolute';
    newContent.style.top = 0;
    newContent.style.left = 0;
    newContent.style.opacity = 0;
    if (addbacklink) {
        var back = document.createElement('div');
        back.className = 'st_quoteTool_details_back';
        back.appendChild(document.createTextNode('back'));
        back.onclick = function() {st_quotetool.swapContent(el, oldContent);};
        back.onmouseover = function() {this.className = 'st_quoteTool_details_back_hover';};
        back.onmouseout = function() {this.className = 'st_quoteTool_details_back';};
        newContent.insertBefore(back, newContent.firstChild);
    }
    transwrap.appendChild(newContent);

    while (el.firstChild) oldContent.appendChild(el.removeChild(el.firstChild));
    el.appendChild(transwrap);

    var millis = 300;
    var steps = millis * 30 / 1000; // 30Hz

    var setopacity = function(element, opacity) {
        element.style.opacity = opacity;     // 0 - 1
        element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';  // 0 - 100
    }

    var opacitydown = function() {
        setopacity(oldContent, parseFloat(oldContent.style.opacity) - 1/steps);
    }

    var opacityup = function() {
        setopacity(newContent, parseFloat(newContent.style.opacity) + 1/steps);
    }

    for (var i=1; i < steps; i++) {
        setTimeout(opacitydown, i * millis/steps);
        setTimeout(opacityup, i * millis/steps);
    }

    setTimeout(function(){
        while (el.firstChild) el.removeChild(el.firstChild);
        while (newContent.firstChild) el.appendChild(newContent.removeChild(newContent.firstChild));
    }, millis);
}

st_quotetool.openPopup = function(el, contentel, closeOnClick) {
    var contentDiv = document.createElement('div');
    contentDiv.className = 'st_quoteTool_pop';
    contentDiv.appendChild(contentel);
    var mask = this.mask(el);
    mask.innerHTML = '';
    mask.appendChild(contentDiv);
    if ( closeOnClick == undefined || closeOnClick == true)
        mask.onclick = function() { st_quotetool.unmask(this) };
}

st_quotetool.mask = function(el) {
    el = this.findParentWithClass(el, 'st_quoteTool');
    if (!el) return;
    if (el.mask)
        return el.mask;

    var mask = document.createElement('div');
    mask.className = 'st_quoteTool_mask';
    el.mask = mask;

    // IE6 has issues with selectors having the right z-index. Hide them.
    var selects = el.getElementsByTagName('select');
    var masked = new Array();
    for (var i=0; i < selects.length; i++) {
        selects[i].style.visibility = 'hidden';
        masked.push(selects[i]);
    }
    mask.selects = masked;

    el.appendChild(mask);
    return mask;
}

st_quotetool.unmask = function(el) {
    el = this.findParentWithClass(el, 'st_quoteTool');
    if (!(el && el.mask)) return;
    for (var i=0; i < el.mask.selects.length; i++)
        el.mask.selects[i].style.visibility = 'visible';
    el.removeChild(el.mask);
    el.mask = undefined;
}

st_quotetool.setLoading = function(el) {
    var loading = document.createElement('div');
    loading.className = "loaderImage";
    var img = document.createElement('img');
    img.src = '/img/quoteTool/loader_green.gif';
    img.width = img.height = '100';
    img.alt = 'Loading...';
    img.border = '0';
    loading.appendChild(img);

    var cancel = document.createElement('a');
    cancel.href = 'javascript:void(0)';
    cancel.onclick = function() {
        st_quotetool.cancelRequests();
        st_quotetool.unmask(this);
    };
    cancel.appendChild(document.createTextNode('cancel'));
    loading.appendChild(cancel);
    mask = this.mask(el);
    mask.appendChild(loading);
}


st_quotetool.hasClass = function(element, className) {
    if (element == null || element.className == undefined)
        return false;
    var classes = element.className.split(/\s+/);
    for (var i in classes)
        if (classes[i] == className)
            return true;
    return false;
}

st_quotetool.findParentWithClass = function(el, className) {
    for (;el && !this.hasClass(el, className); el = el.parentNode){}
    return el;
}

st_quotetool.findFirstChildWithClass = function(el, className) {
    if (this.hasClass(el, className)) return el
    for (var i in el.childNodes) {
        var child = el.childNodes[i];
        if (!child) continue;
        child = this.findFirstChildWithClass(child, className);
        if (child)
            return child;
    }
}

st_quotetool.submitForm = function(form) {
    var args = {};
    if ( typeof form == 'string')
    {
        // do this instead of using document.getElementById because of some weird issue in IE
        var forms = document.getElementsByTagName('form');
        for ( var i in forms)
        {
            var currentForm = forms[i];
            if (currentForm.id == form)
            {
                form = currentForm;
                break;
            }
        }
        if ( typeof form == 'string')
            return;
    }

    for (var i in form.elements) {
        var e = form.elements[i];
        if (!e) continue;
        var value;

        if (e.categorySelector) {
            if (e.categorySelector.link) {
                // get the query string parameters from the url
                var queryStringParameters = this.toQueryString(this.getQueryMap());

                // include all query string parameters in the link if set
                var linkWithQueryStringParameters = e.categorySelector.link
                        + (queryStringParameters.length > 0 ? "?" + queryStringParameters : '');

                if ( this.target == '_parent')
                    location.href = linkWithQueryStringParameters;
                else
                    st_quotetool.openWin({url: linkWithQueryStringParameters, name: this.target});
                return;
            } else
                value = e.categorySelector.id;
        } else {
            switch (e.type){
                case 'checkbox':
                    value = e.checked;
                    break;
                case 'submit':
                    break;
                case 'radio':
                    if (!e.checked)
                        continue;
                default:
                    value = e.value;
                    break;
            }
            if (!(e.name && e.value))
                continue;
        }
        if (value && typeof value == 'string')
            value = value.replace(/^\s+/, '').replace(/\s+$/, '');
        if (value)
            args[e.name] = value;
    }
    try {
        this.setLoading(form);
        this.call(form.action, args);
    } catch (err) {
        this.unmask(form);
    }
}


st_quotetool.onError = function(err) {
    var buf = '';
    for (var i in err)
        buf += i + '=' + err[i] + '\n';
    alert('error: ' + buf);
}

st_quotetool.toQueryString = function(args) {
    var pairs = new Array();
    for (var i in args)
        pairs.push(i + '=' + escape(args[i]));
    return pairs.join('&');
}

st_quotetool.getQueryMap = function() {
    var map = {};
    var s = location.search;
    var arr = s.substring(1, s.length).replace(/\+/g, ' ').split('&');
    for (var i in arr) {
        if (!arr[i]) continue;
        var pair = arr[i].split('=');
        map[unescape(pair[0])] = (unescape(pair[1]) || null);
    }
    return map;
}

st_quotetool.displayQuoteTool = function(layout, args) {
    args = args || {};
    this.layout.absorb(layout);
    qargs = this.getQueryMap();
    for (k in qargs)
        args[k] = qargs[k];
    this.target = args.target || '_parent';
    this.base = args.base || '';

    args.refreshAll = true;
    args.layout = this.layout.toJSON();
    // define base url if present
    if ( args.baseURL != undefined)
        st_quotetool.baseURL = baseURL;

    this.call('/squaretrade/quotetool/Init.action', args);
}

st_quotetool.CategorySelector = function(element, form, categories) {
    this.element = element;
    this.root = {categories: categories};
    this.form = form;
    this.seq = 0;

    this.findNodeInTree = function(key, tree, property) {
        property = property || 'nid';
        if (key == tree[property])
            return tree;

        for (var i in tree.categories) {
            var child = tree.categories[i];
            var node = this.findNodeInTree(key, child, property);
            if (node)
                return node;
        }
        return null;
    }

    this.getNodePath = function(node) {
        var path = new Array();
        for (var n = node; n.parent_; n = n.parent_)
            path.push(n.nid)
        return path;
    }

    this.onLink = function() {
        for (var i=0; i < this.form.elements.length; i++) {
            var e = this.form.elements[i];
            // don't disable the ebay/retail radio buttons
            if (e.name && e.type != 'radio')
            {
                if (e.style.backgroundColor)
                    e.style._backgroundColor = '' + e.style.backgroundColor;
                else
                    e.style._backgroundColor = null;
                e.style.backgroundColor = '#ddd';
                e.disabled = true;
                // clear any text values
                if ( e.type == 'text')
                    e.value = '';
                else if ( e.type == 'checkbox') // uncheck any checkboxes
                    e.checked = false;
            }

        }
    }

    this.onUnlink = function() {
        for (var i=0; i < this.form.elements.length; i++) {
            var e = this.form.elements[i];
            if (e.name && e.disabled)
            {
                e.disabled = false;
                e.style.backgroundColor = e.style._backgroundColor || '#fff';
            }
        }
    }

    this.render = function(nid) {
        var node = this.findNodeInTree(nid, this.root) || this.root;
        var path = this.getNodePath(node);
        if (node) {
            this.element.innerHTML = '';
            this.link = node.link;
            this.id = node.id;
        }

        if (node.link)
            this.onLink();
        else
            this.onUnlink();

        for (; node; node = node.parent_) {
            if (node.categories) {
                var select = document.createElement('select');
                select.className = 'st_form_select';

                var firstOption = document.createElement('option');
                firstOption.value = node.nid;
                firstOption.appendChild(document.createTextNode('Select ...'));
                select.appendChild(firstOption);
                select.controller = this;
                select.onchange = function() {
                    this.controller.render(this.value);
                };

                for (var i in node.categories) {
                    var child = node.categories[i];
                    var option = document.createElement('option');
                    option.appendChild(document.createTextNode(child.name));
                    option.value = child.nid;
                    if (child.nid == path[0]) {
                        option.selected = true;
                        path.shift();
                    }
                    select.appendChild(option);
                }

                if (this.element.hasChildNodes())
                    this.element.insertBefore(select, this.element.firstChild);
                else
                    this.element.appendChild(select);
            }
        }
    }

    this.initNode = function(node, parent_) {
        node = node || this.root;
        node.nid = ++this.seq;
        node.parent_ = parent_;
        if (node.categories)
            for (var i in node.categories)
                this.initNode(node.categories[i], node);
    }

    this.initForm = function() {
        var input = document.createElement('input');
        input.type = 'hidden';
        input.name = 'categoryId';
        input.categorySelector = this;
        this.form.appendChild(input);
    }

    this.initForm();
    this.initNode();

    var preselectedNode;
    var preselect = st_quotetool.getQueryMap().itemCategory;
    if (preselect) {
        preselectedNode = preselectedNode || this.findNodeInTree(preselect, this.root, 'id');
        preselectedNode = preselectedNode || this.findNodeInTree(preselect, this.root, 'name');
    }

    this.render(preselectedNode ? preselectedNode.nid : 1);
}


st_quotetool.openWin = function (args)
{
    if ( !args.name )
        args.name = "_blank";

    if ( !args.resizable)
        args.resizable = "yes";
    var params = "resizable=" + args.resizable + ", scrollbars=yes, toolbar=yes, location=yes, menubar=yes";

    if ( args.width )
        params += ",width=" + args.width;
    else if ( args.widthPct )
        params += ",width=" + (screen.availWidth * args.widthPct);

    if ( args.height )
        params += ",height=" + args.height;
    else if (args.heightPct )
        params += ",height=" + (screen.availHeight * args.heightPct);

    var win = window.open(args.url, args.name, params);
    if ( win )
        win.focus();

    return win;

}

st_quotetool.copyValue = function(fromID, toID)
{
    var from = document.getElementById(fromID);
    if ( from == undefined || from.value == undefined)
        return;
    var to = document.getElementById(toID);
    if ( to == undefined)
        return;
    to.value = from.value;
}
