function talent_save() {
	var data = [[0, treeTalentPoint[0]],
		[1, treeTalentPoint[1]],
		[2, treeTalentPoint[2]]];
	for (var x=0; x<data.length-1; x++) {
		for (var y=0; y<data.length-x-1; y++) {
			if (data[y][1] < data[y+1][1]) {
				var temp = data[y];
				data[y] = data[y+1];
				data[y+1] = temp;
			}
		}
	}
	var num = (data[0][0]+1) * 2 - (data[1][0] < data[2][0] ? 1 : 0);

	var newPosition = talent_defrag(num);
	var mask = new Array();
	var mask2 = new Array();
	for (var x=0; x<newPosition.length; x++) {
		var id = newPosition[x];
		mask.push(pointTalent[id] >= talent[id][2] ? 1 : 0);
		if (pointTalent[id] > 0 && pointTalent[id] < talent[id][2]) {
			if (!pointTalent[id-1] || pointTalent[id-1] == 0 || pointTalent[id-1] >= talent[id-1][2])
				mask2.push(talent_charCode(x));
			mask2.push(pointTalent[id]);
		}
	}
	mask = mask.join(''); mask = mask.replace(/(0*)$/, '');
	mask = mask + "0000".substring(0, 4 - (mask.length + 4) % 5);
	var full_string = new Array();
	for (var x=0; x<mask.length; x+=5) {
		var code = parseInt(mask.substr(x, 5), 2);
		var str = talent_charCode(code);
		full_string.push(str);
	}

	
	var result = [num, full_string.join('')];
	if (mask2.length > 0) {
		result.push(0);
		result.push(mask2.join(''));
	}
	location.hash = '#' + result.join('');
	prompt('請復製以下網址', location.href);
}

function talent_defrag(num) {
	var temp = [new Array(), new Array(), new Array()];
	var treeId = [Math.floor((num-1)/2), num % 2 == 0 ? (num==6? 1 : 2) : (num==1? 1 : 0),
		num % 2 == 0 ? (num==2? 1 : 0) : (num==5 ? 1 : 2)];

	for (var x=0; x<talent.length; x++) temp[ talent[x][0] ].push(x);
	var result = temp[ treeId[0] ].concat( temp[ treeId[1] ], temp[ treeId[2] ]);
	return result;
}

function talent_charCode(code) {
	var result = new Array();
	do {
		var i = code % 52;
		result.push(String.fromCharCode(i > 25 ? 71 + i : 65 + i));
		code = (code-i) / 52;
	} while (code > 0);
	result = result.reverse();
	return result.join('');
}

function talent_code(val) {
	var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
	var result = 0;
	for (var x=0; x<val.length; x++) {
		var code = str.indexOf(val.substr(x, 1));
		if (code < 0) return -1;
		result += code * Math.pow(52, val.length - x - 1);
	}
	return result;
}

function talent_load() {
	var str = location.hash.substr(1); if (str < 1) return;
	var zeroPosition = str.indexOf('0');
	var data = [parseInt(str.substr(0,1))]; if(isNaN(data[0]) || data[0] < 1 || data[0] > 6) return;
	data.push(zeroPosition < 0 ? str.substr(1) : str.substring(1, zeroPosition));
	data.push(zeroPosition < 0 ? '' : str.substr(zeroPosition+1));

	var mask = new Array();
	for (var x=0; x<data[1].length; x++) {
		var code = talent_code(data[1].substr(x, 1)); if(code < 0) return;
		code = code.toString(2);
		mask.push("0000".substring(0, 4 - (code.length + 4) % 5));
		mask.push(code);
	}
	mask = mask.join('');

	var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
	var mask2 = new Array();
	var lastId = -1;
	for (var x=0; x<data[2].length; x++) {
		var point = parseInt(data[2].substr(x, 1));
		if (isNaN(point)) {
			var val = new Array();
			for (;x<data[2].length; x++) {
				var c = data[2].substr(x, 1);
				var s = str.indexOf(c);
				if (s < 0) break;
				val.push(c);
			}
			x--;

			lastId = talent_code(val.join(''));
		}
		else if (lastId < 0 || point > 5) return;
		else
			mask2.push([lastId++, point]);
	}


	var newPosition = talent_defrag(data[0]);
	var newPointTalent = new Array();
	var newTreeTalentPoint = [0, 0, 0];
	var newTreeDeepTier = [0, 0, 0];
	var newTierTalentPoint = [new Array(), new Array(), new Array()];
	var newPoints = PointsMax;

	for (var z=0; z < 3; z++)
		for (var x=0; x < tierNum; x++) newTierTalentPoint[z][x] = 0;
	for (var x=0; x<talent.length; x++) newPointTalent[x] = 0;

	for (var x=0; x<mask.length; x++) {
		var flag = parseInt(mask.substr(x, 1));
		if (flag > 0 && typeof(newPosition[x]) == 'undefined') return;
		var id = newPosition[x];
		newPointTalent[id] = flag ? talent[id][2] : 0;
	}

	for (var x=0; x<mask2.length; x++) newPointTalent[ newPosition[mask2[x][0]] ] = mask2[x][1];

	for (var x=0; x<newPointTalent.length; x++) {
		if (newPointTalent[x] > 0) {
			newTreeDeepTier[ talent[x][0] ] = Math.max(newTreeDeepTier[ talent[x][0] ], talent[x][4]);
			newTreeTalentPoint[ talent[x][0] ] += newPointTalent[x];
			newTierTalentPoint[ talent[x][0] ][ talent[x][4]-1 ] += newPointTalent[x];
		}
	}

	for (var z=0; z < 3; z++){
		var talent_text = document.getElementById('talent_tree' + (z+1) + '_text');
		talent_text.innerHTML = treeName[z] + ': ' + newTreeTalentPoint[z];

		for (var x=0; x < tierNum-1; x++) {
			newTierTalentPoint[z][x] += newTierTalentPoint[z][x-1];
			if (newTierTalentPoint[z][x] < tierRequestPoint * (x+1) && x < newTreeDeepTier[z]-1) return;
		}
	}

	for (var x=0; x<talent.length; x++) {
		if (newPointTalent[x] > 0) {
			if (talent[x][5] && newPointTalent[ talent[x][5][0] ] < talent[x][5][1]) return;
			newPoints -= newPointTalent[x];
		}
	}
	if (newPoints < 0 && (!petCalculator_boundOfPoints || newPoints < -5)) return;
	if (newPoints < 0) {
		var boundOfPoints = document.getElementById('boundOfPoints');
		boundOfPoints.checked = true;
		newPoints += 5;
		PointsMax += 5;
		levelMin -= 5 * levelOfEveryPoint;
	}

	pointTalent = newPointTalent;
	treeTalentPoint = newTreeTalentPoint;
	treeDeepTier = newTreeDeepTier;
	tierTalentPoint = newTierTalentPoint;
	Points = newPoints;

	for (var x=0; x<talent.length; x++) {
		var obj = document.getElementById('talent_' + x);
		var textObj = obj.getElementsByTagName('div')[1];
		var flag1 = pointTalent[x] > 0 || Math.floor(treeTalentPoint[ talent[x][0] ]/tierRequestPoint)+1 >= talent[x][4] && Points > 0;
		var flag2 = !talent[x][5] || pointTalent[ talent[x][5][0] ] >= talent[x][5][1];

		textObj.innerHTML = pointTalent[x] + '/' + talent[x][2];
		if (pointTalent[x] >= talent[x][2]) talent_full(obj);
		else if (flag1 && flag2) talent_available(obj);
		else talent_disable(obj);

		if (flag1 || flag2) refreshTalentTooltip(x);
		if (flag1) refreshTalentArrow(x);
	}

	refreshInformationBar();

	if (petCalculator_loading) petCalculator_loading();
}