//
// $Id: upload.js,v 1.3 2008/05/17 07:00:42 suter Exp $
// Copyright (C) 2007 Mark Suter <suter@humbug.org.au>
//
// This file is part of Upload.
//
// Upload is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

// Checked on 2007-12-04 using The JavaScript Verifier (Edition 2007-11-14) at http://jslint.com/
// Recommended Options + Good Parts + Assume a browser + Tolerate eval (leaves ActiveXObject undefined) 

// Let server timestamps work in the browser
var date = new Date();
var client_offset = TIME - (date.getTime() / 1000);

// Human readable times
function human_time(seconds) {
    if (seconds > 3600) {
        return Math.floor(seconds / 3600) + ' hours ' + Math.round((seconds % 3600) / 60) + ' min';
    } else if (seconds > 60) {
        return Math.floor(seconds / 60) + ' min ' + Math.round(seconds % 60) + ' sec';
    } else {
        return Math.round(seconds) + ' sec';
    }
}

// Progress IDentifier
var alpha = "0123456789abcdef";
function generate_pid() {
    var id = '';
    for (var i = 0; i < 16; i += 1) {
        id += alpha.charAt(Math.round(Math.random() * 16));
    }
    return id;
}

// http://www.e-articles.info/e/a/title/Cross-Browser-XMLHttpRequest/
function new_web_client() {
    var xmlhttp;
    var ms_objects = [ 'MSXML2.XMLHTTP.5.0',
        'MSXML2.XMLHTTP.4.0',
        'MSXML2.XMLHTTP.3.0',
        'MSXML2.XMLHTTP',
        'Microsoft.XMLHTTP' ];
    var success = false;
    var i;
    try {
        // Mozilla / Safari / IE7
        xmlhttp = new XMLHttpRequest();
    } catch (e1) {
        // IE
        for (i = 0; !success && i < ms_objects.length; i += 1) {
            try {
                xmlhttp = new ActiveXObject(ms_objects[i]);
                success = true;
            } catch (e2) {
                // Ignore
            }
        }
        if (! success) {
            throw new Error('Unable to create XMLHttpRequest');
        }
    }
    return xmlhttp;
}

function progress_bar(data) {
    // Correct for client offset
    data.activity -= client_offset;
    data.start -= client_offset;

    // Refresh the date object
    date = new Date();

    // Stalled?
    var warning = '';
    var age = Math.round((date.getTime() / 1000) - data.activity);
    if (age >= 60) {
        warning = '<div class="alert">Progress may have stalled - last update is ' + age + ' seconds old!</div>';
    }

    // Measured
    var ratio = data.done / data.total;
    var elapsed = (date.getTime() / 1000) - data.start;

    // Estimated
    var rate = Math.round(100 * data.done / elapsed / 1024 ) / 100 + ' KiB/s';
    var time = '';
    if (data.done === data.total) {
        time = human_time(elapsed) + ' (total)';
    } else if (data.done === 0 || ratio < 0.05 || elapsed < 0) {
        rate = 'Starting...';
    } else {
        time = elapsed / ratio - elapsed;
        if (time < 7) {
            time = '';
        } else {
            time = human_time(time) + ' (linear estimate)';
        }
    }

    // Our progress bar - ideas (but not code) taken from on view-source:http://encodable.com/uploaddemo/
    return warning + '<div id="meter">' +
        '<div id="graph"><div id="bar" style="width: ' + Math.round(100 * ratio) + '%;"></div></div>' +
        '<div id="text"><table summary="details" style="width: 100%"><tbody><tr>' +
        '<td id="rate">' + rate + '</td>' +
        '<td id="time">' + time + '</td>' +
        '<td id="percent">' + Math.round(100 * 100 * ratio) / 100 + ' %</td>' +
        '</tr></tbody></table></div>' +
        '</div></p>';
}


// http://developer.mozilla.org/en/docs/AJAX:Getting_Started
function handle_response(req, pid) {
    var finished = 0;
    var data;
    if (req.readyState === 4) {
        try {
            if (req.status === 200) {

                // Eval the JSON representation
                data = eval('(' + req.responseText + ')');

                // Update the progress bar
                document.getElementById(pid).innerHTML = progress_bar(data);

                // Are we there yet?
                if (data.total !== 0 && data.total === data.done) {
                    finished = 1;
                }

                // Do the scroll to the botton, if present
                var info = document.getElementById("info");
                info.scrollTop = info.scrollHeight;
            }
        } catch (e1) {
            // Ignore
        }
        if (! finished) {
            window.setTimeout('update_progress("' + pid + '")', 1500);
        }
    }
}

function update_progress(pid) {
    // http://en.wikipedia.org/wiki/XMLHTTP#Caching
    var url = '.status-' + pid + '?ie=' + Math.random();
    var req = new_web_client();
    try {
        req.open('GET', url, true);
        req.onreadystatechange = function () {
            handle_response(req, pid);
        };
        req.send(null);
    } catch (e1) {
        // Ignore
    }
}

function check_upload(form) {
    // Validate first
    var response = document.getElementById('errors_upload');
    if (form.code.value === '') {
        response.innerHTML = 'Please enter the captcha.';
        response.className = 'alert';
        form.code.focus();
        return false;
    } else if (form.code.value !== 'CAPTCHA') {
        response.innerHTML = 'Please try the captcha again or refresh for a new one.';
        response.className = 'alert';
        form.code.focus();
        return false;
    } else if (form.filename.value === '') {
        response.innerHTML = 'Please choose a file to upload.';
        response.className = 'alert';
        form.filename.focus();
        return false;
    } else {
        // Embed progress bar
        var pid = generate_pid();
        document.getElementById('progress').id = pid;
        form.action += '?pid=' + pid;
        window.setTimeout('update_progress("' + pid + '")', 500);
        response.className = 'hide';
        response.innerHTML = '';
        return true;
    }
}


