﻿var encode_chars_ = [
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!_",
	"liCDEIGHFJ1LMNOPQRST!VWXYZabcdefghB_kAmnopqrstuvwxyz0K23456789Uj"//to shoren skill code.
];
var encode_delimiter_ = "=";

var BIT_LAZY                = 0x800;
var BIT_PLAYER_LV           = 0x0FF;//下位8bit=最大LV256

function get64Strlen(max){
	var len = 1;
	if(max>Math.pow(2,18)){
		len = 4;
	}else if(max>Math.pow(2,12)){
		len = 3;
	}else if(max>Math.pow(2,6)){
		len = 2;
	}
	return len;
}
	
function n2s(n, max, lazy){
	var len = get64Strlen(max);
	var estr = "";
	for(var i=0;i<len;i++){
		var low = n&63;
		estr += encode_chars_[lazy].charAt(low);
		n >>>= 6;
	}
	return estr;
}
	
function numerTo64Str(n, lazy){
	//console.log("numerTo64Str(n=%d)", n);
	return n2s(n, n, lazy);
}
function toNumerFrom64Str(str, lazy){
	//console.log("toNumerFrom64Str(str=%s)", str);
	var n = 0;
	for(var i=0;i<str.length;i++){
		n += encode_chars_[lazy].indexOf(str.charAt(i))*Math.pow(2, 6*i);
	}
	return n;
}

function decode(scode){
	//console.log("decode(scode=%o)", scode);
	if(scode =="")return;
	var mf = $("mainform");
	var lazy = 0;
	var plv = toNumerFrom64Str(scode.substring(0,2), 0);//先頭2バイトはnon-lazy
	//lazy 1bit
	if(plv&BIT_LAZY){//先頭ビットが立っていたら
		lazy = 1;
		plv &= ~BIT_LAZY;
	}
	$("plv").value = plv;

	var dsp = toNumerFrom64Str(scode.substring(2,4), lazy);//2バイト
	$("dsp").value = dsp;
	
	var idx = 4;
	var len = 0;
	//quests
	len = getBooleanArrayLength(scode.charAt(idx), lazy);//str[idx]形式の記述はIEだとダメっぽい
	if(len==0){//全部OFF
		idx++;
	}else if(len==-1){//全部ON
		for(var i=0;i<mf.quest.length;i++){
			mf.quest[i].checked = true;
		}
		idx++;
	}else{
		var qq = codeToBooleanArray(scode, idx+1, len, lazy);
		for(var i=0;i<mf.quest.length&&i<qq.length;i++){
			mf.quest[i].checked = qq[i];
		}
		idx+=len+1;
	}
	//automaster
	len = getBooleanArrayLength(scode.charAt(idx), lazy);
	if(len==0){//全部OFF
		idx++;
	}else if(len==-1){//全部ON
		for(var i=0;i<mf.automaster.length;i++){
			mf.automaster[i].checked = true;
		}
		idx++;
	}else{
		var aa = codeToBooleanArray(scode, idx+1, len, lazy);
		for(var i=0;i<mf.automaster.length&&i<aa.length;i++){
			mf.automaster[i].checked = aa[i];
		}
		idx+=len+1;
	}
	//skills
	var ss = new Array();
	for(var i=idx;i<scode.length;i++){
		ss.push(toNumerFrom64Str(scode.charAt(i), lazy));
	}
	for(var i=0;i<ss.length&&i<mf.skills.length;i++){
		setSkillLevelOf(mf.skills[i], ss[i]);
	}
	q(mf);
	s(mf);
	return true;
}
function getBooleanArrayLength(ch, lazy){
	//console.log("getBooleanArrayLength(ch=%s)", ch);
	var len = toNumerFrom64Str(ch, lazy);
	if(len==63)return -1;
	return len;
}
function codeToBooleanArray(scode, from, len, lazy){
	var str = scode.substring(from, from+len);
	var aa = new Array();
	for(var i=0;i<str.length;i++){
		var b64 = toNumerFrom64Str(str.charAt(i), lazy);
		var base = 1;
		for(var b=0;b<6;b++){
			aa[i*6+b] = (b64&base)!=0;
			base*=2;
		}
	}
	return aa;
}
function encode(lazy){
	if(typeof lazy == "undefined"){
		lazy = 0;
	}else{
		lazy = lazy?1:0;//boolean->0/1
	}
	var plv = $F("plv");
	if(lazy){
		plv |= 0x800;
	}
	var pstr = n2s(plv, 4096, 0);//先頭はnon-lazy
	//console.log("plv :" + pstr);
	
	var dsp = $F("dsp");
	var dspstr = n2s(dsp, 4096, lazy);
	
	var qstr = "";
	var qq = document.getElementsByName("quest");
	qstr = checksToCodeStr(qq, lazy);
	//console.log("qstr:" + qstr);
	//console.log("qstr.length=" + qstr.length);
	
	var astr = "";
	var aa = document.getElementsByName("automaster");
	astr = checksToCodeStr(aa, lazy);
	//console.log("astr:" + astr);
	//console.log("astr.length=" + astr.length);
	
	var sstr = "";
	var ss = document.getElementsByName("skills");
	for(var i=0;i<ss.length;i++){//これはあるだけ
		sstr += n2s(ss[i].options[ss[i].selectedIndex].getAttribute("slv"), 63, lazy);
	}
	//console.log("sstr:" + sstr);
	//console.log("sstr.length=" + sstr.length);
	
	return pstr + dspstr + qstr + astr + sstr;
}

function checksToCodeStr(cc, lazy){
	var ret ="";
	var cca = $A(cc);
	//62セット=62*6bitまで対応
	//最初の一文字が0は全部OFF,63で全部ON，それ以外は文字列の長さ(6bit単位)
	if(cca.all(function(v,i){return v.checked;})){
		return encode_chars_[lazy].charAt(63);
	}else if(cca.all(function(v,i){return !v.checked;})){
		return  encode_chars_[lazy].charAt(0);
	}
	var len = 0;
	for(var i=0;i<cc.length;i+=6){//6bit単位で処理
		var v = 0;
		var base = 1;
		for(var j=i;j<i+6&&j<cc.length;j++){
			if(cc[j].checked)v += base;
			base*=2;
		}
		ret += n2s(v, base, lazy);
		len++;
	}
	var zero_char = encode_chars_[lazy].charAt(0);
	for(var i=ret.length-1;i>=0;i--){
		if(ret[i] == zero_char){//0ならフラグはすべてOFF→設定の必要なし
			ret = ret.substring(0, ret.length-1);
			len--;
			continue;
		}
		break;
	}
	return encode_chars_[lazy].charAt(len) + ret;//長さを付ける
}

