/*
 * Created by Florian Leitner on 2007-09-20.
 * Copyright (c) 2007 Florian Leitner.
 * All rights reserved.
 *  
 * GNU GPL LICENSE
 * 
 * This module is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; latest version thereof,
 * available at: <http://www.gnu.org/licenses/gpl.txt>.
 * 
 * This module is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this module; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
 */
 
function expandNormalization() {
    $("tbody#GN_overview_body > tr.normalizations_overview_row, " +
      "tbody#GN_detail_body > tr.prediction").each(function() {
        $.metadata.setType('attr','data')
        var data = null
        data = $.metadata.get($("div.GN_data", this).get(0))
        /*alert("adding click function to " + $(this).html() + 
              "\nwith data\ndb:" + data.database + "\nid:" + data.entry_id + 
              "\nlink:" + data.link + "\nname:" + data.name + "\ntax:" + 
              data.tax_id + "\nconf:" + data.confidence)*/
        $(this).click(function() {
            loadExpansionData(data)
            $("span#GN_help").hide()
            $("div#GN_expanded").show()
        })
    })
    $("div.GN").click(function() {
        $("div#GN_expanded").hide()
    })
}

function fitPPIBar(n, p, desc) {
    //alert("N:" + n[0] + "/" + n[1] + ";P:" + p[0] + "/" + p[1])
    $("#ppi_bar_negative").css({backgroundColor: n[1], width: n[0]})
    $("#ppi_bar_positive").css({backgroundColor: p[1], width: p[0]})
    $("#ppi_bar").click(
        function() {
            $("#ppi_bar_help").slideToggle("slow")
        }
    )
}

function flipView(source, target_A, target_B) {
    $(source).click(function() {
        $(target_A + ", " + target_B).toggle();
    })
}

function getMentionData() {
    var datalist = new Array()
    $(".GM_data").each(function() {
        $.metadata.setType('attr','data')
        datalist.push([$.metadata.get(this), this])
    })
    return datalist
}

function highlightMentions(textid, maxlevel) {
    $(textid + " > span.mention").each(function() {
        mentionRecursion(this, -1, maxlevel, new Array())
    })
    $(textid + " > span.mapping > span.mention").each(function() {
        mentionRecursion(this, -1, maxlevel, new Array())
    })
}

function loadExpansionData(data) {
    $("dd#GN_database").text(data.database)
    $("dd#GN_entry_id").text(data.entry_id)
    if (data.link != null) {
        $("dd#GN_link a").attr("href", data.link).text(data.name)
    } else {
        $("dd#GN_link a").attr("href", "").text(data.name)
    }
    $("dd#GN_taxon").text(data.taxon)
    if (data['confidence'] == null) {
        $("dd#GN_confidence").text("-")
    } else {
        $("dd#GN_confidence").text(data['confidence'])
    }
}

function loadGradient(gradient) {
    $("#mentions_gradient"
      ).html("<p><span class='emph'>Mention Gradient:</span> " +
             "<span class='text'>mention was detected by " + 
             gradient + " servers.</span></p>")
}

function loadMappingData(mention, data) {
    /* alert("data loaded for " + mention + ":\n" + data) */
    $("#mapping_mention").text(mention)
    $("#mapping_normalizations").empty()
    for (var i=0; i < data.length; i++) {
        /*alert("data[" + i + "]:\nurl:" + data[i].url + 
              "\nname:" + data[i].name + "\ntaxon:" + data[i].taxon)*/
        $("#mapping_normalizations"
          ).append('<li><a href="' + 
                   data[i].url + '" target="_blank">' + 
                   data[i].name + '</a><br/><span class="text">[' + 
                   data[i].taxon + ']</span></li>')
    };
}

function showMappingsSelector(obj, mentions, mappings) {
    var some_id = $("span.mention:first", obj).attr("id") + "_mapping"
    var strbuf = new Array()
    for (var i=0; i < mentions.length; i++) {
        strbuf.push("<a count='" + i + "'>" + mentions[i] + "</a>")
    };
    var dialog = ')<div id="' + some_id +
        '" class="bcms" title="Multiple mappings - select passage">' +
        strbuf.join("<br/>")
    dialog = $(dialog)
    $("a", dialog).click(function(i) {
        var cnt = parseInt($(this).attr("count"))
        loadMappingData(mentions[cnt], mappings[mentions[cnt]])
        $("#mapping_help").hide()
        $("#mappings").show()
        $(dialog).dialog("close")
    })
    $(dialog).dialog({draggable:true})
}

function mappingMarkupRecursion(obj, mentions, mappings) {
    $("span.mapping", obj).each(function() {
        var mention = $(this).text()
        mentions.push(mention)
        mappings[mention] = new Array()
        mapping = $.metadata.get($(this).get(0))
        for (var i=0; i < mentions.length; i++) {
            for (var j=0; j < mapping.length; j++) {
                mappings[mentions[i]].push(mapping[j])
            }
        }
        if ($("span.mapping", this).length > 0) {
            mappingMarkupRecursion($(this).html(), mentions, mappings)
        }
        starRows(mention, mappings[mention])
    })
}

function mappingMarkup() {
    /* TODO: count and divert depending on number of found inner
     * mapping spans.
     * Find way to show a dropdown of span choices for enclosed
     * mappings. (currently, just collects all inner spans) */
    $("span.mapping").each(function() {
        $.metadata.setType('attr','data')
        var mentions = new Array()
        var mappings = new Array()
        mentions[0] = $(this).text()
        mappings[mentions[0]] = $.metadata.get($(this).get(0))
        if ($("span.mapping", this).length > 0) {
            mappingMarkupRecursion($(this).html(), mentions, mappings)
        }
        if (mentions.length == 1) {
            $(this).click(function() {
                loadMappingData(mentions[0], mappings[mentions[0]])
                $("#mapping_help").hide()
                $("#mappings").show()
            })
            starRows(mentions[0], mappings[mentions[0]])
        } else {
            var obj = this
            $(this).click(function() {
                showMappingsSelector(obj, mentions, mappings)
            })
        }
        $(this).css({ fontStyle:"italic" })        
    })
}

function mentionHover(row, ids) {
    $(row).hover(
        function() {
            for (var i = ids.length - 1; i >= 0; i--) {
                $("#" + ids[i] + "_span > span.mention"
                  ).css("color", "purple").css("border", "thin solid purple")
                $("#" + ids[i] + "_span"
                  ).css("color", "purple").css("border", "thin solid purple")
            }
        },
        function() {
            for (var i = ids.length - 1; i >= 0; i--) {
                $("#" + ids[i] + "_span > span.mention"
                  ).css("color", "black").css("border-style", "none")
                $("#" + ids[i] + "_span"
                  ).css("color", "black").css("border-style", "none")
            }
        }
    )
}

function mentionMarkup(servers) {
    // maxlevel as float to calculate markup color strength [0.0 - 1.0]
    highlightMentions("#title", (parseInt(servers) - 1) * 1.0)
    highlightMentions("#abstract", (parseInt(servers) - 1) * 1.0)
    mentionMouseovers()
}

function mentionMouseovers() {
    var data = getMentionData()
    $(".mentions_overview_row").each(function() {
        var mention = $.trim($(".mentions_string", this).attr("title"))
        var ids = new Array()
        for (var i=0; i < data.length; i++) {
            if (escape(data[i][0]['representation']) == escape(mention)) {
                ids.push(data[i][0]['item_id'])
            }
        }
        mentionHover(this, ids)
    })
    $("tbody#GM_body > tr").each(function() {
        var ids = new Array()
        ids.push($(this).attr("itemid"))
        mentionHover(this, ids)
    })
}

function mentionRecursion(span, level, maxlevel, servers) {
    var strength = 0.0
    var server_id = parseInt($(span).attr("server"))
    var rgb_diff = new Array(0xFF - 0xE6, 0xF0 - 0xE6, 0xC0 - 0xE6)
    //var rgb_diff = new Array(0xD0 - 0xFF, 0xE7 - 0xF0, 0xFF - 0xC0)
    var rgb = new Array(0xE6, 0xE6, 0xE6) // light yellowish - light cyanish
    //var rgb = new Array(0xFF, 0xF0, 0xC0) // light yellowish - light cyanish
    if (span == null) {
        alert("Error: no content for recursion at level " + level)
        return
    }
    if (level > maxlevel) {
        alert("Error: recursion depth (" + level + "/" + maxlevel + ")")
        alert("In span:\n" + $(span).text())
        return
    }
    if (server_id == NaN || server_id == null || server_id == "NaN") {
        alert("server id NaN:\n" + $(span).text() + "\n" + $(span).attr("id"))
        return
    }
    // increase level if this server has not predicted anything on this span:
    level++
    for (var i=0; i < servers.length; i++) {
        if (server_id == servers[i]) {
            level--
            break
        }
    }
    if (maxlevel > 0 && level > 0) {
        strength = level / maxlevel // calc relative color gradient
    }
    if (strength > 1.0) {
        alert("bad strength=" + strength + ", level=" + level + ", max=" +
              maxlevel)
        strength = 1.0
    }
    for (var i = rgb.length - 1; i >= 0; i--){
        rgb[i] += Math.round(strength * rgb_diff[i]) // calc abs. gradient
    };
    var color = "rgb(" + rgb.join(", ") + ")"
    $(span).css("background-color", color)
    // recurse down into any further mention spans
    $("#" + $(span).attr("id") + ".mention > span.mapping > span.mention").each(function() {
        next_servers = new Array() // rebuild the array - may be changed
        for (var i=0; i < servers.length; i++) {
            next_servers.push(servers[i])
        }
        next_servers.push(server_id) // save server to known servers
        mentionRecursion(this, level, maxlevel, next_servers)
    })
    
    $("#" + $(span).attr("id") + ".mention > span.mention").each(function() {
        next_servers = new Array() // rebuild the array - may be changed
        for (var i=0; i < servers.length; i++) {
            next_servers.push(servers[i])
        }
        next_servers.push(server_id) // save server to known servers
        mentionRecursion(this, level, maxlevel, next_servers)
    })
}

function starRows(mention, data) {
    var normalizations = new Array(data.length)
    for (var i=0; i < data.length; i++) {
        normalizations[i] = data[i].name
    }
    // GM Overview
    $("tr.mentions_overview_row").each(function() {
        if ($("td.overview_prediction", this).attr("title") == mention) {
            $("td.has_mapping", this).text("*")
        }
    })
    // GN Overview
    $("tr.normalizations_overview_row").each(function() {
        var normalization = $("td.overview_prediction", this).attr("title")
        for (var i=0; i < normalizations.length; i++) {
            if (normalizations[i] == normalization) {
                //alert("fitted normalization" + normalization)
                $("td.has_mapping", this).text("*")
            }
        }
    })
}

function toggleSliding(source, target, speed, callback) {
    $(source).click(
        function() {
            $(target).slideToggle(speed, callback)
        }
    )
}

/* unused */
function toHex(dec) { 
    hexChars = "0123456789ABCDEF"
    if (dec > 255) {
        return null
    }
    var i = dec % 16
    var j = (dec - i) / 16
    result = "0x"
    result = ""
    result += hexChars.charAt(j)
    result += hexChars.charAt(i)
    return result
}
