/*
 * Copyright 2008-2010 Microarray Informatics Team, EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 * For further details of the Gene Expression Atlas project, including source code,
 * downloads and documentation, please see:
 *
 * http://gxa.github.com/gxa
 */

var atlas;
var resultEfvs;
var resultGenes;

if(!atlas)
    atlas = {};

(function($){

    function adjustPosition(el) {
         var v = {
             x: $(window).scrollLeft(),
             y: $(window).scrollTop(),
             cx: $(window).width(),
             cy: $(window).height()
         };

         var h = el.get(0);
         // check horizontal position
         if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
             var left = h.offsetLeft - (h.offsetWidth + 20 + 15);
             el.css({left: left + 'px'});
         }
         // check vertical position
         if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
             var top = h.offsetTop - (h.offsetHeight + 20 + 15);
             el.css({top: top + 'px'});
         }
     }

    function drawPlot(jsonObj,root, efvs, eid, eacc, gid){
        if(jsonObj.series) {
            var efvsh = {};
            for(var iefv in efvs)
                efvsh[efvs[iefv].efv.toLowerCase()] = efvs[iefv];

            if(!jsonObj.options)
                jsonObj.options = {};
            if(!jsonObj.options.legend)
                jsonObj.options.legend = {};
            jsonObj.options.legend.container = root.find('.legend');
            jsonObj.options.legend.extContainer = null;
            jsonObj.options.selection = null;

            jsonObj.options.arrayDesignContainer = '#' + eid + '_' + gid +'_arraydesign';
            var height = 1;
            var nlegs = 0;
            var markings = [];
            for (var i = 0; i < jsonObj.series.length; ++i){
                if(jsonObj.series[i].label) {
                    var series = jsonObj.series[i];
                    var efv = efvsh[jsonObj.series[i].label.toLowerCase()];
                    if(efv) {
                        var data = series.data;
                        var xMin= data[0][0] - 0.5;
                        var xMax= data[data.length-1][0] + 0.5;

                        markings.push({ xaxis: { from: xMin, to: xMax }, color: '#FFFFCC' });

                        if(series.label.length > 30)
                            series.label = series.label.substring(0, 30) + '...';
                        series.legend.show = true;
                        series.legend.isefv = true;
                        height += 2;
                        nlegs += 1;
                    } else if(series.legend.show) {
                        if(nlegs < 6) {
                            if(series.label.length > 30)
                                series.label = series.label.substring(0, 30) + '...';
                            height += 1;
                            nlegs += 1;
                        } else
                            series.legend.show = false;
                    }
                }
            }

            for (i = 0; nlegs > 6 && i < jsonObj.series.length; ++i) {
                series = jsonObj.series[i];
                if(!series.legend.isefv && series.legend.show) {
                    series.legend.show = false;
                    --nlegs;
                    --height;
                }
            }

            var plotel = root.find('.plot');
            if(height > 5) {
                if(height > 10)
                    height = 10;
                plotel.css({ height: (height * 16 + 20) + 'px' });
            }

            root.find('.plotwaiter').remove();
            root.find('.efname,.plot').show();

            jsonObj.options.grid.markings = markings;

            $.plot(plotel, jsonObj.series, jsonObj.options);
        }
    }

    atlas.hmc = function (igene, iefv, event) {
         $("#expopup").remove();

         var gene = resultGenes[igene];

         var efv; var efo;
         if(isNaN(iefv))
             efo = iefv;
         else
             efv = resultEfvs[iefv];

         var left;
         var top;
         if ( event.pageX == null && event.clientX != null ) {
             var e = document.documentElement, b = document.body;
             left = event.clientX + (e && e.scrollLeft || b.scrollLeft || 0);
             top = event.clientY + (e && e.scrollTop || b.scrollTop || 0);
         } else {
             left = event.pageX;
             top = event.pageY;
         }
         left += 15;
         top += 15;

         var waiter = $('<div class="waiter" />')
                 .css({ left: left + 'px', top: top + 'px' });

         $('body').append(waiter);
         adjustPosition(waiter);

         atlas.ajaxCall('experiments', {
             gene:gene,
             ef: efo ? 'efo' : efv.ef,
             efv: efo ? efo : efv.efv
         }, function(resp) {
             resp.counter = 0;
             var tpl = $('<div/>');
             var popup = $('<div id="expopup" />')
                     .append($("<div/>").addClass('closebox')
                     .click(
                     function(e) {
                         popup.remove();
                         e.stopPropagation();
                         return false;
                     }).text('close'))
                     .append(tpl)
                     .click(function(e){e.stopPropagation();})
                     .attr('title','')
                     .css({ left: left + 'px', top: top + 'px' });

             $('body').append(popup);
             tpl.render(resp, atlas.experimentsTemplate);

             // adjust for viewport
             adjustPosition(popup);

             var plots = popup.find('.oneplot');
             var c = 0;
             for (var iexp = 0, expLen = (resp.experiments || []).length; iexp < expLen; ++iexp) {
                 var exp = resp.experiments[iexp];
                 for (var ief = 0, efLen = (exp.efs || []).length; ief < efLen; ++ief) {
                     var ef = exp.efs[ief];

                     // From amongst the current ef's efvs find the one with the
                     // best pValue and pass it to the plot function - to ensure that it
                     // gets displayed in the plot's legend.
                     var minPVal = 1;
                     var bestEfv = null;
                     for (var iefv = 0, efvLen = (ef.efvs || []).length; iefv < efvLen; ++iefv) {
                         var efv = ef.efvs[iefv];
                         if (efv.pvalue < minPVal) {
                             minPVal = efv.pvalue;
                             bestEfv = efv.efv;
                         }
                     }

                     if (bestEfv == null) {
                         continue;
                     }

                     atlas.ajaxCall("plot", {
                         gid: gene,
                         eacc: exp.accession,
                         ef: ef.ef,
                         efv: bestEfv,
                         plot: 'bar'
                     }, (function(eid, eacc, gid, efvs, target) {
                         return function(o) {
                             drawPlot(o, plots.filter(target), efvs, eid, eacc, gid);
                         };
                     })(exp.id, exp.accession, gene, ef.efvs, '#oneplot_' + (c++)));
                 }
             }
         });
    };

    atlas.popup = function  (url) {
        var width = 700;
        var height = 200;
        var left = ($(window).width() - width) / 2;
        var top = ($(window).height() - height) / 2;
        var params = ['width=' + width,
            'height=' + height,
            'top=' + top,
            'left=' + left,
            'directories=no',
            'location=no',
            'menubar=no',
            'resizable=no',
            'scrollbars=no',
            'status=no',
            'toolbar=no'];
        newwin = window.open(url, 'windowname5', params.join(","));
        if (window.focus && newwin) {
            newwin.focus()
        }
        return false;
    };

    atlas.expandEfo = function (xoffset, yoffset, id, parentsOrChildrenOf) {
        var offset = $('#efoheader').offset();
        offset.top += yoffset;
        offset.left += xoffset;

        $('<div class="waiter"/>').append($('<img/>').attr('src','images/indicator.gif'))
                .css({ left: offset.left + 'px', top: offset.top + 'px' }).appendTo($('body'));

        var f = {};
        f[parentsOrChildrenOf] = id;

        atlas.ajaxCall('efo', f , function(resp) {
            var entered = false;
            var timeout;
            var popup = $('<div/>')
                    .addClass('tokeninputdrop')
                    .css({ width: 'auto', top: offset.top + 'px', left: offset.left + 'px' })
                    .appendTo(document.body)
                    .mouseleave(
                    function (e) {
                        timeout = setTimeout(function () {
                            popup.remove();
                        }, 300);
                    })
                    .mouseenter(
                    function () {
                        if (timeout) {
                            clearTimeout(timeout);
                            timeout = null;
                        }
                        entered = true;
                    });

            var ul = $('<ul/>')
                    .mouseover(
                    function (e) {
                        var t = $(e.target);
                        var li = t.is('li') ? t : t.parents('li:first');
                        if (li.length) {
                            var d = $.data(li.get(0), "efoup");
                            ul.find('li').removeClass('tokendropitemsel');
                            li.addClass('tokendropitemsel');
                        }
                    })
                    .click(
                    function (e) {
                        var t = $(e.target);
                        var li = t.is('li') ? t : t.parents('li:first');
                        if (li.length) {
                            var d = $.data(li.get(0), "efoup");
                            popup.remove();

                            if (atlas.resultConditions) {

                                var newConditions = [];
                                var resultConditions = atlas.resultConditions;
                                var shouldadd = true;
                                for (i = 0; i < resultConditions.length; ++i) {
                                    var cond = resultConditions[i];

                                    var fval = cond.jointFactorValues;
                                    if (fval.indexOf(d.id) == -1)
                                        for (var j = 0; j < cond.efoIds.length; ++j) {
                                            if (cond.efoIds[j] == id) {
                                                fval += ' ' + ((li.text() != "all children") ? d.id : d);  // for 'all children' d is a String of ids
                                                shouldadd = false;
                                                break;
                                            }
                                        }

                                    newConditions.push({
                                        expression: cond.expression,
                                        value: fval,
                                        factor: cond.factor
                                    });
                                }

                                if (shouldadd) {
                                    newConditions.push({
                                        expression: "UP_DOWN",
                                        value: (li.text() != "all children") ? escape(d.id) : escape(d),
                                        factor: ""
                                    });
                                }

                                var newQuery = atlas.latestSearchQuery;
                                newQuery.conditions = newConditions;
                                atlas.submitForm(newQuery);
                            }
                        }
                    });

            var k = 0;
            for (var i in resp.tree) {
                var indent = '';
                for (var j = 0; j < resp.tree[i].depth; ++j)
                    indent += '&nbsp;&nbsp;&nbsp;';

                // Add 'all children' item to the dropdown list hanging off efo id's '+' button in heatmap header
                var allChildrenLi;
                if (i == 0 && parentsOrChildrenOf == 'childrenOf') {
                    allChildrenLi = $('<li />')
                        .html(indent).append($('<span/>').text("all children")).addClass(++k % 2 ? 'tokendropitem' : 'tokendropitem2').appendTo(ul);
                    $.data(allChildrenLi.get(0), "efoup", '@' + id); // '@' preamble indicates that efo id's children should be included
                }
                if (resp.tree[i].id !== id) { // Exclude the efo term being expanded - to stop the user from selecting an already selected efo term
                    var li = $('<li />')
                            .html(indent).append($('<span/>').text(resp.tree[i].term)).append(' <em>(' + resp.tree[i].count + ') ' + resp.tree[i].id + '</em>')
                            .addClass(++k % 2 ? 'tokendropitem' : 'tokendropitem2')
                            .appendTo(ul);
                    $.data(li.get(0), "efoup", resp.tree[i]);
                }
            }

            ul.find('li:first').addClass('tokendropitemsel');

            popup.append(ul);

        });
    };

    atlas.showListThumbs = function (row) {
        var efv = $("#" + row.id + " .lvrowefv").text();

        var m = /([^_]*)_(.*)_([^_]*)/.exec(row.id);

        if (m) {
            var gid = m[1];
            var ef = m[2];
            var i = m[3];

            $(".thumb" + i).not(".done").each(function() {
                var el = $(this),
                    eacc = el.attr("eacc"),
                    deacc = el.attr("deacc");
                atlas.ajaxCall("/deThumbnail", {eacc: eacc, ef: ef, efv: efv, deacc: deacc}, function(jsonObj) {
                    if (jsonObj.plot) {
                        $.plot(el, jsonObj.plot.series, jsonObj.plot.options);
                    }
                });

                $(this).addClass("done");
            });
        } else {
            if (console) {
                console.log("Wrong id format: " + row.id);
            }
        }
    };

    $(document).ready(function () {
        atlas.experimentsTemplate = $('#experimentsTemplate').compile({
            '.@id+': function () {
                return Math.random(10000);
            },
            'div.head a@href': 'gene/#{gene.identifier}',
            '.gname': 'gene.name',
            '.numup': 'numUp',
            '.numdn': 'numDn',
            '.numno': 'numNo',
            '.ef': 'eftext',
            '.efv': 'efv',
            '.experRows': {
                'experiment <- experiments': {
                    '.expaccession': 'experiment.accession',
                    '.expname': 'experiment.name',
                    'table.oneplot': {
                        'ef <- experiment.efs': {
                            '.efname': 'ef.eftext',
                            '.@id': function(a) {
                                return 'oneplot_' + a.context.counter++;
                            },
                            'a.proflink@href': 'experiment/#{experiment.accession}/#{gene.identifier}/#{ef.ef}',
                            '.arraydesign@id': '#{experiment.id}_#{gene.id}_arraydesign'
                        }
                    },
                    '.@class+': function(a) {
                        return (a.pos != a.items.length - 1) ? ' notlast' : '';
                    },
                    'a.proflink2@href': 'experiment/#{experiment.accession}/#{gene.identifier}#{experiment.the_only_ef}',
                    'a.detailink@href': 'http://www.ebi.ac.uk/arrayexpress/browse.html?keywords=#{experiment.accession}&detailedview=on'
                }
            }
        });

        $('#experimentsTemplate').remove();
    });
 })(jQuery);

