function IsButton(e) {
    var i = null;
    if (e.target && e.target != null && e.target != 'undefined') {
        i = e.target;
    }
    if (e.srcElement && e.srcElement != null && e.srcElement != 'undefined') {
        i = e.srcElement;
    }
    if (i == null) {
        return false;
    }
    if (!i.lay || i.lay == null || i.lay == 'undefined') {
        return false;
    }
    if (i.lay.button == 0) {
        return false;
    }
    if (i.ava.paused == 1) {
        i.ava.paused = 0;
        if (i.ava.pausedDefault) {
            i.src = i.ava.root + i.lay.srcInactive;
        }
        else {
            i.src = i.ava.root + i.lay.src;
        }
    }
    else if (i.ava.paused == 0) {
        i.ava.paused = 1;
        if (i.ava.pausedDefault) {
            i.src = i.ava.root + i.lay.src;
        }
        else {
            i.src = i.ava.root + i.lay.srcInactive;
        }
    }
    //alert(i.id + " paused=" + i.ava.paused);
    return true;
}
function Avatar(avaID, root, x, y, w, h, paused, lays) {
    this.avaID = avaID;
    this.root = root;
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.pausedDefault = paused;
    this.paused = paused;
    //Sort(lays);
    this.lays = lays;

    this.numLays = lays.length;
    this.render = RenderAvatar;

    this.doc = null;
    this.ctxMergeTo = null;

    this.rndNum = new Array();
}
function Sort(lays) {
	for (var inc = 3; inc > 0; inc-=2)
	{
		var ll = lays.length;
		for (var i = 0; i < ll; i++)
		{
			var j = i;
			var lay = lays[i];
			while (j >= inc && lays[j - inc].z < lay.z)
			{
				lays[j] = lays[j - inc];
				j = j - inc;
			}
			lays[j] = lay;
		}
	}
}
function Layer(layID, src, z, x, y, w, h, button, srcInactive, anim) {
    this.layID = layID;
    this.src = src;
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.z = z;
    this.button = button;
    this.srcInactive = srcInactive;
    this.anim = anim;
    this.ax = x;
    this.ay = y;

    this.img = null;

    this.div = null;
}
function Animation(x,y,seq,path) {
	var seqA = new Array();
	var seqT = new StringTokenizer(seq, ',');
	var seqI = 0;
	while (HasMoreTokens(seqT)) {
		seqA[seqI] = NextToken(seqT);
		++seqI;
	}

	this.seqFunc = new Array(seqA.length);
	this.seqN = new Array(seqA.length);
	this.seqI = new Array(seqA.length);

	var lastI = 0;
	var sl = seqA.length;
	for (var i = 0; i < sl; i++) {
		var v = Trim(seqA[i]);
		var hasN = false;
		if (StartsWith(v, "P")) {
			this.seqFunc[i] = 0;
			v = v.substring(1, v.length);
			hasN = true;
		}
		else if (StartsWith(v, "R")) {
			this.seqFunc[i] = 1;
			v = v.substring(1, v.length);
			hasN = true;
		}
		else {
			this.seqFunc[i] = 0;
			this.seqN[i] = 1;
		}
		var t = new StringTokenizer(v, " ");
		if (hasN) {
			if (HasMoreTokens(t)) {
				var nt = NextToken(t);
				var nti = MakeIntSafe(nt);
				this.seqN[i] = nti;
			}
			else {
				this.seqN[i] = 1;
			}
		}
		if (HasMoreTokens(t)) {
			var nt = NextToken(t);
			var nti = MakeIntSafe(nt);
			lastI = nti;
		}
		this.seqI[i] = lastI;
	}

   	var pathA = new Array();
	var pathT = new StringTokenizer(path, ',');
	var pathI = 0;
	while (HasMoreTokens(pathT)) {
		pathA[pathI] = NextToken(pathT);
		++pathI;
	}

	this.pathFunc = new Array(pathA.length);
	this.pathN = new Array(pathA.length);
	this.pathX = new Array(pathA.length);
	this.pathY = new Array(pathA.length);
	this.pathStartX = new Array(pathA.length);
	this.pathStartY = new Array(pathA.length);

	var lastX = x;
	var lastY = y;
	var pl = pathA.length;
	for (var i = 0; i < pl; i++) {
		this.pathStartX[i] = lastX;
		this.pathStartY[i] = lastY;
		var v = Trim(pathA[i]);
		var hasN = false;
		if (StartsWith(v, "P")) {
			this.pathFunc[i] = 0;
			v = v.substring(1, v.length);
			hasN = true;
		}
		else if (StartsWith(v, "R")) {
			this.pathFunc[i] = 1;
			v = v.substring(1, v.length);
			hasN = true;
		}
		else {
			this.pathFunc[i] = 0;
			this.pathN[i] = 1;
		}
		var t = new StringTokenizer(v, " ");
		if (hasN) {
			if (HasMoreTokens(t)) {
				this.pathN[i] = MakeIntSafe(NextToken(t));
			}
			else {
				this.pathN[i] = 1;
			}
		}
		if (HasMoreTokens(t)) {
			lastX = MakeIntSafe(NextToken(t));
		}
		if (HasMoreTokens(t)) {
			lastY = MakeIntSafe(NextToken(t));
		}
		if (this.pathN[i] < 2) {
			this.pathStartX[i] = lastX;
			this.pathStartY[i] = lastY;
		}
		this.pathX[i] = lastX;
		this.pathY[i] = lastY;
	}

	this.seqIdx = 0;
	this.seqFuncIdx = 0;
	this.seqFuncLen = 0;

	this.pathIdx = 0;
	this.pathFuncIdx = 0;
	this.pathFuncLen = 0;
}
function StringTokenizer(string, sep) {
	this.i = 0;
	this.string = string;
	this.sep = sep;
}
function HasMoreTokens(tokenizer) {
	return (tokenizer.string.length > 0);
}
function NextToken(tokenizer) {
	var i = tokenizer.string.indexOf(tokenizer.sep);
	var token = "";
	if (i < 0) {
		token = tokenizer.string;
		tokenizer.string = "";
	}
	else {
		token = tokenizer.string.substring(0, i);
		tokenizer.string = tokenizer.string.substring(i + 1);
	}
	return token;
}
function Trim(s) {
	while (StartsWith(s, ' ')) {
		s = s.substring(1);
	}
	while (EndsWith(s, ' ')) {
		s = s.substring(0, s.length-1);
	}
	return s;
}
function StartsWith(string, character) {
	var i = string.indexOf(character);
	return (i == 0);
}
function EndsWith(string, character) {
	var i = string.lastIndexOf(character);
	return (i == string.length-1);
}
function MakeIntSafe(val){
	var numbers = "-0123456789";
	if (val == null || val.length < 1) {
		return 0;
	}
	var vl = val.length;
	for (var i = 0; i < vl; i++) {
		if (numbers.indexOf(val.charAt(i)) < 0) {
			return 0;
		}
	}
	return parseInt(val);
}
function GetRndNum(ava, n) {
	var r = ava.rndNum[n];
	if (!r || r == null || r == "undefined") {
		r = Math.round((Math.random()*n)+1);
		ava.rndNum[n] = r;
	}
	return r;
}
function UpdAnim(increment, ava, lay) {
	var anim = lay.anim;
	if (anim && anim != null && anim != "undefined") {
        var seqLen = anim.seqFunc.length;
        if (seqLen > 0) {
            var seqFunc = anim.seqFunc[anim.seqIdx];
            var seqN = anim.seqN[anim.seqIdx];
            var newSeqIdx = 0;
            if (increment == -1) {
                newSeqIdx = 1;
            }

            var seqFuncLen = seqN;
            if (seqFunc == 1) {
                seqFuncLen = anim.seqFuncLen;
                if (newSeqIdx == 1) {
                    seqFuncLen = GetRndNum(ava, seqN);
                }
            }
            anim.seqFuncLen = seqFuncLen;

            if (increment == 1) {
                newSeqIdx = SeqInc(anim);
                if (newSeqIdx == 1) {
                    seqFunc = anim.seqFunc[anim.seqIdx];
                    seqN = anim.seqN[anim.seqIdx];

                    seqFuncLen = seqN;
                    if (seqFunc == 1) {
                        seqFuncLen = anim.seqFuncLen;
                        if (newSeqIdx == 1) {
                            seqFuncLen = GetRndNum(ava, seqN);
                        }
                    }
                    anim.seqFuncLen = seqFuncLen;
                }
            }  
        }

        var pathLen = anim.pathFunc.length;
		if (pathLen > 0) {
			var pathFunc = anim.pathFunc[anim.pathIdx];
			var pathN = anim.pathN[anim.pathIdx];
			var newPathIdx = 0;
			if (increment == -1) {
				newPathIdx = 1;
			}

			var pathFuncLen = pathN;
			if (pathFunc == 1) {
				pathFuncLen = anim.pathFuncLen;
				if (newPathIdx == 1) {
					pathFuncLen = GetRndNum(ava, pathN);
				}
			}
			anim.pathFuncLen = pathFuncLen;

			if (increment == 1) {
				newPathIdx = PathInc(anim);
				if (newPathIdx == 1) {
					pathFunc = anim.pathFunc[anim.pathIdx];
					pathN = anim.pathN[anim.pathIdx];

					pathFuncLen = pathN;
					if (pathFunc == 1) {
						pathFuncLen = anim.pathFuncLen;
						if (newPathIdx == 1) {
							pathFuncLen = GetRndNum(ava, pathN);
						}
					}
					anim.pathFuncLen = pathFuncLen;
		    	}
			}
		}
	}
}
function SeqInc(anim) {
	var seqNewIdx = 0;
	++anim.seqFuncIdx;
	if (anim.seqFuncIdx >= anim.seqFuncLen) {
		++anim.seqIdx;
		anim.seqFuncIdx = 0;
		seqNewIdx = 1;

		if (anim.seqIdx >= anim.seqFunc.length) {
			anim.seqFuncIdx = 0;
			anim.seqIdx = 0;
		}
	}
	return seqNewIdx;
}
function PathInc(anim) {
	var pathNewIdx = 0;
	++anim.pathFuncIdx;
	if (anim.pathFuncIdx >= anim.pathFuncLen) {
		++anim.pathIdx;
		anim.pathFuncIdx = 0;
		pathNewIdx = 1;

		if (anim.pathIdx >= anim.pathFunc.length) {
			anim.pathFuncIdx = 0;
			anim.pathIdx = 0;
		}
	}
	return pathNewIdx;
}
function CalcPathPt(lay) {
	var anim = lay.anim;
	if (anim && anim != null && anim != "undefined" && anim.pathFuncLen > 0) {
		var idx = anim.pathIdx;
		var pathStartX = anim.pathStartX[idx];
		var pathStartY = anim.pathStartY[idx];
		var dist = (anim.pathFuncIdx+1) / anim.pathFuncLen;
		lay.ax = Math.round(pathStartX + ((anim.pathX[idx] - pathStartX) * dist));
		lay.ay = Math.round(pathStartY + ((anim.pathY[idx] - pathStartY) * dist));
	}
	else {
		lay.ax = lay.x;
		lay.ay = lay.y;
	}
}
function AnimateAvatars(ctx) {
	if (ctx == null) {
		return;
	}
	var cl = ctx.length;
	for (var i = 0; i < cl; i++) {
        var ava = ctx[i];
        if (ava == null) {
            continue;
        }
        if (ava.paused == 1) {
            continue;
        }
        if (ava.doc != null) {
            ava.rndNum = new Array();

            var lays = ava.lays;
			var ll = lays.length;
			for (var j = 0; j < ll; j++) {
				var lay = lays[j];
				var anim = lay.anim;
				if (anim && anim != null && anim != "undefined" && (anim.seqFunc.length > 0 || anim.pathFunc.length > 0)) {
					var div = lay.div;
					if (div == null) {
						div = ava.doc.getElementById(lay.layID);
						lay.div = div;
					}
					if (div != null) {
						CalcPathPt(lay);
						var ax = lay.ax;
						var ay = lay.ay;
						var x = ax;
						var y = ay;
						if (x < ava.x) {
							x = ava.x;
						}
						if (y < ava.y) {
							y = ava.y;
						}
						var x2 = ax + lay.w;
						var clipx2 = ava.x + ava.w;
						if (x2 > clipx2) {
							x2 = clipx2;
						}
						var y2 = ay + lay.h;
						var clipy2 = ava.y + ava.h;
						if (y2 > clipy2) {
							y2 = clipy2;
						}
						var idx = 0;
						if (anim && anim != null && anim != "undefined" && anim.seqFunc.length > 0) {
							idx = anim.seqI[anim.seqIdx];
						}
						var off = idx * lay.w;
						var clip =
								"rect(" +
								(y - ay) +
								"," +
								(x2 - ax + off) +
								"," +
								(y2 - ay) +
								"," +
								(x - ax + off) +
								")";
						var left = (ax - ava.x - off);
						var top = (ay - ava.y);
						var style = div.style;
						style.clip = clip;
						style.left = left;
						style.top = top;
					}
					UpdAnim(1, ava, lay);
				}
			}
		}
	}
}
function DisplayAvatars(doc, ctx) {
	if (ctx == null) {
		return;
	}
	var cl = ctx.length;
	for (var i = 0; i < cl; i++) {
        var ava = ctx[i];
        if (ava != null) {
            DisplayAvatar(doc, ava);
        }
    }
}
function DisplayAvatar(doc, ava, ctxMergeTo) {
	//alert(ava.avaID);
	ava.doc = doc;
    ava.crxMergeTo = ctxMergeTo;

    var div = doc.getElementById(ava.avaID);
	if (div != null) {
		var html = "";
		var lays = ava.lays;
		var ll = lays.length;
		for (var i = 0; i < ll; i++) {
			var lay = lays[i];
			UpdAnim(-1, ava, lay);
			CalcPathPt(lay);
			var x = lay.ax;
			var y = lay.ay;
			if (x < ava.x) {
				x = ava.x;
			}
			if (y < ava.y) {
				y = ava.y;
			}
			var x2 = lay.ax + lay.w;
			var clipx2 = ava.x + ava.w;
			if (x2 > clipx2) {
				x2 = clipx2;
			}
			var y2 = lay.ay + lay.h;
			var clipy2 = ava.y + ava.h;
			if (y2 > clipy2) {
				y2 = clipy2;
			}
			var idx = 0;
			var anim = lay.anim;
			if (anim && anim != null && anim != "undefined") {
				//alert(anim);
				idx = anim.seqI[anim.seqIdx];
			}
			var off = idx * lay.w;
			var src = "";
			if (lay.src.substring(0,1) == '/') {
				src = lay.src;
			}
			else {
				src = ava.root + lay.src;
			}
            var cursor = "";
            if (lay.button == 1) {
                cursor = " cursor: pointer;";
            }
            html +=
				"<div id='" +
				lay.layID +
                "' style='position: absolute; left: " +
				(lay.ax - ava.x - off) +
				"px; top: " +
				(lay.ay - ava.y) +
				"px; width: " +
				(lay.w) +
				"px; height: " +
				(lay.h) +
				"px; z-index: " +
				(lay.z) +
				"; visibility: hidden;" +
                cursor +
                " clip: rect(" +
				(y - lay.ay) +
				"," +
				(x2 - lay.ax + off) +
				"," +
				(y2 - lay.ay) +
				"," +
				(x - lay.ax + off) +
				");'>" +
				"<img id='i_" +
				lay.layID +
				"' src='" +
				src +
				"'>" +
				"</div>";
		}
		div.innerHTML = "";
		div.innerHTML = html;
		//alert(div.innerHTML);
	}

	var lays = ava.lays;
	var ll = lays.length;
	for (var j = 0; j < ll; j++) {
		var lay = lays[j];
		lay.img = doc.getElementById("i_"+lay.layID);
		lay.img.finished = false;
		lay.img.ava = ava;
        lay.img.lay = lay;
        lay.img.onload = OnAvatarImageLoaded;
		lay.img.onerror = OnAvatarImageError;
		lay.img.onabort = OnAvatarImageError;
    }
}
function OnAvatarImageLoaded() {
	if (this.finished == true || this.ava.numLays <= 0) {
		return;
	}
	this.finished = true;
	--this.ava.numLays;
	if (this.ava.numLays <= 0) {
		this.ava.render();
	}
}
function OnAvatarImageError() {
	if (this.finished == true || this.ava.numLays <= 0) {
		return;
	}
	this.finished = true;
}
function RenderAvatar() {
	//alert(this.avaID);
	var div = this.doc.getElementById(this.avaID);
	var divChildren = div.getElementsByTagName("div");
	var dcl = divChildren.length;
	for (var i = 0; i < dcl; i++) {
		var d = divChildren.item(i);
		d.style.visibility = "visible";
	}
    var ctx = this.ctxMergeTo;
    if (ctx != null) {
        var cl = ctx.length;
        for (var i = 0; i < cl; i++) {
            if (ctx[i] == null) {
                ctx[i] = this;
                return;
            }
        }
        ctx[ctx.length] = this;
    }
    //alert(div.innerHTML);
}
