function createYpwCookie()
{
	return new JCookie("YourPassword", 30);
}

var onSubmitYpwParameters = function()
{
	var codeTable = parseAbstractString("A-Za-z0-9");

	var code_A = "A".charCodeAt(0);
	var code_Z = "Z".charCodeAt(0);
	var code_a = "a".charCodeAt(0);
	var code_z = "z".charCodeAt(0);
	var code_space = " ".charCodeAt(0);

	var g = function(id) {return document.getElementById(id);};

	return function(form)
	{
		var seeds = new Array(); // 乱数生成の種

		// Reserved values Info.
		var reservedElements = myDocument.getElementsById(
			new RegExp("^ypwReservedParameter([0-9]+)$"), g("ypwParameters"));

		// [1] Name
		do {
			var nameStringValue = g("ypwName").value;

			if (nameStringValue.length == 0) {
				seeds.push(-1);
				break;
			}

			for (var i = 0, n = nameStringValue.length; i < n; ++i) {
				var code = nameStringValue.charCodeAt(i);
				if (0) {
				} else if (code_a <= code && code <= code_z) {
					seeds.push(code + code_A - code_a);
				} else if (code == code_space) {
					// DONOTHING
				} else {
					seeds.push(code);
				}
			}
		} while (false);

		// [2] Sex
		seeds.push(parseInt(g("ypwSex").value));

		// [3] Blood Type
		seeds.push(parseInt(g("ypwBloodType1").value));
		seeds.push(parseInt(g("ypwBloodType2").value));

		// [4] Date
		seeds.push(parseInt(g("ypwYear").value));
		seeds.push(parseInt(g("ypwMonth").value));
		seeds.push(parseInt(g("ypwDay").value));

		// [5] Word
		do {
			var wordStringValue = g("ypwWord").value;

			if (wordStringValue.length == 0) {
				seeds.push(-1);
				break;
			}

			for (var i = 0, n = wordStringValue.length; i < n; ++i) {
				var code = wordStringValue.charCodeAt(i);
				if (0) {
				} else if (code_a <= code && code <= code_z) {
					seeds.push(code + code_A - code_a);
				} else if (code == code_space) {
					// DONOTHING
				} else {
					seeds.push(code);
				}
			}
		} while (false);

		// [6] Length
		var passwordLength = parseInt(g("ypwLength").value);
		seeds.push(passwordLength);

		// [7]-[27] Reserved Value
		{
			for (var i = 0, n = reservedElements.length; i < n; ++i) {
				var e = reservedElements[i];
				if (e.value !== "") {
					// ERROR
					window.errorMessage("Internal Error!");
					return false;
				}
				seeds.push(-1);
			}
		}

		{
			var prng1 = function(MT) {
				for (var i = 0; i < 512; ++i) MT.nextInteger(); // 捨てる
				return function() {
					return MT.nextFloat();
				}
			}(new MersenneTwister(seeds));

			var prng2 = function(MT) {
				for (var i = 0; i < 512; ++i) MT.nextInteger(); // 捨てる
				return function() {
					return MT.nextFloat();
				}
			}(new MersenneTwister(seeds));

			var prng3 = function(MT) {
				for (var i = 0; i < 512; ++i) MT.nextInteger(); // 捨てる
				return function() {
					return MT.nextFloat();
				}
			}(new MersenneTwister(seeds));

			var pw1 = createRandomString(codeTable, passwordLength, prng1);
			var pw2 = createSafetyPassword(passwordLength, prng2);
			var pw3 = createSecure2Password(passwordLength, prng3);

			g("ypwPassword1").value = pw1;
			g("ypwPassword2").value = pw2;
			g("ypwPassword3").value = pw3;

			var getHintString = function(MT) {
				return function(pw) {
					var rem = "";
					for (var i = 0, l = pw.length; i < l; ++i) {
						rem += " " + adjustText(getHint(pw.charAt(i), MT));
					}
					return rem.substring(1);
				}
			}(new MersenneTwister(seeds));

			g("remainder1").innerHTML = getHintString(pw1);
			g("remainder2").innerHTML = getHintString(pw2);
			g("remainder3").innerHTML = getHintString(pw3);
		}

		var userParameters = createYpwCookie();
		archiveYpwParameters(userParameters, true);

		// Parameters
		{
			var planeParams = "20081206_" + reservedElements.length + "_"
				+ userParameters.paramString();
			var lineParams = "";
			for (var i = 0, n = planeParams.length; i < n; ++i) {
				var code = planeParams.charCodeAt(i);
				lineParams += "+" + (code + i);
			}
			g("ypwAllParameter").value = lineParams.substring(1);
		}

		// Cookie
		{
			if (g("ypwSaveParameters").checked) {
				// save cookie
				userParameters.store();
			} else {
				// remove cookie
				userParameters.remove();
			}
		}

		return false;
	}
}();

function setDescription()
{
	var g = function(id) {return document.getElementById(id);};

	g("nameLabel").title = "あなたの名前もしくはあなたにとって特別な名前を入力します．大文字・小文字は区別されず，空白文字は無視されます．";
	g("sexLabel").title = "それが性別を持つなら入力します．Mele=男性，Femele=女性です．";
	g("bloodTypeLabel").title = "それが血液型を持つなら入力します．ほとんどの人はRH+です．";
	g("dateLabel").title = "あなたにとって特別な日を入力します．ほとんどの人は，生年月日を入力します．";
	g("wordLabel").title = "あなたにとって特別な言葉，単語，文字，番号を入力します．作成するパスワードに関連する文字列でも良いでしょう．";
	g("lengthLabel").title = "生成するパスワードの長さを選択します．長いパスワードほど安全です．";
	g("saveParametersLebel").title = "チェックがONのとき，設定情報をクッキーに保存します．チェックOFFのとき，クッキーを削除します．クッキー保存/削除は，チェックON⇔OFFまたは[Generate Password !]をクリックのタイミングです．保存したクッキーは30日間保持されます．";
	g("ypwAllParameter").title = "入力した情報を符合化したものです．保存しておくと良いことがあるかも知れませんし，ないかも知れません．";
	g("password1Label").title = g("ypwPassword1").title = "あなたが入力した情報をもとに，ランダムに選ばれた文字を並べて生成されたパスワードです．";
	g("password2Label").title = g("ypwPassword2").title = "あなたが入力した情報をもとに生成された，中レベルのセキュリティを持つパスワードです．";
	g("password3Label").title = g("ypwPassword3").title = "あなたが入力した情報をもとに生成された，高レベルのセキュリティを持つパスワードです．";
}

/// http://www002.upp.so-net.ne.jp/mmw2/dfm/das.html
var getHint = function()
{
	var x = {};

	x["0"] = ["zero"];
	x["1"] = ["one"];
	x["2"] = ["two"];
	x["3"] = ["three"];
	x["4"] = ["four"];
	x["5"] = ["five"];
	x["6"] = ["six"];
	x["7"] = ["seven"];
	x["8"] = ["eight"];
	x["9"] = ["nine"];

	x["a"]=x["A"]=["alice",		"apple",		"absolute"];
	x["b"]=x["B"]=["buzz",		"bus",			"brain",		"blog"];
	x["c"]=x["C"]=["chip",		"cat",			"chaos",		"computer"];
	x["d"]=x["D"]=["disney",	"dolphin",		"destiny",		"docomo"];
	x["e"]=x["E"]=["einstein",	"elephant",		"empty",		"email"];
	x["f"]=x["F"]=["fairy",		"fishing",		"final",		"flash"];
	x["g"]=x["G"]=["genie",		"green",		"god",			"google"];
	x["h"]=x["H"]=["hades",		"house",		"hope",			"hacker"];
	x["i"]=x["I"]=["ivan",		"image",		"infinity",		"ipod"];
	x["j"]=x["J"]=["jack",		"jam",							"java"];
	x["k"]=x["K"]=["king",		"kiddy",		"knowledge"];
	x["l"]=x["L"]=["louie",		"lemon",		"love",			"link"];
	x["m"]=x["M"]=["mickey",	"monkey",		"memory",		"microsoft"];
	x["n"]=x["N"]=["nemo",		"newspaper",	"nil",			"network"];
	x["o"]=x["O"]=["oliver",	"octopus",		"origin",		"online"];
	x["p"]=x["P"]=["pluto",		"panda",		"philosophy",	"pentium"];
	x["q"]=x["Q"]=["queen",		"question",		"quantum"];
	x["r"]=x["R"]=["rabbit",	"rainbow",		"religion",		"ruby"];
	x["s"]=x["S"]=["stitch",	"strawberry",	"science",		"security"];
	x["t"]=x["T"]=["timon",		"tiger",		"time"];
	x["u"]=x["U"]=["ursula",	"umbrella",		"universe",		"unix"];
	x["v"]=x["V"]=["victor",	"volcano",		"violence",		"virus"];
	x["w"]=x["W"]=["woody",		"wedding",		"world",		"windows"];
	x["x"]=x["X"]=["x'mas",		"xbox"];
	x["y"]=x["Y"]=["yzma",		"yellow",						"yahoo"];
	x["z"]=x["Z"]=["zazu",		"zebra",		"zero"];

	x["!"] = ["exclamation"];
	x["#"] = ["number"];
	x["$"] = ["dollar"];
	x["%"] = ["percent"];
	x["&"] = ["and"];
	x["'"] = x["\""] = ["quote"];
	x["("] = x[")"] = ["paren"];
	x["="] = ["equals"];
	x["~"] = ["tilda"];
	x["|"] = ["vertical"];
	x["-"] = ["hyphen"];
	x["^"] = ["caret"];
	x["\\"] = x["/"] = ["slash"];
	x["@"] = ["at"];
	x["["] = x["]"] = ["bracket"];
	x["{"] = x["}"] = ["brace"];
	x["`"] = ["grave"];
	x[";"] = x[":"] = ["colon"];
	x["+"] = ["plus"];
	x["*"] = ["asterisk"];
	x["."] = ["dot"];
	x[","] = ["comma"];
	x["<"] = x[">"] = ["than"];
	x["?"] = ["question"];
	x["_"] = ["underscore"];

	var code_A = "A".charCodeAt(0);
	var code_Z = "Z".charCodeAt(0);
	var code_a = "a".charCodeAt(0);
	var code_z = "z".charCodeAt(0);

	return function(c, MT) {
		if (x[c] === void 0) {
			return c;
		}
		var words = x[c];
		var word = words[Math.floor(words.length * MT.nextFloat())];

		var code = c.charCodeAt(0);
		if (code_A <= code && code <= code_Z) {
			var wordUppercase = "";
			for (var i = 0, l = word.length; i < l; ++i) {
				var d = word.charCodeAt(i);
				if (code_a <= d && d <= code_z) {
					wordUppercase += String.fromCharCode(d + code_A - code_a);
				} else {
					wordUppercase += String.fromCharCode(d);
				}
			}
			return wordUppercase;
		} else {
			return word;
		}
	};
}();

window.addOnloadListener(function() {
	var g = function(id) {return document.getElementById(id);};

	setDescription();

	var args = getArgs();
	if (args["mode"] !== void 0) {
		switch (args["mode"]) {
		case "none":
			document.body.className = "";
			break;
		case "hearty":
			document.body.className = "hearty";
			break;
		case "business":
			document.body.className = "business";
			break;
		case "ashes":
			document.body.className = "ashes";
			break;
		case "peach":
			document.body.className = "peach";
			break;
		default:
			document.body.className = "hearty";
			break;
		}
	} else {
		document.body.className = "hearty";
	}

	var form = g("ypwParameters");

	g("ypwParameters").onsubmit = function() {
		return onSubmitYpwParameters(this);
	};
	g("ypwParameters").onreset = function() {
		return true;
	};

	// Name
	{
		g("nameLabel").onmousedown = function() {
			return false;
		};
		g("ypwName").onfocus = function() {
			this.select();
		};
	}

	// Sex
	{
		g("sexLabel").onmousedown = function() {
			return false;
		};
		// 初回のみ最初のエレメントにフォーカス
		g("ypwSex").onclick = function() {
			if (this.value == -1) {
				this.value = this.options[1].value;
			}
			this.onclick = null;
		};
	}

	// Blood Type
	{
		g("bloodTypeLabel").onmousedown = function() {
			return false;
		};

		// 初回のみ最初のエレメントにフォーカス
		g("ypwBloodType1").onclick = function() {
			if (this.value == -1) {
				this.value = this.options[1].value;
			}
			this.onclick = null;
		};

		// 初回のみ最初のエレメントにフォーカス
		g("ypwBloodType2").onclick = function() {
			if (this.value == -1) {
				this.value = this.options[1].value;
			}
			this.onclick = null;
		};
	}

	// Date - Year
	{
		// 100年分生成
		var options = g("ypwYear").options;
		var currentYear = new Date().getFullYear();
		for (var y = currentYear - 100; y <= currentYear; ++y) {
			options[options.length] = new Option(y.toString(), y);
		}

		g("dateLabel").onmousedown = function() {
			return false;
		};

		// 初回のみ真中にフォーカス
		g("ypwYear").onclick = function() {
			if (this.value == -1) {
				var y0 = parseInt(this.options[1].value);
				var y1 = parseInt(this.options[options.length - 1].value);
				this.value = Math.round((y0 + y1) / 2);
			}
			this.onclick = null;
		};

		// 初回のみ最初のエレメントにフォーカス
		g("ypwMonth").onclick = function() {
			if (this.value == -1) {
				this.value = this.options[1].value;
			}
			this.onclick = null;
		};

		// 初回のみ最初のエレメントにフォーカス
		g("ypwDay").onclick = function() {
			if (this.value == -1) {
				this.value = this.options[1].value;
			}
			this.onclick = null;
		};
	}

	// Word
	{
		g("wordLabel").onmousedown = function() {
			return false;
		};

		g("ypwWord").onfocus = function() {
			this.select();
		};
	}

	// Length
	{
		g("lengthLabel").onmousedown = function() {
			return false;
		};

		g("ypwLength").onclick = function() {
			return onSubmitYpwParameters(form);
		};
	}

	// Reserved Value
	{
	}

	// Sabmit Button
	{
		g("ypwSubmit").onmouseover = function() {
			this.className = "focus";
		};

		g("ypwSubmit").onmouseout = function() {
			this.className = "";
		};
	}

	// Check Save Button
	{
		g("ypwSaveParameters").onmousedown = function() {
			return false;
		};

		g("ypwSaveParameters").onclick = function() {
			var Parameters = createYpwCookie();
			if (this.checked) {
				// save to cookie
				archiveYpwParameters(userParameters, true);
				userParameters.store();
			} else {
				// remove cookie
				userParameters.remove();
			}
		};

		var userParameters = createYpwCookie();
		if (userParameters.load()) {
			g("ypwSaveParameters").checked = true;
			// load parameters
			archiveYpwParameters(userParameters, false);
		} else {
			g("ypwSaveParameters").checked = false;
		}
	}

	g("password1Label").onmousedown =
	g("password2Label").onmousedown =
	g("password3Label").onmousedown = function() {
		return false;
	};

	g("ypwPassword1").onfocus = g("ypwPassword1").onclick =
	g("ypwPassword2").onfocus = g("ypwPassword2").onclick =
	g("ypwPassword3").onfocus = g("ypwPassword3").onclick = function() {
		this.select();
	};

	g("ypwAllParameter").onfocus = g("ypwAllParameter").onclick = function() {
		this.select();
	};

	onSubmitYpwParameters(g("ypwParameters"));
});



function archiveYpwParameters(ar, storeORload)
{
	var g = function(id) {return document.getElementById(id);};

	if (ar == null) {
		window.errorMessage("Internal Error!");
		return null;
	}

	if (storeORload) {
		ar["n"] = g("ypwName").value;
		ar["s"] = g("ypwSex").value;
		ar["b"] = g("ypwBloodType1").value;
		ar["c"] = g("ypwBloodType2").value;
		ar["y"] = g("ypwYear").value;
		ar["m"] = g("ypwMonth").value;
		ar["d"] = g("ypwDay").value;
		ar["w"] = g("ypwWord").value;
		ar["l"] = g("ypwLength").value;
	} else {
		if (ar.unload()) {
			window.errorMessage("Internal Error!");
			return null;
		}

		if (ar["n"] !== void 0) {g("ypwName").value =		ar["n"];}
		if (ar["s"] !== void 0) {g("ypwSex").value =		ar["s"];}
		if (ar["b"] !== void 0) {g("ypwBloodType1").value =	ar["b"];}
		if (ar["c"] !== void 0) {g("ypwBloodType2").value =	ar["c"];}
		if (ar["y"] !== void 0) {g("ypwYear").value =		ar["y"];}
		if (ar["m"] !== void 0) {g("ypwMonth").value =		ar["m"];}
		if (ar["d"] !== void 0) {g("ypwDay").value =		ar["d"];}
		if (ar["w"] !== void 0) {g("ypwWord").value =		ar["w"];}
		if (ar["l"] !== void 0) {g("ypwLength").value =		ar["l"];}
	}

	return ar;
}




