
function PickerGrid(divElement) {

    this.div = divElement;
    this.max_grid_size = 9;
    this.cover_divs = [];
    this.indexByItemId = {};

}

PickerGrid.prototype.initialize_matrix = function() {

    if (null == recommendations)
        return;

    //var matrix = document.getElementById('matrix');
    var matrix = this.div;
    if (null == matrix)
        return;

    matrix.innerHTML = "";

    var sel = document.config.showme;
    var grid_size = sel.options[sel.selectedIndex].value;

    this.indexByItemId = {};
    this.cover_divs = [];

    var max = this.max_grid_size;

    for (var i = 0; i < max; i++) {
        if (i < recommendations.length) {
            var item = recommendations[i];
            this.cover_divs[i] = create_cover(item);
            if (i >= grid_size)
                this.cover_divs[i].style.display = 'none';
            matrix.appendChild(this.cover_divs[i]);
            this.indexByItemId[item.item_id] = i;
        }
    }

    // clear div makes everything better
    var clear_div = document.createElement('div');
    clear_div.className = 'clear';
    clear_div.innerHTML = '&nbsp;';
    matrix.appendChild(clear_div);

    //new Effect.Appear('matrix');

};

PickerGrid.prototype.fade = function(index) {

    if (null != this.cover_divs[index])
        this.cover_divs[index].style.opacity = "0.5";

};

PickerGrid.prototype.fade_with_vote = function(index, vote) {

    // disable suckerfish on ie on fade
    if (document.all&&document.getElementById) {
        this.cover_divs[index].onmouseover = null;
        this.cover_divs[index].onmouseout = null;
    }

    this.fade(index);

    var voteDivClass = (1 == vote) ?
        'voted voted_positive' : 'voted voted_negative';

    this.cover_divs[index].innerHTML =
        '<img src="/images/item' + recommendations[index].small_img_link +
            '" onerror="this.src = \'/images/item/missing_image.gif\';">' +
            '<div class="' + voteDivClass + '">&nbsp;</div>';

};

PickerGrid.prototype.fade_all = function() {

    for (var i = 0; i < this.max_grid_size; i++)
        this.fade(i);

};

PickerGrid.prototype.fade_by_item_id = function(item_id) {

    this.fade(this.index_by_item_id(item_id));

};

PickerGrid.prototype.fade_by_item_id_with_vote = function (item_id, vote) {

    var index = this.index_by_item_id(item_id);
    this.fade_with_vote(index, vote);

};

PickerGrid.prototype.index_by_item_id = function(item_id) {

    if (null != this.indexByItemId[item_id])
        return this.indexByItemId[item_id];
    else
        return null;

};

PickerGrid.prototype.show = function(count) {

    for (var i = 0; i < this.max_grid_size; i++) {
        if (null == this.cover_divs[i])
            continue;
        if (i < count)
            this.cover_divs[i].style.display = '';
        else
            this.cover_divs[i].style.display = 'none';
    }

};




function empty_handler(rs) { return; }

function on_showme_changed() {

    if (initializing)
        return false;

    //grid_matrix.initialize_matrix();

    var sel = document.config.showme;
    var grid_size = sel.options[sel.selectedIndex].value;

    grid_matrix.show(grid_size);

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'config',
        extra_params: 'grid_size=' + grid_size,
        handler: empty_handler,
        skip_auth: 1
    });

}

function on_ignore_previous_changed() {

    if (initializing)
        return false;

    var extra_params = 'ignore_previous=' +
        (document.config.ignore_previous.checked ? '1' : '0');

    initialize(extra_params);

}

function on_auto_save_changed() {

    if (initializing)
        return false;

    var auto_save = (document.config.auto_save.checked ? '1' : '0');

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'config',
        extra_params: 'auto_save=' + auto_save,
        handler: empty_handler,
        skip_auth: 1
    });

}

function on_next_clicked() {

    if (initializing || null == recommendations)
        return;

    var skip_item_ids = new Array();

    var sel = document.config.showme;
    var grid_size = sel.options[sel.selectedIndex].value;

    for (var i = 0; i < grid_size; i++) {
        if (i < recommendations.length &&
            null != recommendations[i].item_id) {

            item_id = recommendations[i].item_id;
            if (null == this_screen_votes[item_id])
                skip_item_ids.push(item_id);
        }
    }

    if (0 < skip_item_ids.length)
        recommend('skip_item_ids=' + skip_item_ids.join(','));
    else
        recommend('');

    return false;

}


function push_album(item) {

    if (null == item)
        return;

    var tr = document.createElement('tr');

    var td = document.createElement('td');
    var img = document.createElement('img');
    img.src = (2 == item.user_vote) ?
        '/images/thumbs/t_down.gif' : '/images/thumbs/t_up.gif';
    td.appendChild(img);
    tr.appendChild(td);

    td = document.createElement('td');
    td.className = 'item-title';
    var a = document.createElement('a');
    a.href = '/' + item.category_link_name + '/' + item.item_id + '/';
    a.innerHTML = '<img src="/images/item' + item.small_img_link +
        '" onerror="this.src = \'/images/item/missing_image.gif\';" />' +
        item.name + '</a>';
    td.appendChild(a);
    tr.appendChild(td);

    var tbody = document.getElementById('myrecs_tbody');
    if (null == tbody)
        return;

    var reference_tr = tbody.firstChild; // need to know class name, if any.
    while (null != reference_tr &&
              1 != reference_tr.nodeType)
        reference_tr = reference_tr.nextSibling;

    tr.className = (null  !=  reference_tr &&
                    'odd' !== reference_tr.className) ? 'odd' : 'even';

    tbody.insertBefore(tr, tbody.firstChild);

    // push_album is a combination add-and-prune.  so,...
    trim_tbody();

}


function trim_tbody() {

    var tbody = document.getElementById('myrecs_tbody');

    var row_count = 0;

    var tr = tbody.firstChild;
    while (null != tr) {
        if (1 == tr.nodeType && 'tr' === tr.tagName.toLowerCase())
            ++row_count;
        tr = tr.nextSibling;
    }

    var tr = tbody.lastChild;
    while (tr != null && row_count > 10) {
        if (1 == tr.nodeType && 'tr' === tr.tagName.toLowerCase()) {
            tbody.removeChild(tr);
            --row_count;
        }
        tr = tr.previousSibling;
    }

}




// (begin) for suckerfish dropdown (patch ie :hover)
function get_div_kid(elem) {
    for (var kid = elem.firstChild; null != kid; kid = kid.nextSibling)
        if (1 == kid.nodeType && 'div' === kid.tagName.toLowerCase())
            return kid;
    return null;
}
function ie_show_vote_div(elem) {
    var kid = get_div_kid(elem);
    if (null != kid)
        kid.className = 'covervote coverover';
}
function ie_hide_vote_div(elem) {
    var kid = get_div_kid(elem);
    if (null != kid)
        kid.className = 'covervote';
}
// (end) for suckerfish dropdown (patch ie :hover)

var recommendations = null;
var fade_complete = false;

function set_message_span(data) {

    var messageSpan = document.getElementById('random');
    if (null == messageSpan)
        return;

    if (0 == data.recommendations.length) {
        messageSpan.innerHTML = '(no recommendations)';
        messageSpan.style.display = '';

    } else if (null != data.random && 'true' === data.random) {
        messageSpan.innerHTML = '(these are diverse items)';
        messageSpan.style.display = '';

    } else {
        messageSpan.style.display = 'none';
    }

}


function recommend_handler(rs) {

    switch(rs.response) {
        case 700:
            recommendations = rs.data.recommendations;
            //if (fade_complete)
            if (true)
                grid_matrix.initialize_matrix();
            //show_skip_these();
            votes_this_screen = 0;
            this_screen_votes = {};
            set_like_minded(rs.data.like_minded);
            set_message_span(rs.data);
            break;
        default:
            ATTAP.default_handler(rs);
            break;
    }

}

var pending_add_to_list = null;

function on_fade_complete(effect) {

    effect.setOpacity(0.1);   // from the default

    // item to add to list?
    if (null != pending_add_to_list) {
        push_album(pending_add_to_list);
        pending_add_to_list = null;
        trim_tbody();
    }

    // have we gotten recommendations back yet?
    if (null != recommendations)
        grid_matrix.initialize_matrix();
    else
        fade_complete = true;

}


function recommend(extra_params) {

    if (null == recommendations)
        return;
    recommendations = null;
    fade_complete = false;

//    new Effect.Opacity('matrix', {
//        from: 1.0,
//        to: 0.1,
//        afterFinish: on_fade_complete
//    });

    // for (item_id in matrix_divs)
//        if (null != matrix_divs[item_id] && null != matrix_divs[item_id].style)
//            matrix_divs[item_id].style.opacity = "0.3";
    grid_matrix.fade_all();

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'recommend',
        extra_params: extra_params,
        handler: recommend_handler,
        skip_auth: 1
    });

}

var vote_count_this_session = 0;

function send_vote(extra_params) {

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'vote',
        extra_params: extra_params,
        handler: empty_handler,
        skip_auth: 1
    });

}


function vote(item_id, vote) {

    // votes don't count if we're in the middle of getting recs.
    if (null == recommendations)
        return;

    var item = null;
    for (var i = 0; i < recommendations.length; i++) {
        if (item_id == recommendations[i].item_id) {
            item = recommendations[i];
            break;
        }
    }

    if (null == item)
        return;

    //show_run_recommender();
    ++votes_this_screen;
    this_screen_votes[item_id] = vote;

//    matrix_divs[item_id].style.opacity = "0.3";
    //grid_matrix.fade_by_item_id(item_id);
    grid_matrix.fade_by_item_id_with_vote(item_id, vote);
    item.user_vote = vote;
    push_album(item);
    //pending_add_to_list = item;

    ++vote_count_this_session;

    //recommend('item_id=' + item_id + '&vote=' + vote);
    send_vote('item_id=' + item_id + '&vote=' + vote);

}

function create_cover(item) {

    var div = document.createElement('div');
    div.className = "cover";

    var html = new Array();

    // trim size of name
    var trimmed_name = item.name;
    if (40 < trimmed_name.length) {
        trimmed_name = trimmed_name.substr(0, 40) + '...';
    }

    html.push( '<img src="/images/item' );
    html.push(     item.small_img_link );
    html.push( '" onerror="this.src = \'/images/item/missing_image.gif\';">' );

    html.push( '<div class="covervote">' );
    html.push(    '<h3><a href="/' )
    html.push(           item.category_link_name );
    html.push(           '/' );
    html.push(           item.item_id );
    html.push(           '/" title="See more about ' );
    html.push(           item.name );
    html.push(    '">' );
    html.push(           trimmed_name );
    html.push(    '</a></h3><p>' );
    html.push(    '<img src="/images/thumbs/black/t_up.gif" ' );
    html.push(         'onclick="vote(' + item.item_id + ', 1)">' );
    html.push(    '<img src="/images/thumbs/black/t_down.gif" ' );
    html.push(         'onclick="vote(' + item.item_id + ', 2)">' );
    html.push( '</p></div>' );

    div.innerHTML = html.join('');

    // simple ie check.  apply :hover patch as necessary.
    if (document.all&&document.getElementById) {
        div.onmouseover = function() { ie_show_vote_div(this); };
        div.onmouseout  = function() { ie_hide_vote_div(this); };
    }

    return div;

}


//matrix_divs = {};


function set_like_minded(like_minded) {

    var div = document.getElementById('like_minded_riffers_div');
    if (null == div)
        return;

    if (null == like_minded)
        return;

    var html = new Array();
    var added = 0;

    for (var i = 0; i < like_minded.length; i++) {
        var riffer = like_minded[i];

        if (null == riffer.user_id || null == riffer.username)
            continue;

        html.push( '<div><a href="/user/' );
        html.push(     riffer.username );
        html.push( '/" title="' );
        html.push(     riffer.username );
        html.push( '"><img src="/images/user/' );
        html.push(     riffer.avatar_link );
        html.push( '" alt="' );
        html.push(     riffer.username );
        html.push( '" onerror="this.src=\'/images/user/default.jpg\';"' );
        html.push( ' height="50" /></a></div>' );

        if (++added >= 8)
            break;

    }

    div.innerHTML = html.join('');

}


grid_matrix = null;
votes_this_screen = 0;
this_screen_votes = {};

var is_logging_in = false;
function do_initialize(data) {

    // set the config switches appropriately
    var sel = document.config.showme;
    for (var i = 0; i < sel.options.length; i++)
        sel.options[i].selected =
            (data.config.grid_size == sel.options[i].value);

    document.config.ignore_previous.checked = data.config.ignore_previous;

    document.config.auto_save.checked =
        (1 == data.config.auto_save) ? true : false;

    var category_id = data.config.category_id;
    if (0 == category_id)
        category_id = "";

    sel = document.config.category;
    for (var i = 0; i < sel.options.length; i++)
        sel.options[i].selected =
            (category_id + "" === "" + sel.options[i].value);

    if (null != data.config.advanced)
        display_advanced(data.config.advanced);

    // pre-populate the list of recently voted-on items
    for (var i = 9; i >= 0; i--)
        if (i < data.recent_votes.length)
            push_album(data.recent_votes[i]);

    // fade in the recommendations
    set_message_span(data);
    recommendations = data.recommendations;
    //grid_matrix.initialize_matrix();
    grid_matrix = new PickerGrid(document.getElementById('matrix'));
    grid_matrix.initialize_matrix();
    //show_skip_these();
    votes_this_screen = 0;
    this_screen_votes = {};

    // set like minded riffers, if any
    set_like_minded(data.like_minded);

    // how many votes this session?
    if (null != data.vote_count && 1 != data.config.login_save)
        vote_count_this_session = data.vote_count;
    else
        vote_count_this_session = 0;

    if (null != data.config.is_logging_in && 1 == data.config.is_logging_in) {
        if (null != user_id) {
            // user just logged in, and this is their first time
            // back at explore.  save their votes.
            login_save_session_votes();
            ATTAP.ajax({
                url: '/ajax/explore.cgi',
                section: 'config',
                extra_params: 'is_logging_in=0',
                handler: empty_handler,
                skip_auth: 1
            });
            vote_count_this_session = 0;
        }
    }

    restarting = false;
    initializing = false;

}


function initialize_handler(rs) {

    switch(rs.response) {
        case 700:
            document.getElementById('matrix').innerHTML = "";
            do_initialize(rs.data);
            break;
        default:
            ATTAP.default_handler(rs);
            break;
    }

}

var initializing = true;

function clear_my_votes() {

    // ie seems to need dom parsing for tables
    var tbody = document.getElementById('myrecs_tbody');
    if (null != tbody)
        while (0 < tbody.childNodes.length)
            tbody.removeChild(tbody.lastChild);

}


function initialize(extra_params) {

    initializing = true;

    // leave the matrix grid clearing until later
    // so that the screen doesn't jump.
    clear_my_votes();
    document.getElementById('like_minded_riffers_div').innerHTML = "";

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'initialize',
        extra_params: extra_params,
        handler: initialize_handler,
        skip_auth: 1
    });

}

function on_restart_clicked() {

    restarting = true;
    on_close();
    initialize('clear=true');

}


function save_session_votes() {

    new Ajax.Request('/ajax/explore.cgi', {
        oncomplete: function(transport) { return; },
        asynchronous: false,
        method: 'post',
        parameters: 'section=save'
    });

}

function login_save_session_votes() {

    new Ajax.Request('/ajax/explore.cgi', {
        oncomplete: function(transport) { return; },
        asynchronous: false,
        method: 'post',
        parameters: 'section=login_save'
    });

}


function clear_session_votes() {

    new Ajax.Request('/ajax/explore.cgi', {
        oncomplete: function(transport) { return; },
        asynchronous: false,
        method: 'post',
        parameters: 'section=clear'
    });

}


is_user_logged_in = false;
is_user_already_prompted = false;

function on_close() {

    if (! (0 < vote_count_this_session))
        return true;

    if (document.config.auto_save.checked) {
        save_session_votes();
        return true;
    }

    // if we said 'sign in to save your votes'
    // try to save their votes.
    // this will of course fail if they didn't log in.
    if (is_user_already_prompted) {
        login_save_session_votes();
        return true;
    }

    var message = you_voted_on_message() +
        "  Save these votes?  Hit Cancel to " +
        (restarting ? 'discard' : 'decide later') + ".";

    if (confirm(message)) {
        save_session_votes();
        clear_session_votes();

    } else if (restarting) {
        clear_session_votes();
        vote_count_this_session = 0;
    }

    return true;

}

function set_login_div_message(msg) {

    var div = document.getElementById('login_view');
    if (null == div)
        return;

    var h2_list = div.getElementsByTagName('h2');
    if (0 < h2_list.length)
        h2_list[0].innerHTML = msg;

}


function you_voted_on_message() {

    var vc = (null == vote_count_this_session) ? 0 : vote_count_this_session;
    var items = (1 == vc) ? 'item' : 'items';
    return "You voted on " + vc + ' ' + items + ' this session.';

}


function on_before_unload() {

    // no message is necessary if the user hasn't voted on anything.
    // likewise no message if we're just going to autosave the votes anyway.
    // likewise no message we've already displayed the message.
    if (! (0 < vote_count_this_session) ||
            document.config.auto_save.checked ||
            is_user_already_prompted)
        return void 0;

    // or if the user is already logged in, for that matter.
    if (null != user_id)
        return void 0;

    set_login_div_message('Sign in to save your votes.');
    ATTAP.show_login();

    var message = you_voted_on_message() + "\n" +
            "Hit 'Cancel' then sign in to save your votes.";

    is_user_already_prompted = true;

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'config',
        extra_params: 'is_logging_in=1',
        handler: empty_handler,
        skip_auth: 1
    });

    return message;

}



restarting = false;
window.onunload = on_close;

window.onbeforeunload = on_before_unload;

function on_category_changed() {

    //restarting = true;
    //on_close();

    // get the new category
    var sel = document.config.category;
    var category_id = sel.options[sel.selectedIndex].value;
    if (0 == category_id.length)
        category_id = '0';

    //initialize('clear=true&category_id=' + category_id);
    // try recommend instead, to avoid the 'on_close()'
    recommend('clear=true&category_id=' + category_id);

    // and, since we're changing categories, clear the vote list.
    // actually, don't do that.  it makes for a non-intuitive user experience.
    //clear_my_votes();

}


function toggle_advanced() {

    var a = document.getElementById('toggle_advanced');
    if (null == a)
        return;

    var advanced = ('(simple)' === a.innerHTML) ? '0' : '1';   // toggle
    display_advanced(advanced);

    ATTAP.ajax({
        url: '/ajax/explore.cgi',
        section: 'config',
        extra_params: 'advanced=' + advanced,
        handler: empty_handler,
        skip_auth: 1
    });

}

function display_advanced(advanced) {

    var a = document.getElementById('toggle_advanced');
    var div = document.getElementById('advanced');
    if (null == a || null == div)
        return;

    if ('1' === "" + advanced) {
        div.style.display = "";
        a.innerHTML = "(simple)";
    } else {
        div.style.display = "none";
        a.innerHTML = "(advanced)";
    }

}

function on_recommend_clicked() {

    // actually, don't do this.  just recommend.
    // clear_my_votes();
    recommend('');

}

function show_skip_these() {

    document.getElementById('run_recommender_a').style.display = 'none';
    document.getElementById('skip_these_a').style.display = '';

}

function show_run_recommender() {

    document.getElementById('skip_these_a').style.display = 'none';
    document.getElementById('run_recommender_a').style.display = '';

}


function old_on_next_clicked() {

    if (0 < votes_this_screen)
        on_recommend_clicked();
    else
        on_skip_clicked();

}
