/**
 * product_detail.js
 *
 * @version:1.0.2
 * $Date:2010-3-10
 *
 * Release:
 * 	0.7
 *   global関数の削除（呼び出し元にXdetailContorllerを指定する）
 * 	0.8.2
 *   XtrimDivHeightにX_RECOMMEND_BLOCKを追加
 * 	0.9.0
 *   商品チェック履歴機能呼び出し追加
 *  0.9.1
 *   browser情報のオブジェクト名をXuaに変更
 *  0.9.2
 *   商品チェック履歴機能呼び出しを不本意ながらテンプレートに移動
 *  1.0.0
 *   recommendシステムに対応する為、XtrimDivHeightをtrimDivHeightに名称変更しpublicに変更
 *   1行6列のX_RECOMMEND_BLOCKを廃止
 *   グローバル領域にXrecommendLoadComplate()関数を作成し、trimDivHeightで1行5列のX_RECOMMEND_BLOCKを整形
 *  1.0.1
 *   ソースの整理
 *  1.0.2
 *   カートに渡すパラメータに「商品価格」を加える対応
 *   data.jsから税込価格を取得しhiddenタグに挿入する処理を追加

 */

/**
 * @namespace 商品詳細ページで使用する機能群
 */
var XdetailContorller = {
	
	/**
	 * 設定オブジェクト
	 */
	options:{
		/**
		 * 選択可能商品組み合わせリスト
		 * @type array
		 */
		selectableList : [],
		
		/**
		 * ソート済みデータ
		 * @type object
		 */
		optionData:{},
		
		/**
		 * フォーム部品
		 * @type object
		 */
		Xselect:{ pattern:'X_PATTERNSELECT',size:'X_SIZESELECT',color:'X_COLORSELECT'}
	},
	
	/**
	 * 設定オブジェクトを取得
	 *
	 * @private
	 * @param {string} key 設定オブジェクトのキー
	 * @returns {array|string|object} 設定オブジェクトの内容
	 */
	getOption:function(key){
		return this.options[key];
	},
	/**
	 * 設定オブジェクトに登録
	 *
	 * @private
	 * @param {string} key 設定オブジェクトのキー
	 * @param {array|string|object} param 設定オブジェクトの登録内容
	 */
	setOption:function(key, param){
		this.options[key] = param;
	},
	
	/**
	 * 初期化
	 */
	setup:function(){
		
		//NEWマーク表示
		this.displayNewIcon();
		
		//各データの生成
		this.setOption('optionData',this.analysisValData());
		
		//選択可能全パターンデータ作成
		this.setOption('selectableList',this.analysisItemData());
		
		//select optionタグ生成
		this.setupSelect();
		
		//フォームの表示
		this.displayElementID('X_FORM_SHOPPING');
		
		//高さをそろえる
		this.trimDivHeight('X_COORDINATES', 3);
	},
		
	/**
	 * 要素の高さを揃える関数を作成
	 * @public
	 * @see core.js
	 */
	trimDivHeight : new jp.co.mutow.trimHeight(),
	
	/**
	 * 各セレクトフォームoptionデータの重複を解決しソートする
	 *
	 * @private
	 * @return {object} ソート済みセレクトフォーム<option>用データ
	 */
	analysisValData:function(){
		//各データを重複を解決しローカル変数に格納
		var 
		optPatternData = this.arrayUnique(optionPatternData),
		optSizeData = this.arrayUnique(optionSizeData),
		optColorData = this.arrayUnique(optionColorData);
		
		//サイズのソート
		var sizeSrt = (flgZacca == "1") ? this.sortUpByVal : this.sortDownByVal;
		//それ以外のソート
		var defSrt = this.sortUpByVal;
		
		//ソートする
		optPatternData.sort(defSrt);
		optSizeData.sort(sizeSrt);
		optColorData.sort(defSrt);
		
		return {pattern:optPatternData, size:optSizeData, color:optColorData};
	},
	
	/**
	 * 選択可能な組み合わせを配列オブジェクトに変換する
	 *
	 * @private
	 * @reutn {array} 選択可能な組み合わせオブジェクトの配列
	 */
	 analysisItemData:function(){
		var 
		temp = [],
		iData = itemDetailData,
		sortData = this.getOption('optionData'),
		//コードがキーのオブジェクトを作成
		cData = this.bucketObj(sortData['color']),
		sData = this.bucketObj(sortData['size']),
		pData = this.bucketObj(sortData['pattern']),
		
		/**
		 * オブジェクトの連結
		 *
		 * @private
		 * @memberOf XdetailContorller.analysisItemData
		 * @param {object} master 元のオブジェクト
		 * @param {object} slave 結合されるオブジェクト
		 * @param {string} additional 結合するときにキーに追加する接頭語
		 */
		objConcat = function(master, slave, additional){
			var obj = master;
			for(var o in slave){
				obj[additional+o] = slave[o];
			}
			return obj;
		};
		
		for(var i = 0,len = iData.length - 1 ; i < len ; i++ ){
			var
			obj = {},
			data = iData[i]['shnInfo'].split('||'),
			//各オプションデータからvalとdispのリストを作成
			cValue = data[2],
			sValue = data[3],
			pValue = data[1],
			mValue = data[0],
			kValue = data[4];
			obj = objConcat(obj,cData[cValue], 'color');
			obj = objConcat(obj,sData[sValue], 'size');
			obj = objConcat(obj,pData[pValue], 'pattern');
			obj = objConcat(obj,{mskmno:mValue},'');
			obj = objConcat(obj,{price:kValue},'');
			temp.push(obj);
		}
		return temp;
		
	 },

	/**
	 * select optionタグ生成をコントロールする
	 * @private
	 */
	setupSelect:function(){
		var 
		sortData = this.getOption('optionData'),
		Xselect = this.getOption('Xselect');
		
		for(var o in Xselect){
			var 
			arr = sortData[o],
			len = arr.length;
			//1件の時はhiddenのみなので、optionは作成しない
			if(len>1){
				this.makeSelectOptions(Xselect[o], arr);
			}else{
				this.cleanSelect(o);
			}
		}
	},
	
	/**
	 * selectタグを消去する
	 *
	 * @private
	 * @param {string} o オブジェクトのキー {"pattern"|"size"|"color"}
	 */
	cleanSelect:function(o){
		var 
		Xselect = this.getOption('Xselect'),
		elm = document.getElementById(Xselect[o]);
		
		if(elm) elm.parentNode.style.display = 'none';
			Xselect[o] = null;
			delete Xselect[o] ;
			this.setOption('Xselect', Xselect);
	},
	
	/**
	 * select,optionタグの作成
	 *
	 * @private
	 * @param {string} ID 作成するselectタグのID
	 * @param {array} arr 作成するoptionタグの内容の配列
	 * @param {string} defVal selectタグの設定値
	 */
	makeSelectOptions:function(ID, arr, defVal){
		var 
		elm = document.getElementById(ID),
		len = arr.length,
		ie = Xua.msie,
		out = [];
		
		out.push('<option value="">選択してください</option>');
		for(var i = 0 ; i < len ; i++ ){
			var disp = arr[i].disp || '-';
			out.push('<option value="'+ arr[i].val +'">'+ disp +'</option>');
		}
		//IEはselectにinnerHTMLすることができない凄いバグが
		//あるのでselectごと作成する
		if(ie){
			var tag = elm.outerHTML.split('>');
			elm.outerHTML = tag[0] + '>' + out.join('\n') + '</select>';
			//書き換えたらスコープ失うので再度定義
			var elm = document.getElementById(ID);
		}else{
			elm.innerHTML = '';
			elm.innerHTML = out.join('\n');
		}
		if(defVal) elm.value = defVal;
	},
	
	/**
	 * selectの更新
	 *
	 * @param {object} elm 更新のあった要素
	 */
	updateSelect:function(elm){
	
		var 
		Xselect = this.getOption('Xselect'),
		selectable = this.getOption('selectableList'),
		sortData = this.getOption('optionData'),
		val = this.getSelectValue(Xselect);
		
		/**
		 * 選択可能配列からselectの値で絞り込む
		 *
		 * @private
		 * @param {string} key 基準となるキー
		 * @return {array} 基準となるキーの選択可能な値の配列
		 */
		var refineData = function(key){
			var temp = selectable;
			for(var o in Xselect){
				if(o == key) continue;
				var v = val[o];
				if(v){
					var arr = [];
					for(var i = 0,len = temp.length ; i < len ; i++ ){
						if(temp[i][o+'val'] == v) arr.push(temp.slice(i, i+ 1)[0]);
					}
					temp = arr;
				}
			}
			return temp;
		};
		
		//各selectのoptionデータを取得してタグを作成
		for(var o in Xselect){
			//変更のあったselectは書き換えなくてよい
			if(Xselect[o] == elm.id) continue;
			//それ以外は絞り込む
			var 
			temp = [],
			arr = refineData(o);
			for(var i = 0,len = arr.length ; i < len ; i++ ){
				var t = arr[i];
				temp.push({val:t[o+'val'],rank:t[o+'rank'],disp:t[o+'disp']});
			}
			//重複を解決
			temp = this.arrayUnique(temp);
			//ソート方法を取得
			var srt = (o=='size' && flgZacca == "1") ? this.sortUpByVal :  this.sortDownByVal;
			//ソートして、optionタグを作成
			this.makeSelectOptions(Xselect[o], temp.sort(srt), val[o]);
		}
	},
	
	/**
	 * Xselectのすべてのselectの値を取得しオブジェクトで返す
	 *
	 * @private
	 * @param {object} Xselect フォーム部品
	 * @return {object} フォームの値をXselectのキーでオブジェクト化したデータ
	 */
	getSelectValue:function(Xselect){
			/**
			 * フォーム部品の値を取得
			 * @private
			 * @param {string} ID フォーム部品のID
			 * @return {string} フォーム部品の値
			 */
			var getValue = function(ID){
				var elm = document.getElementById(ID);
				return elm.value;
			};
			//オブジェクトに代入
			for(var o in Xselect){
				this[o] = getValue(Xselect[o]);
			}
			 return this;
	},
	
	/**
	 * 配列をvalをキーにしたオブジェクトに変換
	 * 重複したvalは上書きされる
	 *
	 * @private
	 * @param {array} arr 配列の各要素にキー"val"を持つ配列
	 * @return {object} 配列のvalをキーにしたオブジェクト
	 */
	bucketObj:function(arr){
		var bucket = {};
		for(var i = 0, len = arr.length; i < len ; i++ ){
			bucket[arr[i].val] = arr[i];
		}
		return bucket;
	},
	
	/**
	 * 昇順比較関数
	 * rank機能付き（昇順）
	 *
	 * @private
	 * @param {string} a 比較文字列
	 * @param {string} b 比較文字列
	 * @return {number} (-1|0|1)
	 */
	sortUpByVal:function(a,b){
		if(a.rank != b.rank) return b.rank - a.rank;
		if(a.val < b.val) return -1;
		if(a.val > b.val) return 1;
		return 0;
	},
	/**
	 * 降順比較関数
	 * rank機能付き（昇順）
	 *
	 * @private
	 * @param {string} a 比較文字列
	 * @param {string} b 比較文字列
	 * @return {number} (-1|0|1)
	 */
	sortDownByVal:function(a,b){
		if(a.rank != b.rank) return b.rank - a.rank;
		if(a.val > b.val) return -1;
		if(a.val < b.val) return 1;
		return 0;
	},
	
	/**
	 * 配列からユニークな値の配列に変換
	 *
	 * @private
	 * @param {array} arr
	 * @return {array}
	 */
	arrayUnique:function(arr){
		var temp = [];
		for (var i = 0, len = arr.length; i < len; i++) {
			//valが無ければ排除
			if(!arr[i].val) continue;
			if(!this.inArray(arr[i].val, temp)) temp.push(arr[i]);
		}
		return temp;
	},

	/**
	 * 変数 v が配列 arr に含まれるか確認する
	 *
	 * @private
	 * @param {} v 値
	 * @param {array} 配列
	 * @return {boolean}
	 */
	inArray:function(v, arr){
		for (var i = 0, len = arr.length; i < len; i++) {
			if (v == arr[i].val) return true;
		}
		return false;
	},
	
	/**
	 * 現在の日付との差が14日間以下NEWマーク画像を表示
	 * @private
	 */
	displayNewIcon:function(){
		var 
		d = new Date(),
		ds = new Date(startDate);
		//現在の日付との差が14日間以下NEWマーク画像を表示
		if (d.getTime() < ds.getTime() + (14 * 86400000)) {
			this.displayElementID('X_NEWMARK');
		}
	},
	/**
	 * 要素の表示
	 *
	 * @private
	 * @param {string} ID  表示する要素のID名
	 */
	displayElementID:function(ID){
		var elm = document.getElementById(ID);
		elm.style.display = 'block';
	},
	
	/**
	 * カートに入れる処理
	 * 
	 * @param {object} form 実行されたformエレメント
	 * @return {boolean}
	 * @throws 未選択項目がある場合は、アラートでエラーメッセージ表示
	 */
	onCartAction:function(form){
		var 
		Xselect = this.getOption('Xselect'),
		selectable = this.getOption('selectableList'),
		sortData = this.getOption('optionData'),
		//iselパラメータ
		iselParam = {
			pattern:{err:'パターン', t:'p1', f:'p2',n:'p3'},
			color:{err:'色', t:'c1', f:'c2',n:'c3'},
			size:{err:'サイズ', t:'s1', f:'s2',n:'s3'}
		},
		//フォームの値
		val = this.getSelectValue(Xselect),
		//エラー格納配列
		err = [],
		//isel変数
		isel = "";
		
		for(var o in iselParam){
			var p, v = val[o];
			if(v){
				p = iselParam[o]['t'];
			}else{
				if(!Xselect[o]){
					p = iselParam[o]['n'];
				}else{
					p = iselParam[o]['f'];
					err.push(iselParam[o]['err']);
				}
			}
			isel += p;
		};
		
		//エラーがある場合メッセージを表示
		if (err.length){
			alert(err.join("・") + "を選択してください。");
			return false;
		}else{
			var
			mskmNo,
			price;
			for(var i = 0, len = selectable.length; i < len ; i++ ){
				var 
				obj = selectable[i], 
				chk = 0;
				for(var o in iselParam){
					//値が等しい
					//値がなければ、無しか１件hiddenなのでスキップ
					if(!val[o] || val[o] == obj[o+'val']) chk++;
				}
				if(chk==3){
					mskmNo = obj['mskmno'];
					price = obj['price'];
					break;
				}
			}
			isel += (mskmNo) ? "i1" : "i3";
			
			//HIDDENタグに値を代入
			form.mskmno.value = mskmNo;
			form.isel.value = isel;
			form.cms_price.value = price;
			//送信実行
			form.submit();
			return false;
		}
	},
	/**
	 * 価格・在庫確認
	 *
	 * @param {object} form 実行されたformエレメント
	 * @return {boolean}
	 */
	onStockAction:function(form){
		var win = window.open("","zaiko","width=700,height=600,scrollbars,resizable");
		//送信実行
		form.submit();
		win.focus();
		return false;
	}
};

/**
 * レコメンド書き出しjsの読み込み完了時に呼び出されるコールバック関数
 * recommend.kbmj.com/recommendの書き出すjavascriptの最終行（HTMLを書き出した後）に
 * この関数を呼び出す命令を追加すること
 *
 *  ...
 *  var target = document.getElementById("kbmj_mix1");
 *  target.appendChild(div);
 *  XrecommendLoadComplate();
 * 
 * @public
 */
XrecommendLoadComplate = function(){
	//1行5列のX_RECOMMEND_BLOCK
	XdetailContorller.trimDivHeight('X_RECOMMEND_BLOCK', 5);
};


/**
 * DOM解析終了後のイベント
 */
addEvent(window, 'domReady', function(){
	//詳細ページの機能初期化
	XdetailContorller.setup();
});




