$(function () {

    ///*** Initials ***/// 

    var LOADER = '<div id="loading" class="center"><img src="/site_media/graphic/loading.gif" /></div>';

    $('.toHide').hide();



    /// *** Functions *** ///

    $.fn.random = function() {
        return this.eq(Math.floor(Math.random() * this.length));
    } 

    $('#entitySelector').change(function () {
        $('#conditionSelector').change();
        $('#allResultCounterOutput').empty();
        $('.parentEntityPanel').slideUp();
        $('.parentEntitySelector').val($('.parentEntitySelector option:first').val());
        $('.parentEntitySelector').next('div').hide();
        if ($(this).val() != "choose") {
            $('#conditionSelector').show();
            $('#submitQuery').removeAttr('disabled');
            $('#' + $(this).val() + 'ParentPanel').slideDown();
        } else {
            $('.toHide').hide();
            $('#submitQuery').attr('disabled', 'disabled');
        };
    });
    
    $('#conditionSelector').change(function () {
        if ($(this).val() != "all") {
            $('.entityCriteria').hide();
            $('#' + $('#entitySelector').val() + 'Criteria').show();
            $('#allResultCounterBox').hide();
        } else {
            $('.entityCriteria').hide();
            $('#allResultCounterBox').show();
        };
    });
    
    $('.parentEntitySelector').change(function () {
        $(this).parent().nextAll('.parentEntityPanel').slideUp();
        target = $(this).next('div');
        if ($(this).val() != "choose") {
            $('#' + $(this).val() + 'ParentPanel').slideDown();
            target.children('.entityCriteria').hide();
            target.children('#' + $(this).val() + 'Criteria').show();
            target.show();
        } else {
            target.hide();
        }
    });
    
    $(document).on('change', '.operatorSelector', function() {
        entry1 = $(this).parent().children('.value1');
        entry2 = $(this).parent().children('.value2');
        operator = $(this).val();
        if (operator == "any") {
            entry1.hide(); entry2.hide();
        } else if (operator == "><") {
            entry1.show(); entry2.show();
        } else {
            entry1.show(); entry2.hide();
        };
    });
    
    $(document).on('click', '.addCriterium', function() {
        var criteria = $(this).parent();
        var newCriterium = criteria.children(':first').clone();
        
        /*
        usedCriteria = []
        criteria.children('.entityCriterium').each(function() {
            param = $(this).children('.paramSelector').val();
            if (param != 'choose') {
                usedCriteria.push(param);
            };
        });
        
        // remove used criteria
        newCriterium.children('.paramSelector').children('option').each(function() {
            if ($.inArray($(this).val(), usedCriteria) != -1) {
                $(this).remove();
            };
        });
        */
        
        newCriterium.children('.paramSettings').empty();
        newCriterium.prepend('<div class="andOperator">AND</div>').hide();
        newCriterium.append('<span class="removeCriterium"><img src="/site_media/graphic/icon_minus.png" class="tool_right" title="remove selected criterium" /></span>').appendTo(criteria).insertBefore(this).slideDown();
        setupTipsy();
    });
    
    $(document).on('click', '.removeCriterium', function() {
        $(this).parent().slideUp(function() {
            $(this).remove();
        });
    });
        
    $(document).on('mouseenter', '.removeCriterium', function() {
        $(this).closest('.entityCriterium').css({"outline": "1px dashed #b20000"});
    });
    
    $(document).on('mouseleave', '.removeCriterium', function() {
        $(this).closest('.entityCriterium').css({"outline": ""});
    });
    
    $(document).on('change', '.paramSelector', function() {
        var target = $(this).parent().children('.paramSettings');
        if ($(this).val() != "choose") {
            $.ajax({
                type: "GET",
                url: "/ajax/paramSettings",
                data: {'param': $(this).val(), 'entity': $('#entitySelector').val()},
                success: function(settings) {
                    target.empty().append(settings);
                    setupTipsy();
                }
            });
        } else {
            target.empty();
        };
    });
    
    /* to solve // znaceni cesty vyhodnocene podminky //
    $(document).on('click', '.subQuery', function() {
        console.log($(this).parents('.entityCriterium').children('.paramSelector'));
    });
    
    $(document).on('mouseenter', '.subQuery', function() {
        $(this).parents('.entityCriterium').children('.paramSelector').css({"border-bottom": "3px solid #b20000"});
    });
    
    $(document).on('mouseleave', '.subQuery', function() {
        $(this).parents('.entityCriterium').children('.paramSelector').css({"border-bottom": ""});
    });
    */
    
    $.fn.exists = function () {
        return this.length !== 0;
    };
    
    function getChildCriteria(obj) {
        return obj.find('.entityCriteria').not(':hidden').first().children('.entityCriterium');
    };
    
    function getParentCriterium(obj) {
        return obj.parents('.entityCriterium').first();
    };
    
    function getParamSelector(obj) {
        return obj.children('.paramSelector');
    };
    
    function getCriteriaDict(criteria) {
        var dict = {};
        criteria.each(function() {
            // set parameters
            var param = getParamSelector($(this));
            if (!dict[param.attr('name')]) {
                dict[param.attr('name')] = [param.val()];
            } else {
                dict[param.attr('name')].push(param.val());
            }
            
            // set previous or next entities
            if (param.val().match(/\bneig/) || param.val().match(/\bprev/) || param.val().match(/\bnext/) || param.val().match(/\bopposite/) || param.val().match(/\bchild/)) {
                dict[param.val()] = getCriteriaDict(getChildCriteria($(this)));
                dict['keyEntity'] = [$(this).children('input').val()];
            } else {
                // set operators, input values
                $(this).find('.operatorSelector, input').each(function() {
                    if (!dict[$(this).attr('name')]) {
                        dict[$(this).attr('name')] = [$(this).val()];
                    } else {
                        dict[$(this).attr('name')].push($(this).val());
                    }
                });
            }
        });
        return dict;
    };

    function getParentCriteriaDict(criterium, olddict) {
        var dict = {};
        var parent = getParentCriterium(criterium);
        var param = getParamSelector(criterium);
        
        dict[param.attr('name')] = [param.val()];

        if (!$.isEmptyObject(olddict)) {
            dict[param.val()] = olddict;
            key = criterium.children('input');
            dict[key.attr('name')] = [key.val()];
        } else {
            // set operators, input values
            criterium.find('.operatorSelector, input').each(function() {
                if (!dict[$(this).attr('name')]) {
                    dict[$(this).attr('name')] = [$(this).val()];
                } else {
                    dict[$(this).attr('name')].push($(this).val());
                }
            });
        }

        if (parent.exists()) {
            var parentparam = getParamSelector(parent);
            parentdict = getParentCriteriaDict(parent, dict);
            return parentdict;
        } else {
            return dict;
        }
    };
    
    function buildJSON(form) {
        // set basic form values
        searchQuery.children('select').each(function() {
            form[$(this).attr('name')] = [$(this).val()];
        });
        if ($('#conditionSelector').val() == 'all') {
            form['keyEntity'] = [$('#entitySelector').val()];
        }
        console.log(JSON.stringify(form));
        return form;
    };
    
    getSubQueryCount = function(form) {
        $.ajax({
            type: "POST",
            url: "subQuery",
            async: false,
            data: {'formData': JSON.stringify(buildJSON(form))},
            success: function(result) {
                count = result;
            }
        });
        return count;
    };

    setPropagation = function() {
        $('.nopropagation').click(function(e) {
            e.stopPropagation();
        });
    };

    $(document).on('click', '.subQuery', function() {
        target = $(this).parent().children('.subQueryResult');
        var criterium = getParentCriterium($(this));
        
        param = getParamSelector(criterium).val();
        
        if (param.match(/\bneig/) || param.match(/\bprev/) || param.match(/\bnext/) || param.match(/\bopposite/) || param.match(/\bchild/)) {
            // take the whole tree
            form = getParentCriteriaDict(criterium, getCriteriaDict(getChildCriteria(criterium)));
        } else {
            // lookup only one criterium in tree
            form = getParentCriteriaDict(criterium, {});
        }

        target.empty().append(getSubQueryCount(form));
    });
    
    showResultCounterOutput = function(target) {
        $('#' + target).empty().append('<img src="/site_media/graphic/loading_s.gif" />');
        result = getSubQueryCount({});
        $('#' + target).empty().append(result);
    };



    ///*** Fulltext ***///

    var searchFulltext = $('form[name="searchFulltext"]');
    searchFulltext.submit(function(e) {
        e.preventDefault();
        //args = {'entity': $('#fulltextTopic option:selected').attr('entity'), 'fulltext': true, 'express': $('#fulltextExpress').val(), 'topic': $('#fulltextTopic').val()};
        args = {'entity': 'struct', 'fulltext': true, 'express': $('#fulltextExpress').val(), 'topic': 'any'};
        searchEntities(args, $('#mainWrapper'));
    });



    ///*** Browse ***///
    
    $('.searchBrowse').click(function() {
        $(this).parents('form').submit(function(e) {
            e.preventDefault();
            data = $(this).serializeArray();
            form = {};
            for (var i in data) {
                if (!form[data[i]['name']]) {
                    form[data[i]['name']] = [data[i]['value']];
                } else {
                    form[data[i]['name']].push(data[i]['value']);
                }
            };
            //console.log(JSON.stringify(form));
            searchEntities({'entity': data[0]['value'], 'formData': form, 'parentData': [], 'fulltext': false}, $('#mainWrapper'));
        });
    });



    ///*** Search ***///
    
    var searchQuery = $('form[name="searchQuery"]');
    searchQuery.submit(function(e) {
        e.preventDefault();
        form = getCriteriaDict(getChildCriteria($(this)));

        ///// !!! tohle chce jeste cele zrevidovat - nefunguje, pokud zustane nejaky .paramSelector na hodnote 'choose'
        parents = [];
        $('.parentEntityPanel').not(':hidden').each(function() {
            parentEntity = $(this).children('select').val();
            if (parentEntity != 'choose') {
                parentsFORM = getCriteriaDict(getChildCriteria($(this).children('.parentCriteria')));
                dict = buildJSON(parentsFORM);
                dict["entity"] = [parentEntity];
                parents.push(dict);
            };
        });

        args = {'entity': $('#entitySelector').val(), 'formData': buildJSON(form), 'parentData': parents, 'fulltext': false};
        searchEntities(args, $('#searchResultBox'));
    });

    searchEntities = function(args, target) {
        ///*** args = entity, ids, query, formData, parentData, express, topic, pagination, perpage, page, service, childservice ***///

        args['pagination'] = true; args['perpage'] = 100;
        args['service'] = true; args['childservice'] = true;

        target.empty().append(LOADER).show();
        $('#loading').prepend('<h2>searching...</h2>');

        $.ajax({
            type: "POST",
            url: "/ajax/searchEntities",
            data: {'args': JSON.stringify(args)},
            success: function(result) {
                target.empty().append(result).show(function() {
                    if (ids.length != 0) {
                        if (args['pagination']) {
                            if (typeof pages !== 'undefined') {
                                args['ids'] = pages[0];
                                args['page'] = 0;
                                getEntities(args, $('#searchResultItemsWrapper'));
                            }
                        } else {
                            args['ids'] = ids;
                            getEntities(args, $('#searchResultItemsWrapper'));
                        }
                    }
                    setupTipsy();
                });
            },
            error: function(xhr, text_status, error_thrown) {
                console.log("Error: " + text_status + error_thrown);
            },
        });
    };

    getEntities = function(args, target) {
        ///*** args = entity, ids, regroup, pagination, perpage, page, service, childservice ***///

        args['regroup'] = false;
        args['service'] = true; args['childservice'] = true;
        
        target.empty().append(LOADER).show();
        $('#loading').prepend('<h2>rendering results...</h2>');

        $.ajax({
            type: "POST",
            url: "/ajax/getEntities",
            async: false,
            data: {'args': JSON.stringify(args)},
            success: function(result) {
                target.empty().append(result).show();
                setPropagation();
                adjustParamTableHeader();
                setupTipsy();
                alignJmol();
            }
        });
    };

    getEntityDetails = function(args, target) {
        ///*** args = pdb, entity, ids, service, childservice ***///

        args['service'] = true; args['childservice'] = false;
        
        if (args['entity'] != 'struct' || args['pdb'] != getStructInView()) {
            target.empty().append(LOADER).show();
            $.ajax({
                type: "POST",
                url: "/ajax/loadEntity",
                async: false,
                data: {'args': JSON.stringify(args)},
                success: function(result) {
                    target.empty().append(result).show();
                    setPropagation();
                    adjustParamTableHeader();
                    setupTipsy();
                }
            });
        }
    };



    ///*** ***///

    adjustParamTableHeader = function() {
        $('.paramTableHeader').each(function() {
            $(this).children('th').each(function(index) {
                column = $(this).closest('.paramTable').next('.tinyTable').find('td:eq(' + index + ')');
                if ($(this).width() >= column.width()) {
                    column.css({'min-width': $(this).width()});
                } else {
                    $(this).css({'min-width': column.width()});
                };
            });
        });
    };

    showEntityDetails = function(pdb, entity, ids, src) {
        target = $(src).closest('.childEntityBox').siblings('.childEntityDetails');
        getEntityDetails({'pdb': pdb, 'entity': entity, 'ids': ids}, target);
    };

    showResultDetails = function(pdb, entity, ids, src) {
        target = $(src).closest('.searchResultItem').children('.resultBox');
        getEntityDetails({'pdb': pdb, 'entity': entity, 'ids': ids}, target);
    };

    showStructDetails = function(src, pdb) {
        target = $(src).closest('.searchResultItem').children('.structDetails');
        getEntityDetails({'pdb': pdb, 'entity': 'struct', 'ids': ''}, target);
    };
    
    hideStructDetails = function(src) {
        $(src).closest('.structBox').siblings('.structDetails').hide();
    };
    
    removeChildEntityDetails = function(src) {
        $(src).closest('.childEntityBox').siblings('.childEntityDetails').hide();
    };
    
    $(document).on('click', '.toggleCitation', function() {
        $(this).closest('table').next('div').slideToggle();
    });
    
    $(document).on('click', '.shower', function() {
        $(this).hide();
        $(this).parent().children('.hider').show();
    });

    $(document).on('click', '.hider', function() {
        $(this).hide();
        $(this).parent().children('.shower').show();
    });
    
    $(document).on('click', '.remover', function() {
        $(this).hide();
        $(this).parent().children('.orphan').show();
    });
    
    showStatistics = function(args) {
        if ($('#statResults').is(':empty')) {
            $('#statResults').hide();
            $('#statWrapper').slideDown(function() {
                appendStatistics(args);
                $('#statResults').accordion().show(function(){
                    $(this).find('a').first().click();
                });
            });
        } else {
            $('#statWrapper').slideToggle();
        }
    };

    /*
    getStat = function(args) {
        $.ajax({
            type: "POST",
            url: "/ajax/entityStat",
            async: false,
            data: {'args': JSON.stringify(args)},
            success: function(result) {
                stat = result;
            }
        });
        return stat;
    };
    */

    appendStatistics = function(args) {
        $('#statLoader').show();
        $.ajax({
            type: "POST",
            url: "/ajax/entityStat",
            data: {'args': JSON.stringify(args)},
            success: function(result) {
                $('#statLoader').hide();
                if (args['order'] == 'next') {
                    index = $('#statResults h3').length;
                    $('#statResults').append(result).accordion('destroy').accordion({active:index});
                    $('#statResults h3').last().next('div').hide().slideDown();
                } else {
                    $('#statResults').prepend(result).accordion('destroy').accordion();
                    $('#statResults h3').first().next('div').hide().slideDown();
                };
                setupTipsy();
            }
        });
    };
    
    getParamChart = function(args, target) {
        $('#' + target).slideDown(function() {
            $(this).empty().append(LOADER);
            $.ajax({
                type: "POST",
                url: "/ajax/entityParamStatChart",
                async: false,
                data: {'args': JSON.stringify(args)},
                success: function(result) {
                    $('#' + target).empty().append(result);
                    setupTipsy();
                }
            });
        });
    };
    
    queryAdd = function(query, records, entity, src) {
        $.ajax({
            type: "POST",
            url: "/user/queryAdd",
            data: {'query': query, 'records': records, 'entity': entity},
            success: function(result) {
                //$(src).hide().empty().append('<span class="red">query saved</span>').show();
                if ($('#queryListBox').length != 0) {
                    $(result).hide().prependTo('#queryListBox');
                    $('html').animate({scrollTop: $('#queryListBox').prev('h2').offset().top}, 400, function() {
                        $('#queryListBox').children('div').first().css('opacity', 0).slideDown(function() {
                            $(this).fadeTo(200, 1);
                        });
                    });
                };
                setupTipsy();
            }
        });
    };
    
    queryRemove = function(src, id) {
        $.ajax({
            type: "POST",
            url: "/user/queryRemove",
            data: {'queryId': id},
            success: function(result) {
                $(src).parents('.queryItem').fadeTo(400, 0, function() {
                    $(this).slideUp(400, function() {
                        $.when($(this).remove()).then(function() {
                            if ($('.queryItem').length == 0) {
                                $('#queryListBox').append('<span class="notice">is empty</span>');
                                $('.notice').hide().fadeIn();
                            };
                        });
                    });
                });
                setupTipsy();
            }
        });
    };
    
    removeAllQueries = function() {
        $('.queryItemRemover').click();
    };
    
    removeSelectedQueries = function() {
        $('input:checked').parent().find($('.queryItemRemover')).click();
    };
    
    queryEdit = function(src) {
        $('.queryDescriptionEditor').css('visibility', 'hidden');
        $('.queryDescription').show();
        
        item = $(src).parents('.queryItem');
        item.children('.queryDescription').hide();
        item.children('.queryDescriptionEditor').css('visibility', 'visible');
        item.find('input[name="description"]').focus();
    };
    
    queryExecute = function(queryId, entity) {
        target = $('#queryExecuteResult');
        target.hide().empty().append(LOADER).show();
        $('#loading').prepend('<h2>rendering results...</h2>');
        $.post('queryExecute', {'queryId': queryId, 'entity': entity}, function(result) {
            target.hide().empty().append(result).show();
            setupTipsy();
        });
    };
    


    ///*** Export / using AJAX ***///

    generatePDB = function(PDBs) {
        $('#overlay_dialog').css({'top': $('html').scrollTop() + 50});
        $('#overlay').css({'height': 2 * $(document).height()});
        $('#overlay').fadeIn();
        $.ajax({
            type: "POST",
            url: "/export/PDB",
            async: false,
            data: {'PDBs': JSON.stringify(PDBs), 'call': 'ajax'},
            success: function(result) {
                $('#overlay').fadeOut(function() {
                    window.open(result.url);
                });
            }
        });
    };

    generateCSV = function(pdb, entity, ids) {
        $('#overlay_dialog').css({'top': $('html').scrollTop() + 50});
        $('#overlay').css({'height': 2 * $(document).height()});
        $('#overlay').fadeIn();
        $.ajax({
            type: "POST",
            url: "/export/CSV",
            async: false,
            data: {'pdb': pdb, 'entity': entity, 'ids': JSON.stringify(ids), 'call': 'ajax'},
            success: function(result) {
                $('#overlay').fadeOut(function() {
                    window.open(result.url);
                });
            }
        });
    };

    ///*** Export / using FORM confirmation ***///
    
    exportPDB = function(PDBs) {
        form = $('[name="TXTform"]');
        form.children('[name="PDBs"]').val(JSON.stringify(PDBs));
        form.children('[name="call"]').val('http');
        form.submit();
    };
    
    exportCSV = function(pdb, entity, ids) {
        form = $('[name="CSVform"]');
        form.children('[name="pdb"]').val(pdb);
        form.children('[name="entity"]').val(entity);
        form.children('[name="ids"]').val(JSON.stringify(ids));
        form.children('[name="call"]').val('http');
        form.submit(); // alt.: document.forms["CSVform"].submit();
    };
    


    ///*** Side Menu ***///
    
    gotoFirst = function() {
        $('html').animate({scrollTop: $('.searchResultItem').first().offset().top});
    };

    gotoPrev = function() {
        $('.searchResultItem').each(function() {
            diff = $(this).position().top - $(window).scrollTop();
            if (diff > 0) {
                $('html').animate({scrollTop: $(this).prev().offset().top});
                return false;
            };
        });
    };

    gotoNext = function() {
        $('.searchResultItem').each(function() {
            diff = $(this).position().top - $(window).scrollTop();
            if (diff > 0) {
                if (diff < 1) {
                    $('html').animate({scrollTop: $(this).next().offset().top});
                } else {
                    $('html').animate({scrollTop: $(this).offset().top});
                };
                return false;
            };
        });
    };

    gotoLast = function() {
        $('html').animate({scrollTop: $('.searchResultItem').last().offset().top});
    };



    ///*** Feedback ***///

    sendFeedback = function(src) {
        target = $(src).closest('.content');
        $.ajax({
            type: "POST",
            url: "/feedback",
            data: {'email': target.find('input[name="email"]').val(),
                   'message': target.find('textarea[name="message"]').val()
                  },
            success: function(result) {
                target.slideUp(function() {
                    $(this).empty().append(result).slideDown();
                });
            }
        });
    };



    ///*** Analysis ***///

    getAnalysis = function(choice, target) {
        target.hide().empty().append(LOADER).show();
        $('#loading').prepend('<h2>processing data...</h2>');
        $.ajax({
            type: "POST",
            url: "/ajax/analyseDataset",
            async: false,
            data: {'set_choice': choice,
                  },
            success: function(result) {
                target.empty().append(result);
                setupTipsy();
            }
        });
    };

    $('.set_choice').change(function() {
        if ($(this).val() == 'user') {
            $('#uploadDataset').css('display', 'inline');
        } else {
            $('#uploadDataset').css('display', 'none');
            getAnalysis($(this).val(), $('#analysisResults'));
        }
    });
    
    var analyseDataset = { 
        url: '/ajax/analyseDataset',
        target: '#analysisResults',
        data: {'set_choice': 'user'},
        complete: function(response) {
        }
    };
    
    $('form#uploadDataset').submit(function() {
        $('#analysisResults').empty().append(LOADER).show();
        $('#loading').prepend('<h2>processing data...</h2>');
        $(this).ajaxSubmit(analyseDataset);
        return false;
    });

    exportAnalysis = function() {
        $('#overlay_dialog').css({'top': $('html').scrollTop() + 50});
        $('#overlay').css({'height': 2 * $(document).height()});
        $('#overlay').fadeIn();
        $.ajax({
            type: "POST",
            url: "/ajax/analyseExport",
            async: false,
            data: {'set_choice': $('.set_choice').val(),
                   'set_source': $('.set_source').val(),
                   'call': 'ajax',
                  },
            success: function(result) {
                $('#overlay').fadeOut(function() {
                    window.open(result.url);
                });
            }
        });
    };



    ///*** Classify PDB ***///

    var classifyPDB = { 
        url: '/ajax/entityClassify',
        target: '#classifyResults',
        complete: function(response) {
            setPropagation();
            adjustParamTableHeader();
            setupTipsy();
        }
    };
    
    $('form#uploadPDB, form#submitPDB').submit(function() {
        $('#classifyResults').empty().append(LOADER).show();
        $('#loading').prepend('<h2>processing data...</h2>');
        $(this).ajaxSubmit(classifyPDB);
        return false;
    });

    loadAverageTorsionTable = function(cluster, target) {
        $('#average').show();
        $.post('/ajax/averageTorsionTable', {'cluster': cluster}, function(result) {
            target.empty().append(result);
            adjustParamTableHeader();
            setupTipsy();
        });
    };



    ///*** under construction / tests ***///
    
    $('#removeConditions').click(function () {
        $('.removeCriterium').click();
        $('#conditionSelector').val("all").change();
    });
    
});
