// All translations needed in this file.
_hinfo_options.i18n = {
    'fi': {
        'empty': 'Tyhjä',
        'away': 'Poissa',
        'label_response': 'repliikki',
        'says': 'Puheenvuorot',
        'voting': 'Äänestys',
        'moveto': 'Siirry kohtaan till punkt',
        'add_text': 'muokkaa',
        'cancel_edit': 'Peruuta',
        'save_text': 'Tallenna',
        'could_not_add_decision': 'Virhe päätöksen lisäämisessä.',
        'decision_title': 'Päätös'
    },
    'sv': {
        'empty': 'Blanka',
        'away': 'Frånvarande',
        'label_response': 'replik',
        'says': 'Inlägg',
        'voting': 'Omröstning',
        'moveto': 'Gå till punkt',
        'add_text': 'muokkaa',
        'cancel_edit': 'Peruuta',
        'save_text': 'Tallenna',
        'could_not_add_decision': 'Virhe päätöksen lisäämisessä.',
        'decision_title': 'Beslut'
    }
};

function playposition() {
    var position = 0;
    // Check that the player is created (no splash img elements).
    if (jQuery('#mediaplayer img').length === 0) {
        try {
            position = $f('mediaplayer').getStatus().time;
        } catch (e) {}
    }
    return position;
}

function HallInfo() {

    /* Current state polling frequency in millisecondsnds */
    this.current_state_poll_frequency = 1000 * 10;
    /* Members list polling frequency in milliseconds */
    this.attendants_and_history_poll_frequency = 1000 * 30;
    /* Throttle */
    this.throttle = 0;
    /* Poll busy flag */
    this.poll_busy = false;
    /* Poll congestion rate */
    this.poll_waiting = 0;
    /* Poll congestion limit */
    this.poll_congestion_limit = 6;
    /* List of objects for different time periods and attendants in them. */
    this.attendant_history = null;

    this.statusdata = false;
    this.history_updated = false;
    this.attendants_updated = false;
    this.old_version = false;

    /* Tab ids */
    this.STATUSTAB = 0;
    this.DATATAB = 1;
    this.HISTORYTAB = 2;
    this.ATTENDANTSTAB = 3;

}
/**
 * Helper function to generate voteresults
 */
HallInfo.prototype.generateVoteResults = function (item) {
    var info = this,
        $votes = jQuery('<ul id="aanestys"></ul>');
    jQuery.each(item, function (ai, aitem) {
        if (aitem.tulos) {
           $votes.append(jQuery('<li style="font-weight: bold"></li>').text(aitem['jaa-teksti']+': '+aitem.tulos.jaa));
           $votes.append(jQuery('<li style="font-weight: bold"></li>').text(aitem['ei-teksti']+': '+aitem.tulos.ei));
           $votes.append(jQuery('<li></li>').text(info.i18n('empty') + ': ' + aitem.tulos.tyhjia));
           $votes.append(jQuery('<li></li>').text(info.i18n('away') + ': ' + aitem.tulos.poissa));
       }
    });
    return $votes;
};

/**
 * Refresh function to update status window
 */
HallInfo.prototype.refreshStatusData = function () {
    var info = this;

    /* Try to maintain only a single active poll at a time */
    this.poll_busy = false;
    if (this.poll_busy) {
        this.poll_waiting += 1;
        if (this.poll_waiting < this.poll_congestion_limit) {
            /* Let some poll requests be ignored to avoid congestion and therefore
            duplicate entries. */
            return;
        } else {
            /* Avoid dead-lock by letting the poll proceed if the congestion limit
            is exceeded. */
            this.poll_waiting = 0;
        }
    }

    this.poll_busy = true;

    if (_hinfo_options.is_livesession) {
        jQuery.getJSON(_hinfo_options.context_url + '/@@hallinfo-latest', info.updateStatusData);
    } else {
        if (!info.statusdata) {
            jQuery.getJSON(_hinfo_options.context_url + '/@@hallinfo-annotations',
                function (data, status) {
                    info.statusdata = data;
                    info.updateStatusData(info.findClosestEvent(info.statusdata,
                        Math.round(playposition()+_hinfo_options.video_offset)), true);
                }
            );
        } else {
            info.updateStatusData(info.findClosestEvent(info.statusdata,
                Math.round(playposition()+_hinfo_options.video_offset)), true);
        }
    }
};

/*
 * Update data in status window
 */
HallInfo.prototype.updateStatusData = function (data, status) {

    if (!data) {
        return;
    }

    var info = this;

    /* Basic titles */
    var titles = ['asianumero','kohtanumero','asiateksti','tila'];
    jQuery.each(titles, function(i, item) {
        var tmp;
        if (data[item]) { tmp = data[item]; }
        else { tmp = "-"; }
        jQuery("#"+item).text(tmp);
    });

    /* Speaker */
    var $speaker = jQuery("#puheenvuoro");
    if (data.puheenvuoro && data.puheenvuoro.henkilo) {

        $speaker.parent().show();
        $speaker.text(data.puheenvuoro.henkilo);
    } else {
        $speaker.parent().hide();
        $speaker.text('');
    }

    /* Reservations */
    var $puheenvuorovaraukset = jQuery('#puheenvuorovaraukset');
    $puheenvuorovaraukset.empty();

    var varaukset = data.puheenvuorovaraukset;
    var repliikit = data.repliikkivaraukset;
    if ((varaukset && varaukset.length>0) || (repliikit && repliikit.length>0)) {
        $puheenvuorovaraukset.parent().show();
    } else {
        $puheenvuorovaraukset.parent().hide();
    }

    jQuery.each(repliikit, function (i, item) {
        var liv = jQuery('<li></li>')
            .addClass('varaus')
            .text(item.henkilo);
        $puheenvuorovaraukset.append(liv);
    });
    jQuery.each(varaukset, function (i, item) {
        var liv = jQuery('<li></li>')
            .addClass('varaus')
            .text(item.henkilo);
        $puheenvuorovaraukset.append(liv);
    });

     /*
      * Generate vote results to misc section
      */
    var vote = data.aanestys;
    var misc = jQuery('#muuta');
    if (vote && vote.length>0) {
        misc.append(this.generateVoteresults(vote));
    } else {
        misc.empty();
    }

};

/**
 * Fetch the attendant history data and call the refreshAttendants function.
 */
HallInfo.prototype.fetchPresenceHistory = function () {

    var info = this;

    jQuery.getJSON(_hinfo_options.context_url + '/@@hallinfo-presence-history',
        function (data, status) {
            if (data && data !== 'null' && data.length > 0) {

                // Save fetched data and mark attendant updated.
                info.attendant_history = data;
                info.attendants_updated = true;
                // Refresh the attendant list.
                info.refreshAttendants();

            } else {

                // Fallback to old
                // Fetch the current attendants and update the list.
                jQuery.getJSON(_hinfo_options.context_url + '/@@hallinfo-attendants',
                               function (data, status) {
                                   if (data && data !== 'null' && data.paikat.length > 0) {
                                       info.old_version = true;
                                       info.attendant_history = data;
                                       info.attendants_updated = true;
                                       info.refreshAttendants();
                                   }
                               });
            }
    });

};

/**
 * Wrapper function for attendant list refreshing.
 *
 * Fetches the attendant list for live sessions and
 * calls the refreshAttendantList function to update
 * the list.
 *
 * For non-live sessions the attendant list fetching
 * function is called once and after updating the list
 * the refreshAttendantList function is just called
 * with the current data.
 */
HallInfo.prototype.refreshAttendants = function () {

    var info = this,
        playposition_offset = Math.round(playposition() + _hinfo_options.video_offset);

    if (_hinfo_options.is_livesession) {

        // Fetch the current attendants and update the list.
        jQuery.getJSON(_hinfo_options.context_url + '/@@hallinfo-attendants',
            function (data, status) {
                if (data && data !== 'null') {
                    info.refreshAttendantList(data);
                }
            });

    } else {

        // Fetch attendant JSON if the data has not been yet updated.
        if (!this.attendants_updated) {
            this.fetchPresenceHistory();
            return;
        }

        // Refresh the list with the current data.
        // Fallback to old
        if (!this.old_version) {
            this.refreshAttendantList(this.findClosestEvent(this.attendant_history, playposition_offset));
        } else {
            // Fallback
            this.refreshAttendantList(this.attendant_history);
        }
    }
};

/**
 * Refreshes the attendant list by the given JSON object.
 */
HallInfo.prototype.refreshAttendantList = function (attendants) {

    var attendant_list = [],
        i, num_attendants,
        place, place_num, place_person, place_history,
        j, history_person,
        added_history_attendants = [],
        place_added = false;

    num_attendants = attendants.paikat ? attendants.paikat.length : 0;

    for (i = 0; i < num_attendants; i += 1) {

        place = attendants.paikat[i];
        place_num = place.paikka;
        place_person = place.henkilo;
        place_history = place.history;

        // Add person to the list if the num and the name are not empty.
        if (place_num && place_person) {
            attendant_list.push('<li class="henkilo">' + place_num +
                ' ' + place_person + '</li>');
            place_added = true;
        }

        // If there are persons in the history list, add them
        // below the current person.
        if (place_history && place_history.length > 0) {

            if (!place_added && place_num) {
                attendant_list.push('<li class="henkilo">' + place_num + '</li>');
            }

            for (j = 0; j < place_history.length; j += 1) {

                history_person = place_history[j].henkilo;

                // Add the person from history if it is not the same as the
                // current person on the place.
                if (history_person && history_person !== place_person &&
                    jQuery.inArray(history_person, added_history_attendants) === -1) {

                    attendant_list.push('<li class="henkilo henkilo-history">' +
                        history_person + '</li>');
                    added_history_attendants.push(history_person);
                }
            }
            added_history_attendants = [];
        }
    }

    if (attendant_list) {
        jQuery('#attendants').html(attendant_list.join(''));
    }

};

/**
 * Adds a link that opens an edit field for each case.
 */
HallInfo.prototype.addEditFields = function () {

    var info = this,
        addHtml = ' <a class="decision-link" href="#">' + info.i18n('add_text') + '</a>',

        editHtml = ['<textarea rows="5" cols="20"></textarea><br />',
                    '<input class="edit-decision-submit" type="button" value="',
                        info.i18n('save_text'), '">',
                    '<input class="edit-decision-cancel" type="button" value="',
                        info.i18n('cancel_edit'), '" />'
                   ].join('');

    // Add the edit links for each case.
    $('span.decision').append(addHtml);

    // Use event delegation to assing only one click handler
    // for the parent element and checking the target.
    $('#session-history').click(function (e) {

        var target = $(e.target),
            container = target.parent(),
            decision, decisionText = '',
            decisionLink, editArea, editAreaDom;

        if (target.is('a') && container.is('span.decision')) {

            // Add a global flag so that the content is not refreshed
            // while the edit form is in use.
            _hinfo_options.edit_field_open = true;

            decision = container.children('span.decision-text');
            decisionLink = container.children('a.decision-link');

            // Save added decision if one is found.
            if (decision && decision.html()) {
                decisionText = decision.data('decision_text');
            }

            decision.hide();
            decisionLink.hide();

            // Change the html and focus on the textarea.
            editArea = container.children('span.decision-edit').html(editHtml).fadeIn();
            editAreaDom = editArea.find('textarea').get(0);
            editAreaDom.value = decisionText;
            editAreaDom.focus();

            // Remove the edit field and show the link
            // if the cancel button is clicked.
            container.find('input.edit-decision-cancel').click(function (e) {
                editArea.fadeOut('normal', function () {
                    $(this).empty();
                    decision.show();
                    decisionLink.show();
                    _hinfo_options.edit_field_open = false;
                });
            });

            container.find('input.edit-decision-submit').click(function (e) {

                var editText = editArea.find('textarea').val();

                $.post(_hinfo_options.context_url + '/@@hallinfo-add-decision', {
                    paatos: editText,
                    asianumero: container.siblings('span.kohtanumero').html(),
                    snro: container.siblings('span.snro').text() || 'unknown'
                }, function (data, textStatus) {

                    if (data && typeof data.paatos === 'string' &&
                        typeof data.paatos_raw === 'string') {

                        // Remove the edit form and put the fetched text
                        // in the decision text element.
                        editArea.fadeOut('normal', function () {

                            var text = data.paatos_raw.replace(/\n/g, '\r\n'),
                            decisionTitle = decision.siblings('span.decision-title');

                            $(this).empty();
                            decision.html(info.htmlize(info.escape(data.paatos_raw))).show();
                            decision.data('decision_text', text);

                            // Show decision title only if the decision is non-empty.
                            if (text) {
                                decisionTitle.css('display', 'block');
                            } else {
                                decisionTitle.css('display', 'none');
                            }

                            decisionLink.show();
                            _hinfo_options.edit_field_open = false;
                        });

                    } else {
                        alert(info.i18n('could_not_add_decision'));
                    }
                }, 'json');

            });

            e.preventDefault();
        }
    });
};

/**
 * Refreshes meeting history from the backend.
 */
HallInfo.prototype.refreshHistory = function () {
    var info = this;
    if (!_hinfo_options.is_livesession && info.history_updated) {
        return;
    } else if (_hinfo_options.edit_field_open) {
        // Don't update the content if the edit field is open.
        return;
    }
    jQuery.getJSON(_hinfo_options.context_url + '/@@hallinfo-meeting',
        function (data, status) {
            var $history = jQuery('#session-history');
            $history.empty();

            if (!data) {
                return;
            }
            $.each(data.asiat, function (i, item) {
                if (item.asia.asianumero) {
                    var span1 = jQuery('<span></span>')
                    .addClass('kohtanumero')
                    .text(item.asia.asianumero);
                    var span2 = jQuery('<span></span>')
                    .addClass('tapahtuma')
                    .text(item.asia.asiateksti);

                    if (!_hinfo_options.is_livesession && item.asia.second) {
                        span2 = span2.wrap('<a class="jump-to-title" href="#" title="' +
                                           info.i18n('moveto') + '"></a>').parent();
                        span2.click(function (e) {
                            // Have to make an extra closure to
                            // get the right argument in a loop.
                            (function (second) {
                                info.seek(second, true);
                            }(item.asia.second));
                            e.preventDefault();
                        });
                    }

                    var li = jQuery('<li></li>')
                        .addClass('asiakohta')
                        .append(span1)
                        .append(span2)
                        .append('<span class="snro" style="display:none;">' + item.asia.snro + '</span><br />');

                    li.append('<span class="decision"><span class="decision-title">' + info.i18n('decision_title') +
                              ':</span><span class="decision-text"></span>' +
                              '<span class="decision-edit"></span></span>');

                    if (item.asia.paatos) {
                        li.find('span.decision-title').css('display', 'block');
                        li.find('span.decision-text').html(
                            info.htmlize(info.escape(item.asia.paatos))).data('decision_text',
                                                                 item.asia.paatos.replace(/\n/g, '\r\n'));
                    }

                    if (item.puheenvuorot.length>0) {
                        li.append($('<span class="header">' + info.i18n('says') + '</span>'));
                        var puheenvuorot = jQuery('<table id="puheenvuorot" class="puheenvuorot"></table>');
                        $.each(item.puheenvuorot, function (pi, pitem) {
                            var pli = jQuery('<tr></tr>').addClass('henkilo'),
                                speakerHtml = pitem.henkilo + '<span style="display:none;">' + pitem.second + '</span>';

                            if (!_hinfo_options.is_livesession) {
                                speakerHtml = '<a href="#" class="jump-to-link" title="' +
                                    info.i18n('moveto') + '">' + speakerHtml + '</a>';
                            }

                            pli.append(jQuery('<td></td>').html(speakerHtml));

                            // Display the duration if it is defined, otherwise an empty element.
                            if (pitem.duration) {
                                pli.append(jQuery('<td></td>').addClass('small').text(
                                    Math.round(pitem.duration/60)+':'+info.zpad(pitem.duration%60)+' min'));
                            } else {
                                pli.append('<td class="small"></td>');
                            }
                            puheenvuorot.append(pli);
                        });


                        li.append(puheenvuorot);
                    }
                    if (item.aanestykset.length>0) {
                        li.append('<span class="header">' + info.i18n('voting') + '</span>');
                        li.append(info.generateVoteResults(item.aanestykset));
                    }

                    $history.append(li);
                }
            });

            $('table.puheenvuorot').click(function (e) {

                var target = $(e.target),
                    seekSeconds;

                if (target.is('a.jump-to-link')) {
                    try {
                        seekSeconds = parseInt(target.children('span').html(), 10);
                    } catch(err) {
                        return false;
                    }

                    info.seek(seekSeconds, true);
                    e.preventDefault();

                }
            });

            info.history_updated = true;

            // Add a link that opens an inline edit field for
            // each case for editor users.
            if (_hinfo_options.is_editor) {
                info.addEditFields();
            }
        });
};

// Binary search to find closest action node from annotated list.
// Returned value is always smaller
HallInfo.prototype.findClosestEvent = function(o, v){
    var h = o.length, l = -1, m;
    while(h - l > 1) {
        m = h + l >> 1;
        if(o[m].second < v) {
            l = m;
        } else {
            h = m;
        }
    }
    return o[l];
};

// Convert 0 -> 00, 1 -> 01 , etc
HallInfo.prototype.zpad = function (i) {
    return (i.toString().length === 1) ? '0' + i.toString() : i.toString();
};

/**
 * Seeks the player to the specified position.
 * Starts the player if it not yet playing.
 */
HallInfo.prototype.seek = function (seconds, substractOffset) {

    var player = $f('mediaplayer'),
        offset = substractOffset ? _hinfo_options.video_offset : 0,
        playPosition = seconds - offset;

    playPosition = playPosition < 0 ? 0 : playPosition;

    // Check that the player is created (no splash img elements)
    // and that is already playing.
    if ($('#mediaplayer img').length === 0 && player.isPlaying()) {
        player.seek(playPosition);
    } else {

        // If the player is not yet playing, we must first
        // make it start playing for a while until calling
        // the seek method.
        player.play();

        setTimeout(function () {
            player.seek(playPosition);
        }, 1000);
    }

};

/**
 * Replace linebreaks with br tags and put paragraphs inside p tags.
 */
HallInfo.prototype.htmlize = function (s) {
    // We have to leave the line breaks (\n) in so that
    // the content can be put to the textarea again.

    return '<p>' +
        s.replace(/\n\n/g, '</p><p>').
        replace(/\n/g, '<br />') +
        '</p>';
};

HallInfo.prototype.escape = function (s) {
    return s.
        replace(/&/g, '&amp;').
        replace(/</g, '&lt;').
        replace(/>/g, '&gt;').
        replace(/"/g, '&quot;').
        replace(/'/g, '&#39;');
};

HallInfo.prototype.i18n = function (key) {
    return _hinfo_options.i18n[_hinfo_options.lang][key];
};

var _info = new HallInfo();

/**
 * Polls the backend server indefinitely for attendants & history.
 */
function lists() {
    if (_info.attendants_and_history_poll_frequency > 0) {
        var _selected_tab = jQuery('#session-data').tabs().tabs('option', 'selected');
        if (_selected_tab === _info.HISTORYTAB) {
            _info.refreshHistory();
        }
        if (_selected_tab === _info.ATTENDANTSTAB) {
            _info.refreshAttendants();
        }
        setTimeout(lists,  _info.attendants_and_history_poll_frequency);
    }
}
/**
 * Polls the backend server indefinitely for new status.
 */
function poll() {
    if (_info.current_state_poll_frequency > 0) {
        var _selected_tab = jQuery('#session-data').tabs().tabs('option', 'selected');
        if (_selected_tab === _info.STATUSTAB) {
            _info.refreshStatusData();
        }
        setTimeout(poll, _info.current_state_poll_frequency);
    }
}

function activate_player() {
    jQuery('#portal-column-content a.hkmediacontent').primacontrolflowplayer({
        'portal_url' : 'http://www.helsinkikanava.fi',
        'flowplayer_key' : '#@db758bae28bbdd845c3'
    });
}
 


/* Document init */
jQuery(document).ready(function () {
    // Tabs
    jQuery('#session-data').tabs();
    // Show tab content after onload to avoid unstyled content.
    jQuery('#hallSessionVideoRelatedContent').css('visibility', 'visible');

    // Chapter selector box functionality
    jQuery('#chapters').change(function() {
        _info.seek(jQuery(this).val(), false);
        setTimeout(function () {
            jQuery('#chapters option').removeAttr('selected');
        }, 5000);
    });

    jQuery("#puheenvuoro").parent().hide();
    jQuery('#puheenvuorovaraukset').parent().hide();

    if (_hinfo_options.context_url.match(/\/sv\//)) {
        _hinfo_options.lang = 'sv';
    } else {
        _hinfo_options.lang = 'fi';
    }

    // Polling data
    poll();
    lists();

    if (_hinfo_options.is_livesession) {
        /* For live session check the backend */
        jQuery.getJSON(_hinfo_options.context_url + '/@@show-player',
            function (data, status) {
                if (data.show_player) {
                    activate_player();
                } else {
                    jQuery('#portal-column-content a.hkmediacontent')
                        .replaceWith('<div id="no-player">' +
                                       '<div class="ui-overlay"><div class="ui-widget-overlay"></div><div class="ui-widget-shadow ui-corner-all"></div></div>' +
                                       '<div class="ui-widget ui-widget-content ui-corner-all"><h1>Videopalvelimella on ruuhkaa</h1><p>Videopalvelimen maksimikapasiteetti on saavutettu. Yritä myöhemmin uudelleen.</p></div>' +
                                     '</div>');
                }
        });
    } else {
        activate_player();
    }

    jQuery('#session-data > ul a').bind('click', function () {
        var _selected_tab = jQuery('#session-data').tabs().tabs('option', 'selected');
        if (_selected_tab === _info.STATUSTAB) {
            _info.refreshStatusData();
        }
        if (_selected_tab === _info.HISTORYTAB) {
            _info.refreshHistory();
        }
        if (_selected_tab === _info.ATTENDANTSTAB) {
            _info.refreshAttendants();
        }
    });

    // Seek player to position 'seekto' if such param defined
    // Method is used links on external sites.
    if (window.location.search.split("?").length === 2) {
        var urlparam = window.location.search.split("?")[1].split("=");
        if (urlparam[0] === "seekto") {
            setTimeout(function () {
                _info.seek(urlparam[1], false);
            }, 1000);
        }
    }

});
