// vk:

/*
Syntaxprüfung mit jslint:
java -cp jslint/rhino-1.7.jar \
  org.mozilla.javascript.tools.shell.Main jslint/jslint.js vk.js
*/

/*jslint newcap: false */
/*global $: false, alert: false
 */


var VK = function (conf_arg) {
    var that = {},
    conf = conf_arg,
    create = function () {
    },
    vk_delete = function () {
    },
    updateables = [],
    updateableAdd = function (updateable) {
        updateables.push(updateable);
    },
    updateableRemove = function (updateable) {
        var i;
        for (i = 0; i < updateables.length; i += 1) {
            if (updateables[i] === updateable) {
                updateables.splice(i, 1);
                break;
            }
        }
    },
    updateUpdateables = function (args) {
        var i;
        for (i = 0; i < updateables.length; i += 1) {
            updateables[i].update(that, args);
        }
    };
    that.updateableAdd = updateableAdd;
    that.updateableRemove = updateableRemove;
    that.updateUpdateables = updateUpdateables;
    create();
    return (that);
};


var catIdiEncode = function (idi) {
    return (idi.replace(/\./g, '[DOT]').replace(/,/g, '[KOMMA]').replace(/_/g, '[UNDERLINE]'));
};


var VKSid = function () {
    var sid = $("html>head meta[name=sid]").attr("content");
    // alert('sid: "'+sid+'"');
    return (sid);
};


var VKBasket = function (conf) {
    var that = VK(conf),
    hits = [],
    hitAdd = function (cat, hit) {
        hits.push([cat, hit]);
        that.updateUpdateables({hint: 'basket-add',
                                hit: [cat, hit]});
    },
    fill = function () {
        var sid, url, params;
        sid = VKSid();
        url = "searcher/fillBasket";
        params = {sid: sid, format: 'json'};
        that.updateUpdateables({hint: 'basket-filling'});
        $.ajax({url: url,
                data: params,
                type: 'POST',
                dataType: 'json',
                timeout: 60000,
                success: function (hitsPackage) {
                    var hit, hits, i;
                    if (hitsPackage.error) {
                        alert(hitsPackage.error);
                        that.updateUpdateables({hint: 'basket-err'});
                        return;
                    }
                    hits = hitsPackage.hits;
                    for (i = 0; i < hits.length; i += 1) {
                        hit = hits[i];
                        hitAdd(conf.cats.catGetById(hit.cat_id), hit);
                    }
                    that.updateUpdateables({hint: 'basket-filled'});
                },
                error: function (xhr, status, exception) {
                    var error = true;
                    if (status !== "error") {
                        if (exception) {
                            alert('fill error, status="' + status +
                                  '", exception="' + exception + '"');
                        }
                        else {
                            alert('fill error, status="' + status + '"');
                        }
                    }
                    that.updateUpdateables({hint: 'basket-err'});
                }
            }); 
    },
    clear = function () {
        hits = [];
        that.updateUpdateables({hint: 'basket-clear'});
    },
    create = function () {
        // fill();
    },
    hitRemove = function (cat, hit) {
        var i;
        for (i = 0; i < hits.length; i += 1) {
            if ((cat === hits[i][0]) && (hit.idi === hits[i][1].idi)) {
                hits.splice(i, 1);
                that.updateUpdateables({hint: 'basket-remove',
                                        hit: [cat, hit]});
                break;
            }
        }
    },
    hitsGet = function () {
        return (hits);
    },
    isHitInBasket = function (cat, hit) {
        var i, is = false;
        for (i = 0; i < hits.length; i += 1) {
            if ((cat === hits[i][0]) && (hit.idi === hits[i][1].idi)) {
                is = true;
                break;
            }
        }
        return (is);
    },
    length = function () {
        return (hits.length);
    },
    urlGet = function () {
        var cat, catId, hit, i, id, idi, url;
        catId = "";
        url = "";       
        for (i = 0; i < hits.length; i += 1) {
            cat = hits[i][0];
            hit = hits[i][1];
            idi = hit.idi;
            if (catId !== cat.id) {
                catId = cat.id;
                id = catId + '_' + catIdiEncode(hit.idi);
            }
            else {
                id = catIdiEncode(idi);
            }
            if (url !== "") {
                url += '.';
            }
            url += encodeURIComponent(id);
        }
        if (url !== "") {
            url = "?m=basket&l=" + url;
        }
        return (url);
    };

    create();

    that.fill = fill;
    that.clear = clear;
    that.length = length;
    that.hitAdd = hitAdd;
    that.hitRemove = hitRemove;
    that.hitsGet = hitsGet;
    that.isHitInBasket = isHitInBasket;
    that.urlGet = urlGet;

    return (that);
};


var VKCat = function (conf) {
    var that = VK(conf),
    err = {},
    mats = null,
    hits = null,
    selected = conf.selected,
    create = function () {
        var i;
        // alert("VKCat["+conf.id+"] create");
        if (conf.mats) {
            for (i = 0; i < conf.mats.length; i += 1) {
                if (mats === null) {
                    mats = {};
                }
                mats[conf.mats[i]] = true;
            }
        }
    },
    errorGet = function () {
        return (hits);
    },
    errorSet = function (err) {
        err = err;
        hits = null;
        that.updateUpdateables({hint: 'search-error'});
    },
    hasMats = function (mats_arg) {
        var has = true, i, mat;
        if (mats_arg === null) {
            return (true);
        }
        if (mats === null) {
            if (mats_arg.length > 0) {
                return (false);
            }
            else {
                return (true);
            }
        }
        for (i = 0; i < mats_arg.length; i += 1) {
            mat = mats_arg[i];
            if (!mats[mat]) {
                has = false;
                break;
            }
        }
        return (has);
    },
    hasLengthGet = function (mats) {
        return (hits ? hits.length : null);
    },
    isFunction = function(o) {
        return typeof(o) == 'function' && (!Function.prototype.call ||
                                           typeof(o.call) == 'function');
    },
    hitFields = function () {
        /**/
        var hitFields0 = conf.conf.hitFields;
        if (hitFields0) {
            if (isFunction(hitFields0)) {
                hitFields = hitFields0();
            }
            else {
                hitFields = hitFields0;
            }
        }
        else {
            hitFields = [['title', 'Titel'],
                         ['au', 'Autor'],
                         ['place', 'Verlagsort'],
                         ['pub', 'Verlag'],
                         ['date', 'Erscheinungsjahr'],
                         ['isbn', 'isbn'],
                         ['subj', 'Schlagwörter']];
        }
        return (hitFields);
        /**/
    },
    hitShortAlt = function () {
        return (conf.conf.hitShortAlt);
    },
    hitsLengthGet = function () {
        return (hits ? (hits.totalLength ? hits.totalLength : hits.length)
               : null);
    },
    hitsGet = function () {
        return (hits);
    },
    hitsSet = function (hits_arg) {
        hits = hits_arg;
        that.updateUpdateables({hint: 'hits'});
    },
    info = function () {
        return (conf.conf.info);
    },
    isSelected = function () { 
        return (selected);
    },
    matsGet = function () {
        return (conf.mats);
    },
    nameGet = function () {
        return (conf.name);
    },
    nameShortGet = function () {
        return (conf.nameShort);
    },
    query,
    search = function (args) {
        var mats, q, cs = /*(args.cs) ? args.cs :*/ null, i;
        if (conf.conf.isExtern) {
            query = args.query;
            that.updateUpdateables({hint: 'query-extern', 'query': query});
            // QueryHelp löschen:
            conf.searcher.updateUpdateables({hint: 'searching'}); 
            return;
        }
        if (args.query) {
            query = args.query;
	}
        q = query.get();
        if (!hasMats(q.mats)) {
	    errorSet({msg: "Materialartsuche wird nicht unterstützt"});
	    return;
        }
	if (that.isIndexCat() && (q['cats'] !== null)) {
	    cs = [];
            for (i = 0; i < q['cats'].length; i += 1) {
		cs.push(q['cats'][i]['id']);
	    }
	}
        hits = null;
        that.updateUpdateables({hint: 'searching'});
        conf.searcher.search({cat: that,
                              query: query,
                              first: args.first,
                              last: args.last,
			      cs: cs
			     });
    },
    select = function (sel) {
        if (selected !== sel) {
            selected = sel;
            if (!isSelected()) {
                hits = null;
            }
            that.updateUpdateables({hint: 'cat select'});
        }
    },
    urlGet = function () {
        return (conf.url);
    },
    isIndexCat = function () {
        return (false);
    };
    that.conf = conf.conf;
    that.hasMats = hasMats;
    that.errorGet = errorGet;
    that.errorSet = errorSet;
    that.hitFields = hitFields;
    that.hitShortAlt = hitShortAlt;
    that.id = conf.id;
    that.isSelected = isSelected;
    that.nameGet = nameGet;
    that.nameShortGet = nameShortGet;
    that.hitsLengthGet = hitsLengthGet;
    that.hitsGet = hitsGet;
    that.hitsSet = hitsSet;
    that.matsGet = matsGet;
    that.search = search;
    that.select = select;
    that.urlGet = urlGet;
    that.info = info;
    that.isIndexCat = isIndexCat;
    create();
    return (that);
};


/**/
var VKIndexCat = function (conf) {
    var that = VKCat(conf),
    length = 0,
    hitsLengthGet = function () {
	return(length);
    },
    hitsLengthSet = function (l) {
	length = l;
    },
    isIndexCat = function () {
        return (true);
    };
    that.hitsLengthGet = hitsLengthGet;
    that.hitsLengthSet = hitsLengthSet;
    that.isIndexCat = isIndexCat;
    return (that);
};
/**/


var VKCats = function (conf_arg, indexCats) {
    var that = VK(conf_arg),
    cats,
    conf = conf_arg,
    catGetById = function (id) {
        var cat = null, i;
        for (i = 0; i < cats.length; i += 1) {
            cat = cats[i];
            if (cat.id === id) {
                break;
            }
        }
        return (cat);
    },
    catGetByPos = function (pos) {
        var cat = cats[pos];
        return (cat);
    },
    catsConfGet = function () {
        return (conf.cats);
    },
    catsTreeConfGet = function () {
        return (conf.tree);
    },
    create = function () {
        var cat, id;
        cats = [];
        for (id in conf.cats) {
            if (conf.cats.hasOwnProperty(id)) {
                // alert(id+': "'+conf.cats[id].name+'"');
		if (indexCats && (indexCats === 1)) {
                    cat = VKIndexCat({id: id,
				      conf: conf.cats[id],
				      name: conf.cats[id].name,
				      nameShort: conf.cats[id].nameShort,
				      url: conf.cats[id].url,
				      searcher: conf.searcher,
				      selected: conf.cats[id].preselected,
				      mats: conf.cats[id].mats,
				      cats: that
				     });
		}
		else {
                    cat = VKCat({id: id,
				 conf: conf.cats[id],
				 name: conf.cats[id].name,
				 nameShort: conf.cats[id].nameShort,
				 url: conf.cats[id].url,
				 searcher: conf.searcher,
				 selected: conf.cats[id].preselected,
				 mats: conf.cats[id].mats});
		}
                cats.push(cat);
            }
        }
    },
    listGet = function () {
        return (cats);
    },
    selectedGet = function () {
        var cat, i, selected = [];
        for (i = 0; i < cats.length; i += 1) {
            cat = cats[i];
            if (cat.isSelected()) {
                selected.push(cat);
            }
        }
        return (selected);
    },
    search = function (args) {
        var cat, cats, i, query;
        query = args.query;
        cats = query.catsGet();
        if (!cats) {
            cats = selectedGet();
        }
        for (i = 0; i < cats.length; i += 1) {
            cat = cats[i];
            cat.search({query: query,
                        first: args.first,
                        last: args.last});
        }
        that.updateUpdateables({hint: 'search', query: query});
    },
    selectByIds = function (ids) {
        var cat, i, id;
        for (i = 0; i < cats.length; i += 1) {
            cat = cats[i];
            cat.select(false);
        }
        for (i = 0; i < ids.length; i += 1) {
            id = ids[i];
            cat = catGetById(id);
            cat.select(true);
        }
    };
    that.catGetById = catGetById;
    that.catGetByPos = catGetByPos;
    that.catsConfGet = catsConfGet;
    that.catsTreeConfGet = catsTreeConfGet;
    that.listGet = listGet;
    that.search = search;
    that.selectByIds = selectByIds;
    that.selectedGet = selectedGet;
    create();
    return (that);
};


var VKIndexCats = function (conf_arg) {
    var that = VKCats(conf_arg, 1), i, cats,
    search = function (args) {
        var cat, cats/*, i*/, query/*, cs = []*/, id;
        query = args.query;
        cats = query.catsGet();
        if (!cats) {
            cats = that.selectedGet();
        }
	/*
        for (i = 0; i < cats.length; i += 1) {
            cat = cats[i];
	    id = cat.id;
	    cs.push(id);
        }
	*/
        cat = that.catGetById('index');
        cat.search({query: query,
                    first: args.first,
                    last: args.last/*,
		    cs: cs*/});
        that.updateUpdateables({hint: 'search', query: query});
	/*
        for (i = 0; i < cats.length; i += 1) {
            cat = cats[i];
            that.updateUpdateables({hint: 'search', query: query});
        }
	*/
    }
    /*
    ,    
    hitsLengthGet = function () {
	var hits = hitsGet();
	return(null);
    }
    */
    ;
    that.search = search;
    return (that);
};


var VKCoins = function (conf) {
    var that = VK(conf),
    coinss,
    create = function () {
        coinss = {};
    },
    add = function (coins, vw) {
        var c;
        c = coinss[coins];
        if (c === null) {
            c = {active: vw, inactive: []};
            coinss[coins] = c;
            vw.update(that, {hint: "active"});
        }
        else {
            c.inactive.push(vw);
            vw.update(that, {hint: "inactive"});
        }
        // alert("add coin "+ coin);
    },
    remove = function (coins, vw) {
        // alert("remove coin "+ coins);
        var c, i;
        c = coinss[coins];
        if (c !== null) {
            if (c.active === vw) {
                c.active = c.inactive.shift();
                if (c.active === null) {
                    delete(coinss[coins]);
                }
                else {
                    c.active.update(that, {hint: "active"});
                }
            }
            else {
                for (i = 0; i < c.inactive.length; i += 1) {
                    if (c.inactive[i] === vw) {
                        c.inactive.splice(i, 1);
                        break;
                    }
                }
            }
        }
    };

    that.add = add;
    that.remove = remove;

    create();

    return (that);
};


var VKMat = function (conf_arg) {
    var that = VK(conf_arg),
    conf = conf_arg,
    mats = [],
    url2Mat = {
        "B": "book",
        "T": "periodical",
        "P": "olper",
        "O": "binary",
        "A": "article"
    },

    create = function () {
    },
    add = function (mat) {
        var i, found = false;
        for (i = 0; i < mats.length; i += 1) {         
            if (mat === mats[i]) {
                found = true;
                break;
            }
        }
        if (!found) {
            mats.push(mat);
            mats.sort();
            that.updateUpdateables({hint: "mat"});
        }
    },
    clear = function (mat) {
        if (mats.length > 0) {
            mats = [];
            that.updateUpdateables({hint: "mat"});
        }
    },
    matsFromUrlParam = function (param) {
        var i, id, mat, mats;
        mats = [];
        if ((param === null) || (param.length === 0)) {
            return (mats);
        }
        for (i = 0; i < param.length; i += 1) {
            id = param.substr(i, 1);
            mat = url2Mat[id];
            if (mat) {
                mats.push(mat);
            }
        }
        return (mats);
    },
    matsGet = function () {
        var i, mats2 = [];
        for (i = 0; i < mats.length; i += 1) {
            mats2.push(mats[i]);
        }
        return (mats2);
    },
    matsSet = function (mats2) {
        mats = mats2;
        that.updateUpdateables({hint: "mat"});
    },
/**/
    matsSelGet = function () {
        var i, matsSel = {};
        for (i = 0; i < mats.length; i += 1) {         
            matsSel[mats[i]] = true;
        }
        return (matsSel);
    },
/**/    
    remove = function (mat) {
        var i, found = false;
        for (i = 0; i < mats.length; i += 1) {         
            if (mat === mats[i]) {
                found = true;
                break;
            }
        }
        if (found) {
            mats.splice(i, 1);
            that.updateUpdateables({hint: "mat"});
        }
    };
    that.add = add;
    that.matsFromUrlParam = matsFromUrlParam;
    that.remove = remove;
    that.clear = clear;
    that.create = create;
    that.matsGet = matsGet;
    that.matsSet = matsSet;
    create();
    return (that);
};


var VKQuery = function (conf_arg) {
    var that = VK(conf_arg),
    conf = conf_arg,
    keys = null,
    vals = null,
    ops = null,
    mats = null,
    cats = null,
    fqs = null,
    mat2Url = {
        "book": "B",
        "periodical": "T",
        "olper": "P",
        "binary": "O",
        "article": "A"
    },

    normalize = function () {
        var i;
        for (i = 0; i < vals.length; i += 1) {
            if (vals[i] === "") {
                keys.splice(i, 1);
                vals.splice(i, 1);
                ops.splice(i, 1);
                i -= 1;
            }
        }
        if (i > 0) {
            if (ops.length > i - 1) {
                ops.splice(i - 1, ops.length - i + 1);
            }
        }
    },

    create = function () {
        keys = conf.keys;
        vals = conf.vals;
        ops = conf.ops;
        mats = conf.mats;
        cats = conf.cats;
	if (conf.fqs) {
            fqs = conf.fqs;
	}
        normalize();
    },

    displayStr = function (s) {
        var s2ds = { all: t("Überall"),
                     person: t("Person"),
                     title: t("Titel"),
                     subject: t("Schlagwort"),
                     id: t("Nummer"),
                     //index: "Index",
                     //description: "Zusatzinfos I und II",
                     //classification: "Systematik",
                     date: t("Jahr"),
                     and: t("und"),
                     or: t("oder"),
                     "and not": t("und nicht")};
        return (s2ds[s]);
    },

    equalArrays = function (a, b) {
        var i;
        if ((a !== null) && (b !== null)) {
            if (a.length !== b.length) {
                return (false);          
            }
            for (i = 0; i < a.length; i += 1) {
                if (a[i] !== b[i]) {
                    return (false);              
                }
            }
            return (true);
        }
        else if ((a === null) && (b === null)) {
            return (true);
        }
        else {
            return (false);
        }
    },

    catsGet = function () {
        return (cats);
    },

    equal = function (q_arg) {
        var q = q_arg.get();
        return (equalArrays(keys, q.keys) && equalArrays(vals, q.vals) && 
                equalArrays(mats, q.mats) && equalArrays(ops, q.ops) &&
                equalArrays(cats, q.cats) && equalArrays(fqs, q.fqs));
    },

    get = function () {
        return ({keys: keys, vals: vals, ops: ops, mats: mats, cats: cats, fqs: fqs});
    },

    // XSS-Lücke vermeiden:
    escapeHtml = function (str) {
	return str.replace(/&(?!amp;)/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') ;
    },

    asDisplayStringGet = function () {
        var i, mat, str, first = true;
        str = "";
        for (i = 0; i < vals.length; i += 1) {
            if (i === 0) {
                str = displayStr(keys[i]) + ': ( ' + escapeHtml(vals[i]) + ' )';
            }
            else {
                str = '( ' + str + ' ) ' + displayStr(ops[i - 1]) +
                    ' ( ' + displayStr(keys[i]) + ': ( ' + escapeHtml(vals[i]) + ' ) )';
            }
        }
        mat = that.matUrlParamGet();
        if (mat) {
            str += ', Mat: ' + mat;
        }
        /*
        str += ", "+cats.length+" Katalog";
        if (cats.length != 1) {
            str += "e";
        }
        */
        str += ", " + t('Katalog(e)') + ": ";
        for (i = 0; i < cats.length; i += 1) {
            if (first) {
                first = false;
            }
            else {
                str += ', ';
            }
            str += cats[i].nameShortGet();
        }
        // alert(str);
        return (str);
    },

    asStringGet = function () {
        var i, str;
        str = "";
        for (i = 0; i < vals.length; i += 1) {
            if (i === 0) {
                str = keys[i] + ': ( ' + vals[i] + ' )';
            }
            else {
                str = '( ' + str + ' ) ' + ops[i - 1] +
                      ' ( ' + keys[i] + ': ( ' + vals[i] + ' ) )';
            }
        }
        // alert(str);
        return (str);
    },

    matUrlParamGet = function () {
        var i, param = "";
        if (mats) {
            for (i = 0; i < mats.length; i += 1) {
                param += mat2Url[mats[i]];
            }
        }
        return (param);
    },

    asURLGet = function () {
        var i, isSimple = true, mat, q, url, fqss;
        url = "?";
        for (i = 0; i < vals.length; i += 1) {
            if (i === 0) {
                if (keys[0] === "all") {
                    q = encodeURIComponent(vals[i]);
                }
                else {
                    isSimple = false;
                }
            }
            else {
                isSimple = false;
                url += '&' + 'o' + (i - 1) + '=' + ops[i - 1];
                url += '&';
            }
            url += "k" + i + "=" + keys[i] + '&v' + i + "=" +
                encodeURIComponent(vals[i]);
        }
        if (mats.length > 0) {
            isSimple = false;
        }
        if (isSimple) {
            url = '?q=' + q;
        }
        else {
            mat = matUrlParamGet();
            if (mat) {
                url += '&mat=' + mat;
            }
        }
        for (i = 0; i < cats.length; i += 1) {
            url += '&' + 'c=' + cats[i].id;
        }
	/*
	if ($.isCombiSearch()) {
	    url += '&' + 'index=1';
	}
	*/

	if (fqs !== null) {
	    fqss = JSON.stringify(fqs);
            url += '&' + 'fqs=' + encodeURIComponent(fqss);	    
	}

        return (url);
    },

    isSimple = function () {
        var is = true;
        if (vals.length !== 1) {
            is = false;
        }
        else if (keys[0] !== "all") {
            is = false;
        }
        else if ((mats !== null) && (mats.length > 0)) {
            is = false;
        }
        return (is);
    },

    matsGet = function () {
        return (mats);
    },

    fqsGet = function () {
        return (fqs);
    };

    that.asDisplayStringGet = asDisplayStringGet;
    that.asStringGet = asStringGet;
    that.asURLGet = asURLGet;
    that.catsGet = catsGet;
    that.equal = equal;
    that.get = get;
    that.create = create;
    that.equal = equal;
    that.isSimple = isSimple;
    that.matsGet = matsGet;
    that.fqsGet = fqsGet;
    that.matUrlParamGet = matUrlParamGet;

    create();

    return (that);
};


var VKQueryHistory = function (conf_arg) {
    var that = VK(conf_arg),
    conf = conf_arg,
    queries = [],
    posSel = null,
    findQueryPos = function (q) {
        var i;
        for (i = 0; i < queries.length; i += 1) {
            if (queries[i].equal(q)) {
                return (i);
            }
        }
        return (-1);
    },
    add = function (query) {
        var p = findQueryPos(query);
        /*
        that.updateUpdateables({hint: "query-history"});
        */
        if (p > -1) {
            query = queries[p];
            posSel = p;
            // alert("gefunden");
            that.updateUpdateables({hint: "query-history", q: query,
                        pos: posSel});
        }
        else {      
            queries.push(query);
            posSel = queries.length - 1;
            // alert("nicht gefunden");
            that.updateUpdateables({hint: "query-history", q: query,
                        pos: posSel});
        }
        return (query);
    },
    create = function () {
    },
    findQuery = function (q) {
        var i;
        for (i = 0; i < queries.length; i += 1) {
            if (queries[i].equal(q)) {
                return (queries[i]);
            }
        }
        return (null);
    },
    queriesGet = function () {
        return (queries);
    },
    querySelectByPos = function (pos) {
        if ((0 <= pos) && (pos < queries.length)) {
            posSel = pos;
            that.updateUpdateables({hint: "query-history-select",
                        pos: pos});
        }
    },
    sel = function () {
        var q = null;
        if ((posSel !== null) && (queries.length)) {
            q = queries[posSel];
        }
        return (q);
    };
    that.add = add;
    that.findQuery = findQuery;
    that.create = create;
    that.queriesGet = queriesGet;
    that.querySelectByPos = querySelectByPos;
    that.sel = sel;
    create();
    return (that);
};


var VKSearcher = function (conf_arg) {
    var that = VK(conf_arg),
    conf = conf_arg,
    create = function () {
        // alert("VKSearcher create");
    },
    search = function (args) {
        var data, mat, q, fq, cs;
	q = args.query.asStringGet();
	fq = args.query.fqsGet();
	if (args.cs && (args.cs.length > 0)) {
	    cs = args.cs;
	}
        that.updateUpdateables({hint: 'searching'});
        data = { c: args.cat.id,
                 q: q,
                 qid: 1,
                 f: args.first - 1,
                 l: args.last - 1,
                 format: 'json'};
        mat = args.query.matUrlParamGet();
        if (mat) {
            data.mat = mat;
        }
        if (fq) {
            data.fq = fq;
        }
        if (cs) {
            data.cs = cs;
        }
        /*
        alert("Search for \""+args.query.asStringGet()+"\" in cat \""+
              args.cat.id+"\"");
        */
        $.ajax({url: conf.url,
                type: 'GET',
                dataType: 'json',
                data: data,
                success: function (hits) {
                    // alert("success cat "+args.cat.id+" "+hits.length);
                    /*
                    alert("success cat "+args.cat.id+" "+
                          hits.hits.length);
                    */
		    hits.q = q;
                    args.cat.hitsSet(hits);
                },
                error: function (xhr, status, exception) {
                    // alert('cat-'+args.cat.id+' error: "'+status+'"');
                    args.cat.errorSet({status: status,
                                          exception: exception});
                }}); 
    };
    that.search = search;
    create();
    return (that);
};


var opacUrlGet = function (hit) {
    var opac_url, opac_url_natde,
    natQuery = function (q) {
        return (q.replace('?', ' '));
    };
    if (hit.cat_id === 'teso') {
        opac_url = hit.opac_url;
        opac_url_natde = opac_url;
        opac_url_natde = opac_url_natde.replace(/\/\/gateway\.proquest\.com\//,
            '//gateway.proquest.com.proxy.nationallizenzen.de/');
        /*
        opac_url_natde = opac_url_natde.replace(/\/\/teso\.chadwyck\.co\.uk\//,
            '//teso.chadwyck.co.uk.proxy.nationallizenzen.de/');
        */
    }
    else if (hit.cat_id === 'nat_pao') {
        if (hit.ajId) {
            if (hit.id0.substr(3, 1) === "a") {
                // article: (Bsp. pioa400105080142)
                opac_url = 'http://gateway.proquest.com/openurl?' +
                'url_ver=Z39.88-2004&res_dat=xri:pao:' +
                '&rft_dat=xri:pao:article:' + hit.ajId;
                opac_url_natde = 
                'http://pao.chadwyck.co.uk.proxy.nationallizenzen.de/' +
                'articles/displayItemFromId.do?' +
                'QueryType=articles&ItemID=' + hit.ajId;
            }
            else if (hit.id0.substr(3, 1) === "z") {
                // journal: (Bsp. piozh372)
                opac_url = 'http://gateway.proquest.com/openurl?' +
                'url_ver=Z39.88-2004&res_dat=xri:pao:' +
                '&rft_dat=xri:pao:journal:' + hit.ajId;
                opac_url_natde = 
                'http://pao.chadwyck.co.uk.proxy.nationallizenzen.de/' +
                'journals/displayItemFromId.do?' +
                'QueryType=journals&ItemID=' + hit.ajId;
            }
        }
    }
    else if (hit.cat_id === 'nat_pio') {
        if (hit.ajId) {
            if (hit.id0.substr(3, 1) === "a") {
                // article: (Bsp. pioa400105080142)
                opac_url = 'http://gateway.proquest.com/openurl?' +
                'url_ver=Z39.88-2004&res_dat=xri:pio:' +
                '&rft_dat=xri:pio:article:' + hit.ajId;
                opac_url_natde =
                'http://pio.chadwyck.co.uk.proxy.nationallizenzen.de/' +
                'articles/displayItemFromId.do?' +
                'QueryType=articles&ItemID=' + hit.ajId;
            }
            else if (hit.id0.substr(3, 1) === "z") {
                // journal: (Bsp. piozh372)
                opac_url = 'http://gateway.proquest.com/openurl?' +
                'url_ver=Z39.88-2004&res_dat=xri:pio:' +
                '&rft_dat=xri:pio:journal:' + hit.ajId;
                opac_url_natde =
                'http://pio.chadwyck.co.uk.proxy.nationallizenzen.de/' +
                'journals/displayItemFromId.do?' +
                'QueryType=journals&ItemID=' + hit.ajId;
            }
        }
        else {
            /* ajId kann fuer PIO-Artikel nicht sicher aus den Daten ermittelt 
               werden:
            */
            if (hit.id0.substr(3, 1) === "a") {
                // article: (Bsp. pioah66100120015)

                opac_url = 'articles/executeSearch.do?Suchen=Suchen';
                if (hit.title) {
                    opac_url += '&searchTermTitle=' +
                        encodeURIComponent(natQuery(hit.title));
                }
                if (hit.author) {
                    opac_url += '&searchTermAuthor=' +
                        encodeURIComponent(hit.author);
                }
                if (hit.jtitle) {
                    opac_url += '&searchTermJnlTitle=' +
                        encodeURIComponent(hit.jtitle);
                }
                if (hit.date) {
                    opac_url += '&yearFrom=' +
                        encodeURIComponent(hit.date);
                }

                opac_url_natde = 
                'http://pio.chadwyck.co.uk.proxy.nationallizenzen.de/' +
                opac_url;
                opac_url = 'http://pio.chadwyck.co.uk/' + opac_url;
            }
            /* nicht noetig, da ajId fuer PIO-Zeitschriften sicher 
               aus den Daten (id0) erzeugt werden kann:
            else if (hit.id0.substr(3,1) == "z") {
                // journal: (Bsp. pioz6402)

                if (hit.title) {
                    opac_url = 'journals/executeSearch.do?Suchen=Suchen';
                    opac_url += '&searchTermJnlTitle=' +
                    encodeURIComponent(hit.title);

                    opac_url_natde = 
                    'http://pio.chadwyck.co.uk.proxy.nationallizenzen.de/'+
                    opac_url;
                    opac_url = 'http://pio.chadwyck.co.uk/'+opac_url;
                }
            }
            */
        }
    }
    else {
        opac_url = hit.opac_url || null;
    }
    return ({"opac_url": opac_url, "opac_url_natde": opac_url_natde});
};
