


function ProcessStaus(status,message,progress){
this.status=status;
this.message=message;
this.progress=progress;
this.getProgress=function(){return this.progress;};
this.hasProgress=function(){return ((this.progress != undefined) && (this.progress != ''));};
this.getStatus=function(){return this.status;};
this.getMessage=function(){return this.message;};
this.hasMessage=function(){return ((this.message != undefined) && this.message != '');};
this.isCompleted = function(){ return ((status != 'running') && (status != 'waiting'));};
this.toString = function(){ var txt = 'Status: ' + status; if (this.hasMessage()){ txt = txt + ', Message: ' + message;} if (this.hasProgress()){ txt = txt + ', Progress: ' + progress;} return txt;};
}

/**
 * SlugMgr class definition
 * @param updateFunc application update function name.
 * @param pid process ID.
 * @param slugUrl URL to the SlugServlet mapping.
 * @param translator translator name.
 * @param runner optional runner name. Detault is used if this parameer is not provided.
 * @return new SlugMgr instance.
 */
function SlugMgr(updateFunc, pid, slugUrl, translator, runner) {
    // default refresh time of 1/2 second.
    this.refresh = 500;
    // set update call bask
    this.appUpdate = function (ps) { updateFunc(this, ps); };
    // set the default error call back
    this.appError = function (status) { alert ('Error server status: ' + status); };

    // calculate urls
    this.statusUrl  = mkSlugURL(slugUrl, pid, 'status', translator, runner);
    this.cancelUrl  = mkSlugURL(slugUrl, pid, 'cancel', translator, runner);
    this.consumeUrl = mkSlugURL(slugUrl, pid, 'consume', translator, runner);

    // set default URL
    this.reqUrl = this.statusUrl;
    // set running status to not in use
    this.inProcess = false;

    // Process manaagement functions
    // cancel process call
    this.cancel = function () {this.reqUrl = this.cancelUrl;};
    // consume process call
    this.consume = function () {this.reqUrl = this.consumeUrl;};
    // initial startup call
    this.start = function() { doRequest(this); };

    // internal functions
    /**
     * Send request
     * @param mgr SlugMgr to act on
     */
    function doRequest(mgr) {
        // do not reenter if request is pending
        if (mgr.inProcess) {
            return;
        }
        mgr.inProcess = true;

        // obtain a request object
        var req = false;
        if (window.XMLHttpRequest) { // Mozilla/Safari
            req = new XMLHttpRequest();
        } else if (window.ActiveXObject) { // IE
            req = new ActiveXObject('Microsoft.XMLHTTP');
        }
        req.open('GET', mgr.reqUrl, true);
        req.onreadystatechange = function() {
            process(mgr, req);
        };
        req.send(null);
    }

    /**
     * Request processor
     * @param mgr SlugMgr to act on
     * @param req current XMLHttpRequest
     */
    function process(mgr, req) {
        mgr.inProcess = false;
        if (req.readyState == 4) {
            if (req.status != 200) {
                // TODO retry?!
                mgr.appError(req.status);
                return;
            }
            var prStatus;
            if (req.responseText.indexOf('<?xml') == 0) { // XML input
                prStatus = dom2ps(req.responseXML);
            } else { // raw JavaScrip input
                prStatus = eval(req.responseText);
            }
            mgr.appUpdate(prStatus);
            if (!prStatus.isCompleted()) { // call itself recursively
                setTimeout(function () { doRequest(mgr); }, mgr.refresh);
            }
        }
    }

    /**
     * Create slug URL
     * @param slugUrl path to Slug servlet's mapping.
     * @oaram pid Process ID.
     * @param action Slug action to call - one of "status", "cancel" or "consume".
     * @param runner optioanl runner name.
     * @return SlugUrl URL for provided parameters.
     */
    function mkSlugURL(slugUrl, pid, action, translator, runner) {
        var aURL = slugUrl + '/' + action;
        if (translator != undefined) {
            aURL = aURL + '/' + translator;
        }
        aURL = aURL + '/?pid=' + pid;
        if (runner != undefined) {
            aURL = aURL + '&rn=' + runner;
        }
        return aURL;
    }

    /**
     * Obtain value of the first node.
     * @param dom XML DOM.
     * @parma nn node name.
     * @return the value of the first chiled of the first node with provided 
     * name or undefined if no node is found.
     */
    function getNodeValue(dom, nn) {
        var s;
        var node = dom.getElementsByTagName(nn);
        if (node.length > 0) {
            s = node.item(0).firstChild.nodeValue;
        }
        return s;
    }

    /**
     * Converts XML DOM ProcessStatus to a SlugProcessStatus object.
     * @param dom XML Slug response.
     * @return SlugProcessStatus instance.
     */
    function dom2ps(dom) {
        var status = getNodeValue(dom, 'status');
        var message = getNodeValue(dom, 'message');
        var progress = getNodeValue(dom, 'progress');
        var ps = new ProcessStaus(status, message, progress);
        return ps;
    }
}




