var Drivecart = function() {};

// Set from locallang
Drivecart.labels = {}; 

// Set from TypoScript
Drivecart.rebuildOnUpdate = 0; 
Drivecart.exec = {};

Drivecart.checkjQuery = function() {
	if ( typeof(jQuery) != "undefined" ) return true;
	alert(Drivecart.labels.error_jQueryNotInstalled);
}

Drivecart.lock = {};

Drivecart.add = function(ref, count, params) { this.doRequest( 'add', ref, count, params ); }
Drivecart.edit = function (ref, count, params) { this.doRequest( 'edit', ref, count, params ); }
Drivecart.remove = function (ref) { this.doRequest( 'remove', ref ); }
Drivecart.clear = function() { this.doRequest( 'clear' ); }

Drivecart.doRequest = function (action, ref, count, params) {
	if ( !this.checkjQuery() ) return;
	if ( this.isLockActive() ) return;
	this.lock.request = 1;

	var response = $.getJSON("",
		{
			'eID':'tx_drivecart_ajax',
			'data[action]': action,
			'data[ref]': ref ? ref : '',
			'data[count]': count ? count : '',
			'data[params]': params ? this.serialize(params) : '',
			'sr' : Math.random() // Anti-IE caching issue
		}, 
		function (data) {
			delete Drivecart.lock.request;
			if ( !data || typeof(data) != 'object' || !data.success ) Drivecart.doError(data);
			if (Drivecart.exec) { Drivecart.execUserFunc(data, action); }
			Drivecart.execAfterUpdate();
			if (Drivecart.rebuildOnUpdate) { Drivecart.rebuild(); }
		}
	);
}

Drivecart.isLockActive = function() {
	for (i in Drivecart.lock) return true;
	return false;
}

Drivecart.doError = function(data){
	if ( !data || typeof(data) != 'object' ) alert(Drivecart.labels.error_unknown);
	else if ( !data.success ) {
		if ( data.error ) alert(data.error)
		else if ( data.errorLabel ) {
			error = Drivecart.labels[data.errorLabel]
			alert(error?error:data.errorLabel)
		}
		else alert( Drivecart.labels.error_unknown )
	} else {
		alert(Drivecart.labels.error_fail)
	}
}

Drivecart.rebuild = function() {
	Drivecart.lock.rebuild = 1;
	rebuildRequest = new Array();
	if ($("#tx_drivecart_pi1_fullview").length) rebuildRequest.push('fullview');
	if ($("#tx_drivecart_pi1_briefview").length) rebuildRequest.push('briefview');
	if ( rebuildRequest.length ) drivecart_rebuild(rebuildRequest, 'Drivecart.execAfterRebuild();');
	else Drivecart.execAfterRebuild();
}

Drivecart.addAfterRebuild = function( funcRef ){
	this.addExecFunction('AfterRebuild', funcRef );
}

Drivecart.addAfterUpdate = function( funcRef ){
	this.addExecFunction('AfterUpdate', funcRef );
}

Drivecart.addExecFunction = function( event, funcRef ) {
	var key = 'exec' + event + 'Functions';
	if (!this[key]) this[key] = [];
	this[key].push(funcRef);
}

Drivecart.execAfterRebuild = function() {
	delete Drivecart.lock.rebuild
	this.execFunction('Rebuild');
}

Drivecart.execAfterUpdate = function() {
	this.execFunction('Update');
}

Drivecart.execFunction = function( event ) {
	var key = 'execAfter' + event + 'Functions';
	if ( this[key] ) {
		for (i in this[key] ) {
			if (typeof(this[key][i]) == 'function' ) this[key][i]();
		}
	}
}

Drivecart.addUserFunc = function(action, funcRef) {
	if ( !Drivecart.exec[action] ) Drivecart.exec[action] = new Array();
	Drivecart.exec[action].push(funcRef);
}

Drivecart.execUserFunc = function(data, action){
	Drivecart.lock.execUserFunc = 1;
	var keepLock = 0;
	if ( funcs = Drivecart.exec[action] ) {
		for ( i in funcs ) {
			var userFunc = undefined;
			try { userFunc = eval(funcs[i]); } catch(e) { alert(e) }
			if ( i < funcs.length && typeof(userFunc) == 'function') {
				userFunc(data, action);
			}
		}
	}
	delete Drivecart.lock.execUserFunc;
}


Drivecart.serialize = function( mixed_value ) {
    var _getType = function( inp ) {
        var type = typeof inp, match;
        var key;
        if (type == 'object' && !inp) {
            return 'null';
        }
        if (type == "object") {
            if (!inp.constructor) {
                return 'object';
            }
            var cons = inp.constructor.toString();
            if (match = cons.match(/(\w+)\(/)) {
                cons = match[1].toLowerCase();
            }
            var types = ["boolean", "number", "string", "array"];
            for (key in types) {
                if (cons == types[key]) {
                    type = types[key];
                    break;
                }
            }
        }
        return type;
    };
    var type = _getType(mixed_value);
    var val, ktype = '';
 
    switch (type) {
        case "function": 
            val = ""; 
            break;
        case "undefined":
            val = "N";
            break;
        case "boolean":
            val = "b:" + (mixed_value ? "1" : "0");
            break;
        case "number":
            val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
            break;
        case "string":
            val = "s:" + mixed_value.length + ":\"" + mixed_value + "\"";
            break;
        case "array":
        case "object":
            val = "a";
            var count = 0;
            var vals = "";
            var okey;
            var key;
            for (key in mixed_value) {
                ktype = _getType(mixed_value[key]);
                if (ktype == "function") { 
                    continue; 
                }
 
                okey = (key.match(/^[0-9]+$/) ? parseInt(key) : key);
                vals += Drivecart.serialize(okey) +
                        Drivecart.serialize(mixed_value[key]);
                count++;
            }
            val += ":" + count + ":{" + vals + "}";
            break;
    }
    if (type != "object" && type != "array") val += ";";
    return val;
}
