/*
** $Id: client.js,v 1.54 2008-04-10 09:48:25 jakub Exp $
** Pazpar2's javascript client .
*/

setupGetParameters();

// check for pz2.js
if(typeof window.pz2 == "undefined"){
    throw new Error("Client requires pz2.js library.");
}

// check for jQuery
if(typeof window.jQuery == "undefined"){
    throw new Error("Client requires requires jQuery library");
}

var xslPostfix;
confLangCode == 'en' 
    ? xslPostfix = ''
    : xslPostfix = '-' + confLangCode;
 
//get the language file
var langRequest = 
    new pzHttpRequest("locale/front-"+confLangCode+".xml");

langRequest.get(
    {},
    parseLangConf
);

/* start with creating pz2 object and passing it event handlers*/
var my_paz = new pz2( { "onshow": my_onshow,
                    //"showtime": 1000,
                    //"onstat": my_onstat,
                    "onterm": my_onterm,
                    "termlist": confTermlists.join(','),
                    //"onbytarget": my_onbytarget,
                    "autoInit": false,
                    "errorhandler": my_errorhandler,
                    "detailstylesheet": 
                        "xsl/" + confDetailsXsl + xslPostfix + '.xsl',
                    "onreset": my_onreset,
                    "onrecord": my_onrecord,
                    "usesessions": false,
		    "pazpar2path": pazpar2_proxy ? pazpar2_proxy : '.' } );

var myEvents = new mkEvents();

//var curQuery = new pzQuery();
var curState = new mkState();
curState.sort = confSort;
curState.perPage = Number(confShowPerPage);
curState.page = 0;


var resFilters = new mkFilter();

/* detailed view of the selected record */
var currentDetailedId = null;
var currentDetailedData = null;
var cachedDetails = null;
var justRedrawnId = null;

/* advanced search is set to false on the page load */
var advancedOn = false;

/* TODO do it smart */
var viewTaken = false;
var gotResults = false;
var termlistRefreshCounter = 0;

/* config to be parsed when the dom is ready */
var lang;

/* upper right corner logo uri */
var logo;
var loaderGfx = '';//'gfx/ajax_loader.gif';

/* wait until the DOM is ready and register basic handlers */
$(document).ready( 
    function() {
        logo = document.getElementById('logo').src;

        // when page is refreshed, erase the state
        // prevents bookmarking
        window.location.hash = '#'; 
        $.historyInit(historyHandler);

        document.search.onsubmit = onFormSubmitEventHandler;
        document.search.query.disabled = '';
        document.search.query.focus();

        document.search.title.value = '';
        document.search.author.value = '';
        document.search.subject.value = '';
        document.search.date.value = ''; 
 
        // is 'query' in the params
        if (window.location.parameters["query"] != null) {
            document.search.query.value = window.location.parameters["query"];
            onFormSubmitEventHandler();
        } else {
            document.search.query.value = '';
        }
                  
        /*
        $('.search').corner('bottom');
        $('.leftbar').corner();
        $('.content').corner();
        */
        
        /* if authentication is disabled init the pz2 session */
        if(typeof window.Auth == "undefined"){
            my_paz.init();
        }

        $('#aboutLink').click(
            function() {
                viewTaken = true;
                $('div.content').hide();
                $("div.leftbar").hide();
                $('#helpDiv').hide();
                $('#aboutDiv').show();
                return false;
            }
        );

        $('#helpLink').click(
            function() {
                viewTaken = true;
                $('div.content').hide();
                $("div.leftbar").hide();
                $('#aboutDiv').hide();
                $('#helpDiv').show();
                return false;
            }
        );
               
        $('#advanced').click(toggleAdvanced);

        $('#sort').change(
            function(){ 
                curState.sort = this.value;
                curState.page = 0;
                my_paz.show(0, curState.perPage, curState.sort);
            }
        );
        
        $('#perpage').change(
            function(){ 
                curState.perPage = Number(this.value);
                curState.page = 0;
                my_paz.show(0, curState.perPage, curState.sort);
            }
        );
        
        $('.termTitle').click (
            function() {
                if( this.firstChild.className == "selected" ) {
                    this.firstChild.className = "unselected";
                    $(this).siblings('.termEntries').hide();
                } else {
                    this.firstChild.className = "selected";
                    $(this).siblings('.termEntries').show();
                }
                return false;
            }
        );
    }
);

/*
********************************************************************************
** pz2 Event Handlers **********************************************************
********************************************************************************
*/

/* pazpar2 (backend) errors */
function my_errorhandler(err)
{
    switch (err.code) {
        case '101' : 
            logOut();
            $('#loginDiv').show(); 
            $('#username')[0].focus(); 
            break;
        default: alert(err.message);
    }
}

function my_onreset()
{
    $('div.showing').empty();
    $('div.pages').empty();
    $('div.records').empty();

    $('div.content').hide();
    $("div.leftbar").hide();
}

/*
** data.hits["md-title"], data.hits["md-author"], data.hits.recid, 
** data.hits.count
** data.activeclients, data.merged, data.total, data.start, data.num 
*/
function my_onshow(data)
{
    if ( data.hits.length )
        gotResults = true;

    if( data.activeclients === 0)
        changeMKLogo(logo);

    /* TODO this is only temporary */
    if ( !viewTaken ) {
        if (data.total) $('div.leftbar').show();
        $('div.content').show();
    }

    var recsBody = $('div.records');
    recsBody.empty();
    
    for (var i = 0; i < data.hits.length; i++) {
        var title = data.hits[i]["md-title"] || 'N/A';
        var author = data.hits[i]["md-author"] || '';
        var id = data.hits[i].recid;
        var count = data.hits[i].count || 1;
        
        var recBody = $('<div class="record" id="' 
            + id +'"></div>');
        var aTitle = $('<a href="show_details" class="recTitle">'
            + title + ' </a>')
                .appendTo(recBody);
        
        aTitle.click(
                function(){
                    var clickedId = this.parentNode.id;
                    
                    if (currentDetailedId != null)
                        $( document.getElementById(currentDetailedId) )
                            .children('.detail').remove();
                    
                    if(currentDetailedId == clickedId) {
                        currentDetailedId = null;
                        justRedrawnId = null;
                        return false;
                    }
                    
                    currentDetailedId = clickedId;
                    my_paz.record(currentDetailedId);
                    return false;
                }
            );
        
        if( author ) {
            recBody.append('<i> '+lang['briefby']+' </i>');
            $('<a href="limit_by_author" name="author" class="recAuthor">'
                + author + '</a>\n')
                .click(
                    function() { 
                        redirect(this.name, 
                            this.firstChild.nodeValue);
                        return false;
                    }
                ).appendTo(recBody);
        }

        if( currentDetailedId == id ) {
            recBody.append(cachedDetails);
            justRedrawnId = id;
        }

        if( count > 1 ) {
            recBody.append('<span> ('+count+')</span>');
        }

        recsBody
            .append('<div class="resultNum">' 
                + (curState.page*curState.perPage + i + 1)
                + '.</a>');
        recsBody.append(recBody);
    }
    drawPager(data.merged, data.total, data.activeclients);

    // show block so this should be called only when search is done
    // there's no results
    if ( data.total === 0 ) {
        $('.termEntries').empty();
        $('div.leftbar').hide();
    }
}

/*
** data.activeclients, data.hits, data.records, data.clients, data.searching
*/
function my_onstat(data){}

/*
** data[listname]: name, freq, [id]
*/
function my_onterm(data)
{
    // hack as long as the termlist command doesn't block
    termlistRefreshCounter++;

    for (var key in data){
        if (key == "activeclients")
            continue;
        var listEntries = $('#term_'+key).children('.termEntries');
        if ( data[key].length || (termlistRefreshCounter > 1) ) 
            listEntries.empty();

        for (var i = 0; i < data[key].length; i++){
            if (key == "xtargets"){
                var listItem = 
                    $('<a href="limit_by_resource" class="sub"'
                        + 'name="xtarget" value="'
                        + data[key][i].id + '">' 
                        + data[key][i].name
                        + '<span> (' + data[key][i].freq 
                        + ')</span>' + '</a>')
                            .click(
                                function() {
                                    refine(this.name, 
                                        this.getAttribute('value'), 
                                        this.firstChild.nodeValue);
                                return false;
                                }
                            );
                listItem.appendTo(listEntries);
            } else {
                var listItem = 
                    $('<a href="limit_by_field" class="sub" name="'
                    + key + '">' + data[key][i].name
                    + '<span class="facetFreq"> (' + data[key][i].freq 
                    + ')</span>'+'</a>')
                        .click(
                            function() {
                                refine(this.name, 
                                    this.firstChild.nodeValue);
                            return false;
                            }
                        );
                listItem.appendTo(listEntries);
            }
        }         
    }
}

/*
** data["md-title"], data["md-date"], data["md-author"], 
** data["md-subject"], data["location"][0].name
*/
function my_onrecord(data)
{
    if (justRedrawnId == data.recid)
        return;
    
    currentDetailedData = data;
    cachedDetails = $('<div class="detail"></div>');
    drawDetailedRecWithXsl(cachedDetails);
    var params = {
            'data':     data,
            'cell':     cachedDetails

    };
    myEvents.callEvents('detPostTransform', params);
    cachedDetails
        .appendTo($(document.getElementById(currentDetailedId)));
}

/*
** data[i].id, data[i].hits, data[i].diagnostic, data[i].records, data[i].state
*/
function my_onbytarget(data){}

/*
********************************************************************************
** HELPER FUNCTIONS ************************************************************
********************************************************************************
*/

function copyObjProperties (newObj, stateObj)
{
    for( var property in stateObj ) {
        if ( newObj.hasOwnProperty(property) )
            newObj[property] = stateObj[property];
    }
}

function historyHandler ( stateJSON )
{
    // state was serialized after '#' ?
    if( stateJSON ) {
        var newState = new mkState();
        copyObjProperties( newState, $.parseJSON( stateJSON ));

        // for bookmarking
        if ( newState.action == 'show' &&
             newState.toCCL() + newState.getSingleFilterString()
             != curState.toCCL() + curState.getSingleFilterString() )
            newState.action = 'search';

        copyObjProperties (curState, newState);
        drawBreadcrumb();

        switch ( curState.action ) {
            // TODO resource selction should overwrite filter
            case 'search' :
                my_paz.search(curState.toCCL(), 
                    curState.perPage,
                    curState.sort,
                    curState.getSingleFilterString() 
                    || resFilters.getFilterString(),
                    curState.page * curState.perPage );
                break;
            case 'show' :
                if (gotResults) {
                    my_paz.showPage( curState.page );
                }
                break;
        }
    }

}

//0 indexed
function showPage (pageNum)
{
    curState.page = pageNum;
    curState.action = 'show';
    $.historyLoad( $.toJSON(curState) );

    //my_paz.showPage(pageNum);
    //curState.page = pageNum;
}

function onFormSubmitEventHandler() 
{
    // load query and clear filter
    loadQueryFromForm();
    curState.clearSingleFilter();

    // switch view back and empty old terms
    backToSearch();
    $('div.leftbar').hide();
    $('.termEntries').empty();
    $('div.content').show();

    fireSearch();
    return false;
}

function fireSearch()
{
    // clear timeouts
    my_paz.stop();

    // reset state
    curState.page = 0;
    currentDetailedId = null;
    termlistRefreshCounter = 0;

    // cleanup display
    showIndicator($('div.showing').empty());
    $('div.pages').empty().html('&nbsp;');
    $('div.records').empty();
    drawBreadcrumb();

    // if empty search don't bother
    if( !curState.totalLength() ) {
        $('.termEntries').empty();
        $('div.content').hide();
        $("div.leftbar").hide();
        return false;
    }

    // change logo to loader
    changeMKLogo(loaderGfx);
   
    // set action and fire back-button handler
    curState.action = 'search';
    $.historyLoad( $.toJSON( curState ) );

    /*
    my_paz.search(curState.toCCL(), 
                    curState.perPage,
                    curState.sort,
                    curState.getSingleFilterString() );
    /*/
}

function changeMKLogo (logo)
{
    if (!logo) return;
    /* hourglass - experimental */
    document.getElementById("logo").src = logo;
}

function toggleAdvanced()
{
    if(advancedOn){
        advancedOn = false;

        $("input[@name=query]").attr("disabled", "");
        
        $("div.advanced").hide();
        $("div.search").height(73);

        $("#advancedLinkText").show();
        $("#simpleLinkText").hide();
    } else {
        advancedOn = true;
        
        $("input[@name=query]").attr("disabled", "disabled");

        $("div.search").height(183);
        $("div.advanced").show();

        $("#advancedLinkText").hide();
        $("#simpleLinkText").show();
        loadFormFieldsFromQuery();
    }
}

function drawDetailedRecWithXsl(detailBox)
{
    // set the custom resolver
    ourlNode = currentDetailedData.xmlDoc.getElementsByTagName('md-open-url');
    if ( ourlResolver && ourlNode.length ) {
        var ourl = ourlNode[0].firstChild.nodeValue;
        ourl = ourlResolver + '?'  + ourl.split('?')[1];
        ourlNode[0].firstChild.nodeValue = ourl;
    }

    Element_appendTransformResult ( detailBox[0], 
            currentDetailedData.xmlDoc,
            currentDetailedData.xslDoc );
    
}

function refine(field, value, opt)
{
    switch(field) {
        case "author":  curState.addTerm('au', '"' + value + '"'); break;
        case "title":   curState.addTerm('ti', '"' + value + '"'); break;
        case "date":    curState.addTerm('date', '"' + value + '"'); break;
        case "subject": curState.addTerm('su', '"' + value + '"'); break;
        case "xtarget": curState.setSingleFilter(opt, value); break;
    }
    
    updateAdvSearchForm();
    fireSearch();
}

function redirect(field, value, opt)
{
    curState.reset();
    refine(field, value, opt);
}

function updateAdvSearchForm()
{
    if(advancedOn)
     loadFormFieldsFromQuery();
}

function loadQueryFromForm()
{
    curState.reset();

    if( advancedOn )
    {
        if (validate(document.search.anywhere.value))
            curState.simpleQuery = document.search.anywhere.value;
        curState.addTermsFromList(document.search.author.value, 'au');
        curState.addTermsFromList(document.search.title.value, 'ti');
        curState.addTermsFromList(document.search.date.value, 'date');
        curState.addTermsFromList(document.search.subject.value, 'su');
    } else {
        curState.simpleQuery = document.search.query.value;
    }
}

function validate (input)
{
    return input.match(/\S/) ? true : false;
}

function loadFormFieldsFromQuery()
{
    document.search.anywhere.value = curState.simpleQuery;
    document.search.author.value = '';
    document.search.title.value = '';
    document.search.date.value = '';
    document.search.subject.value = '';

    for(var i = 0; i < curState.numTerms; i++)
    {
        switch( curState.getTermFieldByIdx(i) )
        {
            case "au": 
                document.search.author.value 
                    += curState.getTermValueByIdx(i) + '; '; 
                    break;
            case "ti": 
                document.search.title.value 
                    += curState.getTermValueByIdx(i) + '; '; 
                    break;
            case "date": 
                document.search.date.value 
                    += curState.getTermValueByIdx(i) + '; '; 
                    break;
            case "su": 
                document.search.subject.value 
                    += curState.getTermValueByIdx(i) + '; '; 
                    break;
        }
    }
}

function drawPager(max, hits, active)
{
    var firstOnPage = curState.page * curState.perPage + 1;
    var lastOnPage = (firstOnPage + curState.perPage - 1) < max 
                            ? (firstOnPage + curState.perPage - 1) 
                            : max;
    if(!lastOnPage) firstOnPage = 0;

    var results = $('div.showing');
    results.empty();
    
    var pager = $('div.pages');
    pager.empty();

    if ( active )
        showIndicator(results);
    else if ( hits )
        results.append(msg['completed']);

    if ( hits )
        results.append(' ' + lang["displaying"]+': <b>'
                        +firstOnPage+'</b> - <b>'+lastOnPage
                        +'</b> / <b>'+max
                        +'</b> ( '+lang["totalhits"]+': '+hits+' )');
    else
        results.append(msg["completed"] + ' ' + msg["norecords"]);
    
    if ( curState.page > 0 ){
        $('<a href="prev" class="previous_active">'
            + lang["previous"] + '</a>')
            .click(
                function() { 
                    showPage(curState.page - 1);
                    return false;
                })
            .appendTo(pager.eq(0));

        $('<a href="prev" class="previous_active">'
            + lang["previous"] + '</a>')
            .click(
                function() {
                    showPage(curState.page - 1)
                    return false;
                })
            .appendTo(pager.eq(1));
    }
    else
        pager.append('<a style="cursor: default;" class="previous_inactive">'
            +lang["previous"] + '</a>');

    var numPages = Math.ceil(max / curState.perPage);

    var start = ( curState.page - 5 > 0 ? curState.page - 5 : 1 );
    var stop =  ( start + 12 < numPages ? start + 12 : numPages );

    if (start > 1) $('<span>... </span>').appendTo(pager);
    
    for(var i = start; i <= stop; i++)
    {
        if( i == (curState.page + 1) ){
           $('<a class="select">'+i+'</a>')
            .appendTo(pager);
           continue;
        }
        var pageLink = $('<a href="page" class="page">'+ i +'</a>');
        var plClone = pageLink.clone();

        pageLink.click(
            function() { 
                showPage(this.firstChild.nodeValue - 1);
                return false;
            }
        );

        plClone.click(
            function() { 
                showPage(this.firstChild.nodeValue - 1);
                return false;
            }
        );

        //nasty hack to clone click events
        pager.eq(0).append(pageLink);
        pager.eq(1).append(plClone);
    }

    if (stop < numPages) $('<span> ...</span>').appendTo(pager);

    if ( curState.page < (numPages-1) ){
        $('<a href="next" class="next_active">' 
            + lang["next"] + '</a>')
            .click(
                function() { 
                    showPage(curState.page + 1); 
                    return false;
                }
            )
            .appendTo(pager.eq(0));

        $('<a href="next" class="next_active">'
            + lang["next"] + '</a>')
            .click(
                function() {
                    showPage(curState.page + 1);
                    return false;
                }
            )
            .appendTo(pager.eq(1));
    }
    else
        pager.append('<a style="cursor: default;" class="next_inactive">'
        + lang["next"] + '</a>');
}

function drawBreadcrumb()
{
    var bc = $("#breadcrumb");
    bc.empty();

    bc.append('<b>'+lang['yoursearch']+'</b>');
    
    if(curState.singleFilter) 
        $('<strong id="filter"><a href="remove_limit">'
                        + curState.getSingleFilterName() 
                        + '</a>: </strong>')
                            .click(
                                function() {
                                    curState.clearSingleFilter();
                                    updateAdvSearchForm();
                                    fireSearch();
                                    return false;
                                }
                            )
                            .appendTo(bc);

    $('<a href="remove_limit">&nbsp;' 
        + curState.simpleQuery + '&nbsp;</a>')
        .click(
            function() {
                curState.clearSimpleQuery();
                updateAdvSearchForm();
                fireSearch();
                return false;
            }
        )
        .appendTo(bc);

    for(var i = 0; i < curState.numTerms; i++){
        if ( i != 0 || curState.simpleQuery )
            bc.append('<strong> + </strong>');

        var bcLink = $('<a href="remove_limit" id="pos_' + i +'">'
            + curState.getTermValueByIdx(i) + '</a>')
            .click(
                function() { 
                    curState.removeTermByIdx(this.id.split('_')[1]);
                    updateAdvSearchForm();
                    fireSearch();
                    return false;
                }
            );
        bc.append(bcLink);
    }
}

function parseLangConf ( xmlConf )
{
    xmlConf.documentElement.normalize();
    var confEntries = xmlConf.documentElement.childNodes;

    /* parts of the interface and messages kept separetely
    ** for convenience
    */
    var langConf = new Array();
    var msgConf = new Array();

    for(var i = 0; i < confEntries.length; i++) 
    {
        if ( confEntries[i].nodeType == Node.ELEMENT_NODE ) 
        {
            if ( confEntries[i].nodeName.toLowerCase() == 'messages') 
            {
                for(var j = 0; j < confEntries[i].childNodes.length; j++) 
                {

                    if ( confEntries[i].childNodes[j].nodeType 
                        == Node.ELEMENT_NODE ) 
                    {
                        msgConf[confEntries[i].childNodes[j]
                            .nodeName.toLowerCase()] 
                        = Element_getTextContent(confEntries[i].childNodes[j]);
                    }
                }
                continue;
            }
                
            langConf[confEntries[i].nodeName.toLowerCase()] 
                    = Element_getTextContent(confEntries[i]);
        }
    }
    
    lang = langConf;
    msg = msgConf;
}

function backToSearch ()
{
    $('#helpDiv').hide();
    $('#aboutDiv').hide();
    viewTaken = false;
    
    if ( gotResults ) {
        $('div.content').show();
        $("div.leftbar").show();
    }
}

function showIndicator (jEl)
{
    jEl.append( msg["searching"] 
        + '<span style="text-decoration: blink">. . .</span>');

}

function setupGetParameters() {
    var parameters = new Object();
    if(window.location.search) {
        var paramArray = window.location.search.substr(1).split('&');
        var length = paramArray.length;
        for (var index = 0;index <length; index++ ) {
            var param = paramArray[index].split('=');
            var name = param[0];
            var value =
                typeof param[1] == "string"
                ? decodeURIComponent(param[1].replace(/\+/g," "))
                : null;
            parameters[name] = value;
        }
    }
    window.location.parameters = parameters;
}
