/*
   幸運のグッズ（グラス・まねき猫）で利用するjavascript
  
  以下を行っています。
  ・プレビューへの値のコピー
  ・画面遷移、ボタン押下時の制御
  ・バリデーション
  ・郵便番号による住所の入力保管
  
  当javascripを利用するには、
  htmlファイルを記述する上で以下の制約・規約があります。
  
  ・HTMLでは以下のidをもつdiv要素を実装する必要あります。
     ・ offer    ... 購入フォーム用
     ・ preview  ... プレビュー用
     ・ complete ... メール送信完了
     ・ message  ... エラーや送信中のメッセージ表示用

  ・プレビュー箇所の記述方法
     入力値を表示する箇所は、対応するinputタグのIDに"preview_"をつけた
     spanタグを記述します。
     
     例）
       <div id="offer">  <!-- 入力フォーム -->
         商品名：<input type="text" id="product_name"/>
       </div>
	   <div id="preview"> <!-- プレビュー -->
	     商品名：<span id="preview_product_name"></span>
	   </div>
 
  ・商品の購入数の入力チェックを行う場合
   （全商品のうち最低ひとつは、数量が１以上となっているかをチェック）

     <span id="products_amount"> ... </span>でinputタグを括ってください。
     そのspan内にあるinputタグの入力値がすべてゼロなら入力チェックでエラーとなります。
*/

// ---------------------------------------------------------
// プレビューへの値コピー

/**
 * 購入フォームの各項目に対応するプレビュー画面のspanタグのIDの接頭語
 * フォームの値をプレビューに反映するときに利用します。（copyToPreview関数）
 * 
 * 例）購入フォームのinputタグのIDが"product"であれば、
 * プレビューのspanタグに"preview_product"とIDをつける.
 */
var preview_id_prefix = "preview_";

/**
 * 購入フォーム、プレビュー、完了、メッセージ用のdivのidです。
 */
var blocks = new Array("offer", "preview", "complete", "message");


/**
 * フォームの値をプレビューに反映します.
 * inputのvalueを"preview_xxxxxx"のidをもつ
 * elementのinnerHTMLにコピーします
 */
function copyToPreview(input) {
	var thisId = input.getAttribute('id');
	var previewElement = document.getElementById(preview_id_prefix + thisId);
	if (!previewElement) return;
	if("cat"==document.getElementById("title").value){initNumberInputFields();}
	previewElement.innerHTML = input.value.replace(/\n/g, "<br/>");  // 改行を置換
}

/**
 * divName配下のタグ（tagNameで指定）のすべてにcopyToPreview関数を設定します.
 * 
 * @param {Object} divName
 * @param {Object} tagName
 */
function attachCopyToPreview(divName, tagName) {
	var divElement = document.getElementById(divName);
	var inputElements = divElement.getElementsByTagName(tagName);
	for (var i = 0; i < inputElements.length; i++) {
		copyToPreview(inputElements[i]);
	}
}

// ---------------------------------------------------------
// ボタン制御・画面遷移の制御

/**
 * プレビューで送信をクリックしたとき
 */
function clickedSend() {
	showWorking();
	var mailBody = jp.co.takarakujinet.MailUtil.makeMailBody("offer");
	
	jp.co.takarakujinet.MailSender.send(mailBody, showComplete, showError);
}
/**
 * メール送信完了用のdivを表示します.
 */
function showComplete() {
	show("complete");
}
/**
 * メール送信中を表示します.
 */
function showWorking() {
	document.getElementById("message_text").innerHTML="メールの送信中です。しばらくお待ちください";
	document.getElementById("free_area").innerHTML=
			"<img src='../images/ajax-loader.gif' /><br/>";
	show("message");
}
/**
 * メール送信エラーを表示します.
 */
function showError() {
	document.getElementById("message_text").innerHTML="メールの送信でエラーが発生しました";
	document.getElementById("free_area").innerHTML=
	         "再度送信してください"
		   + "<a href='/index.html'><br/>トップページへ戻る</a>";
	show("message");
}

/**
 * プレビューから戻ります.
 */
function showOffer() {
	show("offer");
}

/**
 * プレビューを表示します。
 */
function showPreview() {
	show("preview");
}

/**
 * 表示するdivブロックを切り替えます.
 * @param id "offer", "preview", "complete", "message"のいずれかを指定します.
 */
function show(id) {
	for (i = 0; i < blocks.length; i++) {
		display = (id == blocks[i] ? "block" : "none");
		document.getElementById(blocks[i]).style.display = display;
	}
}

// ---------------------------------------------------------
// バリデーション

/**
 * 招き猫のバリデーションを行います.
 * 
 * @param {Object} form
 */
function validateOfferCat(form) {
	
	if (amountIsAllZero()) {
		window.alert("購入商品がありません。");
		return;
	}
	if (!Validator.submit(form)) {
		return;
	}
	
	showPreview();
}
/**
 * グラスギフトのバリデーションを行います.
 * 
 * @param {Object} form
 */
function validateOfferGlass(form) {
	if (hasNotProduct()) {
		window.alert("商品を選択してください。");
		return;
	}
	if (isNotMatched()) {
		window.alert("商品または数量が未入力ですので、お確かめください。");
		return;
	}
	if (!Validator.submit(form)) {
		return;
	}
	
	showPreview();
}
function hasNotProduct() {
	for (var i = 0; i < 5; i++) {
		var product = document.getElementById("product" + (i + 1)).value;
		var quantity = document.getElementById("quantity" + (i + 1)).value;
		if (product || quantity) {
			return false;
		}
	}
	return true;
}
/**
 * 購入商品と個数の相関チェック
 * 商品と数量が正しく選択されていない場合にtrueを返します。
 */
function isNotMatched() {
	var matchedCount = 0;
	for (var i = 0; i < 5; i++) {
		var product = document.getElementById("product" + (i + 1)).value;
		var quantity = document.getElementById("quantity" + (i + 1)).value;
		if (("" == product) == ("" == quantity)) {
			matchedCount++;
		}
	}
	return matchedCount < 5;
}
/**
 * 購入商品個数の0チェック
 * "products_amount"のIDをもつ要素内にあるinputタグの数量が
 * すべてゼロの場合にtrueを返します.
 */
function amountIsAllZero() {
	var amountsDiv = document.getElementById("products_amount");
	if (!amountsDiv) return false;
	
	var amounts = amountsDiv.getElementsByTagName("select");
	
	for (var i = 0; i < amounts.length; i++) {
		if (amounts[i].value != 0) {
			return false;
		}
	}
	return true;
}

// ---------------------------------------------------------
// 郵便番号による住所検索・補完入力
// 


/**
 * 郵便番号による住所検索APIを呼び出す
 */
AddressLoader = {
	_callbackName : null,
	_obj : null,
	
	/**
	 * Webサービスに接続し、郵便番号に対応する住所の一覧を取得します.
	 * 呼び出し後、obj.callbackNameをコールします。
	 * 
	 * @param {Object} zipcode 郵便番号
	 *                          ハイフンは有無どちらでも可。3桁上入力された場合に検索する。
	 * @param {Object} obj コールバックする関数を持つオブジェクト
	 * @param {Object} callbackName コールバック関数名（文字列）
	 */
	search : function(zipcode, obj, callbackName) {
		this._callbackName = callbackName;
		this._obj = obj;
		
		if (!this._checkZipcode(zipcode)) {
			return false;
		}
		var target = document.createElement('script');
		target.charset = 'utf-8';
		target.src = 'http://groovetechnology.co.jp/ZipSearchService/v1/zipsearch?'
		           + 'zipcode=' + encodeURIComponent(zipcode)
				   + '&callback=_callbackAddressReader';
		
		document.body.appendChild(target);
	},
	
	_checkZipcode : function(zipcode) {
		if (  !zipcode 
		   ||  zipcode.length == 0
		   || !zipcode.match(/^[0-9]{7}$/)) {
			return false;
		}
		
		return true;
	},
	
	_callback : function(data) {
		this._obj[this._callbackName](data);
	}
}
/**
 * Webサービスから呼び出されるコールバック関数.
 * "."区切りのコールバック関数が呼べないためにAddressSuggestLoader外に定義.
 * 
 * @param {Object} data
 */
function _callbackAddressReader(data) {
	AddressLoader._callback(data);
}

/**
 * 郵便番号による入力補完オブジェクトを作成するコンストラクタ.
 * @param {Object} addressId 補完される住所のinputタグ要素のID
 * @param {Object} zipcodeId 検索する郵便番号のinputタグ要素のID
 * @param {Object} suggestListId 補完リストを表示するタグ要素のID
 */
function AddressSuggest (addressId, zipcodeId, suggestListId){
	this._addresses = null;
	this._addressElement = document.getElementById(addressId);
	this._zipcodeElement = document.getElementById(zipcodeId);
	this._suggestListElement = document.getElementById(suggestListId);
}

AddressSuggest.prototype = {
	/**
	 * 郵便番号による検索を行い、
	 * 検索結果が複数あれば補完候補のリストを表示します。
	 * 検索結果が1件の場合は、リストは表示されず住所のInputタグに検索された住所が入ります。
	 */
	search : function() {
		AddressLoader.search(
			this._zipcodeElement.value, this, "_callbackSuggestLoaded");
	},
	
	/** AddressLoader用のコールバック関数. */
	_callbackSuggestLoaded : function (zipData) {
		this._createAddressList(zipData);
		
		if (this._addresses.length == 1) {
			this._setAddress(0);
			return;
		}
		
		this._createSuggestListHtml();
	},
	
	/** 補完候補リストの作成. */
	_createSuggestListHtml : function() {

		var listElement = document.createElement("ul");
		for (var i = 0; i < this._addresses.length; i++) {
			
			// 以下のようなタグを出力.
			// <li><a href='' onclick='addressSuggest._setAddress(0);return false;'>東京都</a></li>
			var liElement = document.createElement("li");
			var aElement = document.createElement("a");
			aElement.addressIndex = i;
			aElement.href="";
			var thisObj = this;
			aElement.onclick = function() {
				thisObj._setAddress(this.addressIndex);
				return false;      // リンクに飛ばないようにfalse;
			}
			aElement.innerHTML = this._addresses[i].text;
			liElement.appendChild(aElement);
			listElement.appendChild(liElement);
		}
		this._suggestListElement.innerHTML = "";
		this._suggestListElement.appendChild(listElement);
		this._suggestListElement.style.display = "block";
	},
	
	/** 住所のタグ要素に値を設定します。また、郵便番号も合わせて設定します。 */
	_setAddress : function(index){
		this._addressElement.value = this._addresses[index].text;
		
		var zipcode = this._addresses[index].zipcode;
		this._zipcodeElement.value = zipcode.substr(0, 3) + zipcode.substr(3);
		
		this._suggestListElement.innerHTML = "";
		this._suggestListElement.style.display = "none";
	},
	
	/** AddressLoader で取得したデータを扱いやすいように配列にします. */
	_createAddressList : function(zipData) {
		this._addresses = new Array();
		for (var i in zipData.zipcode) {
			this._addresses.push({
				zipcode : zipData.zipcode[i].zipcode,
				text : this._createAddressText(zipData.zipcode[i])}
			);
		}
		for (var i in zipData.office) {
			this._addresses.push({
				zipcode : zipData.office[i].zipcode,
				text : this._createAddressText(zipData.office[i])
			});
		}
	},
	
	/** AddressLoader で取得した住所データを扱いやすいように整形します */
    _createAddressText : function(zipData) {
		var value = zipData.prefecture + zipData.city;
		if (! zipData.zipcode.match(/[0-9]{5}00$/)) { // xxx-xx00(「以下に掲載がない場合」)
			value += zipData.town;
			if (zipData.street) {
				value += zipData.street;
			}
		}
		return value;
	}
}




