GGSB.modules.data = function(ggsb) {
	
	var API_URL = {
			'golf' :  '/api/m/golf',
			'round' : '/api/t/roundrecord',
			'myweapon' : '/api/m/myweapon',
			'cdclub' : '/api/m/cdclub',
			'mystrategy' : '/api/t/mystrategy'
		};
	
	var Data = function(args) {
		this._data = {};
		
		
		//this.initData(this._params);
	};
	
	
	
	var prot = {
		
		ErrorMessage : {
			'ShotLimit' : '1ホール15打までしか登録できません',
			'DecreaseFirstShotNo' : '選択したショットは先頭に存在します',
			'ShotNoDecrementDuplicate' : '既に同じ打数が存在する為、打数の減少はできません',
			'CommentLengthOver' : '50文字以内で入力してください',
			'ShotNoDuplicate' : '重複する打数が指定されているためショットを追加できません。重複するショットを削除するか打数を追加・減少させ重複をなくして下さい。'
		},
		
		
		initData: function(args) {
			
			this._params = $.extend({
				triggerEventName:''
			}, args);
			
			var data = $.extend(args.data, {}),
				self = this,
				callback = callback,
				api,
				i;
			
			this._countAjaxRequest = 0;
			this._requestAPI = args.api;
			
			for (i = 0; i < this._requestAPI.length; i++) {
				api = this._requestAPI[i];
				self._data[api] = {};
				$.ajax({
					type:'POST',
					url:API_URL[api],
					dataType:'json',
					data:data,
					success:function(dat, dataType) {
						var api, i;
						
						for (i = 0; i < self._requestAPI.length; i++) {
							api = self._requestAPI[i];
							if (this.url == API_URL[api]) {
								self._data[api] = dat.Data;
								
								break;
							}
						}
					},
					complete:function(request, status) {
						if (++self._countAjaxRequest == self._requestAPI.length) {
							if (self._params.triggerEventName.length > 0) {
								$(window).trigger(self._params.triggerEventName);
							}
						}
					},
					error:self.ajaxError
				});
			}
		},
		
		
		ajaxError : function(XMLHttpRequest, textStatus, errorThrown) {
			console.log('error', textStatus);
		},
		
		
		getShotData : function(hole) {
			var ret = [];
			
			for (dat in this._data.T_SHOT_TRACE_LIST) {
				//if (dat['ROUND_
			}
		},
		
		
		
		getMapData : function() {
			return this._data.golf.M_GOLF;
		},
		
		
		
		getMapImage : function() {
			return this._data.golf.M_GOLF_IMG_LIST;
		},
		
		
		
		getCourse : function(args) {
			if (args.holeIndex < 10) {
				return this._data.golf.M_GOLF_COURSE_LIST[0];
			} else {
				return this._data.golf.M_GOLF_COURSE_LIST[1];
			}
		},
		
		
		
		getCourseHole : function(args) {
			if (!this._data.golf) {
				return;
			}
			
			
			var obj = this._data.golf.M_GOLF_COURSE_HOLE_LIST,
				i,
				l = obj.length;
			
			for (i = 0; i < l; i++) {
//				if (args.holeId == obj[i].HOLE_NO) {
				if (args.holeId == obj[i].HOLE_NO && args.courseId == obj[i].GOLF_COURSE_ID) {
					return obj[i];
				}
			}
			
			return null;
		},
		
		
		
		getCourseHoleNoMax : function() {
			var obj = this._data.golf.M_GOLF_COURSE_HOLE_LIST,
				i,
				l = obj.length
				ret = 0;
			
			for (i = 0; i < l; i++) {
				if (ret < obj[i].HOLE_NO) {
					ret = obj[i].HOLE_NO;
				}
			}
			
			return ret;
		},
		
		
		
		getCourseHoleHazard : function(args) {
			var obj = this._data.golf.M_GOLF_COURSE_HOLE_HAZARD_LIST,
				i,
				l = obj.length;
			
			// カップは複数ある可能性があるので、必ず配列になっている
			for (i = 0; i < l; i++) {
//				if (args.holeId == obj[i][0].HOLE_NO) {
				if (args.holeId == obj[i][0].HOLE_NO && args.courseId == obj[i][0].GOLF_COURSE_ID) {
					return obj[i];
				}
			}
			
			return null;
		},
		
		
		
		getScoreRecord : function(args) {
			if (!this._data.round) {
				return;
			}
			
			var obj = this._data.round.T_SCORE_RECORD_LIST,
				i,
				l;
			
			if (obj) {
				l = obj.length;
				
				for (i = 0; i < l; i++) {
//					if (obj[i].HOLE_NO == args.holeId) {
					if (obj[i].SCORE_RECORD_ID == args.scoreRecordId) {
						return obj[i];
					}
				}
			}
			return null;
		},
		
		
		
		getStrategyMemo : function(args) {
			var obj = this._data.mystrategy.T_MY_STRATEGY_MEMO,
				i,
				l;
			
			if (obj) {
				l = obj.length;
				
				for (i = 0; i < l; i++) {
					if (obj[i].HOLE_NO == args.holeId) {
						return obj[i];
					}
				}
			}
			
			return null;
		},
		
		
		setStrategyMemo : function(memo, args) {
			var obj = this._data.mystrategy.T_MY_STRATEGY_MEMO,
				i,
				l;
			
			if (!obj) {
				this._data.mystrategy.T_MY_STRATEGY_MEMO = [];
				obj = this._data.mystrategy.T_MY_STRATEGY_MEMO;
			}
			
			l = obj.length;
			
			for (i = 0; i < l; i++) {
				if (obj[i].HOLE_NO == args.holeId) {
					obj[i].MEMO = memo;
					return;
				}
			}
			
			// 該当のHOLE_NOがなければ新規追加
			// memoが空（かつデータが存在しなければ）追加の必要は無い
			if (memo.length == 0) {
				return;
			}
			var hole = this.getCourseHole(args);
			this._data.mystrategy.T_MY_STRATEGY_MEMO.push({
				GOLF_COURSE_HOLE_ID : hole.GOLF_COURSE_HOLE_ID,
				GOLF_COURSE_ID : hole.GOLF_COURSE_ID,
				GOLF_ID : $('#golfID').val(),
				HOLE_NO : hole.HOLE_NO,
				MEMO : memo,
				USER_ID : $('#userID').val(),
				CREATE_DATE : '',
				UPDATE_DATE : ''
			});
		},
		
		
		
		getShotTraceList : function(args) {
			if (!this._data.round || !this._data.round.T_SHOT_TRACE_LIST || !args) {
				return null;
			}
			
			var obj = this._data.round.T_SHOT_TRACE_LIST,
				ret,
				i, l;
			
			if (!obj) {
				this._data.round.T_SHOT_TRACE_LIST = [];
				return null;
			}
			l = obj.length;
			
			for (i = 0; i < l; i++) {
				ret = obj[i];
				if (ret && ret[0] && ret[0].SCORE_RECORD_ID == args.scoreRecordId) {
					ret.sort(this.sortShotTrace);
					
					return ret;
				}
			}
			
			return null;
		},
		
		
		
		sortShotTrace : function(a, b) {
			//return a.SHOT_NO > b.SHOT_NO ? 1 : -1;
			return a.SHOT_TRACE_ID > b.SHOT_TRACE_ID ? 1 : -1;
		},
		
		
		
		setShotTraceList : function(args, data) {
			var obj = this._data.round.T_SHOT_TRACE_LIST,
				l,
				i;
			
			if (!obj) {
				this._data.round.T_SHOT_TRACE_LIST = [];
				obj = this._data.round.T_SHOT_TRACE_LIST;
			}
			
			l = obj.length;
			// argsがnullの時
			// 新規に配列を追加する
			if (!args) {
				
				for (i = 0; i < l+1; i++) {
					if (!obj[i]) {
						obj[i] = [];
						obj[i] = [$.extend(true, {}, data)];
						
						return;
					}
				}
				return;
			}
			
			
			for (i = 0; i < l; i++) {
			    if (obj && obj[i] && obj[i][0] && obj[i][0].SCORE_RECORD_ID == args.scoreRecordId) {
					obj[i] = $.extend(true, [], data);
					return;
				}
			}
			//this._data['round']['T_SHOT_TRACE_LIST'][args.holeId-1] = $.extend(true, [], data);
		},
		
		
		
		detectShot : function(shotTraceId, obj) {
			var i, 
				l = obj.length,
				ret = null;
			
			// ショットデータ位置特定
			for (i = 0; i < l; i++) {
				if (obj[i].SHOT_TRACE_ID == shotTraceId) {
					ret = i;
					break;
				}
			}
			return ret;
		},
		
		
		
		prependShot : function(args) {
			var i,
				obj = this.getShotTraceList(args),
				l = obj.length,
				shot,
				pos;
			
			if (obj && obj.length >= 15) {
				alert(this.ErrorMessage.ShotLimit);
				return;
			}
			
			
			pos = this.detectShot(args.shotTraceId, obj);
			
			if (pos == null) {
				return;
			}
			
			if (this.testShotNoDuplicate(obj)) {
				alert(this.ErrorMessage.ShotNoDuplicate);
				return;
			}
			
			
			shot = $.extend(true, {}, obj[pos]);
			
			shot.MY_WEAPON_ID = null;
			shot.CLUB_NAME = "";
			shot.COMMENT = "";
			
			if (pos == 0) {
				var cups = this.getCourseHoleHazard(args);
				
				if (cups) {
					shot.LAT = (cups[0].LAT + shot.LAT) / 2;
					shot.LON = (cups[0].LON + shot.LON) / 2;
				}
			} else {
				shot.LAT = (obj[pos].LAT + obj[pos-1].LAT) / 2;
				shot.LON = (obj[pos].LON + obj[pos-1].LON) / 2;
			}
			
			// 挿入以後のSHOT_NOをインクリメント
			args.NotClearCarryYard = true;

			if (obj && pos > 0 && (obj[pos-1].SHOT_NO + 1 < obj[pos].SHOT_NO)) {
				// 「前に追加する」と選んだショットとすでに前にあるショットのSHOT_NOが連続していない場合
				// すでにあるショットのSHOT_NOを変更せずに新しくショットを追加します。
				// SHOT_NOが連続していないため、「前に追加する」と選んだショットのSHOT_NO - 1 を
				// 新しく追加するショットのSHOT_NOとしてもショット番号が重複せずに設定可能です。
				shot.SHOT_NO = obj[pos].SHOT_NO - 1;
			} else {
				// 「前に追加する」と選んだショットとすでに前にあるショットのSHOT_NOが連続している場合
				// すでにあるショットのSHOT_NOを増加してSHOT_NOが重複しないようにします。
				this.increaseShotNo(args);
			}

			// SHOT_NOが連続していない場合でもSHOT_TRACE_ID は常に連続しているので
			// SHOT_TRACE_ID はインクリメントします
			this.increaseShotID(args);
			
			obj.splice(pos, 0, shot);
			
		},
		
		
		
		appendShot : function(args) {
			var i,
				obj = this.getShotTraceList(args),
				l,
				shot,
				pos,
				hole;
			
			if (obj) {
				if (this.testShotNoDuplicate(obj)) {
					alert(this.ErrorMessage.ShotNoDuplicate);
					return;
				}
				
				l = obj.length;
			} else {
				l = 0;
			}
			
			if (obj && obj.length >= 15) {
				alert(this.ErrorMessage.ShotLimit);
				return;
			}
			
			// ショットを末尾に追加に対応するようにshotNoがない場合は末尾に追加する
			if (args && args.shotTraceId) {
				pos = this.detectShot(args.shotTraceId, obj);
			} else {
				pos = l-1;
			}
			
			if (pos == -1) {
				pos = 0;
				
				hole = this.getCourseHole(args);
				
				shot = {
					"ALTITUDE"			: null,
					"CARRY_YARD"		: null,
					"CLUB_NAME"			: "",
					"COMMENT"			: "",
					"CREATE_DATE"		: "",
					"DELETE_FLG"		: false,
					"GPS_CREATE_DATE"	: "",
					"GPS_FLG"			: false,
					"HOLE_NO"			: ~~(args.holeId),
					"LAT"				: hole.LAT,
					"LON"				: hole.LON,
					"MY_WEAPON_ID"		: null,
					"REVISE_FLG"		: false,
					"ROUND_RECORD_ID"	: $('#roundRecordID').val(),
					"SCORE_RECORD_ID"	: args.scoreRecordId,
					"SHOT_NO"			: 0,
					"SHOT_TRACE_ID"		: 0,
					"UPDATE_DATE"		: "",
					"USER_ID"			: $('#userID').val()
				};
			} else {
				shot = $.extend(true, {}, obj[pos]);
				
				shot.MY_WEAPON_ID = null;
				shot.CLUB_NAME = "";
				shot.COMMENT = "";
			}
			
			if (pos < l - 1) {
				args.NotClearCarryYard = true;
				args.shotNo++;
				args.shotTraceId++;
				if (obj && (obj[pos].SHOT_NO + 1 >= obj[pos+1].SHOT_NO)) {
					// 今回追加するショットとすでにあるショットのSHOT_NOが等しい場合は
					// すでにあるショットのSHOT_NOを増加してSHOT_NOが重複しないようにします。
					//
					// 今回追加するショットとすでにあるショットのSHOT_NOが等しくない場合、
					// つまり、後ろに追加すると選んだショットとすでに後ろにあるショットのSHOT_NOが連続していない場合、
					// すでにあるショットのSHOT_NOを変更せずに今回のショットを追加します。
					this.increaseShotNo(args);
				}
				// SHOT_NOが連続していない場合でもSHOT_TRACE_ID は常に連続しているので
				// SHOT_TRACE_ID はインクリメントします
				this.increaseShotID(args);
			}
			
			// 地点情報有りの場合、シミュレートモード
			if (args && args.lat) {
				if (l > 3) {
					return;
				}
				
				shot.LAT = args.lat;
				shot.LON = args.lon;
			} else {
				// 末尾の場合、前のショットとカップの中間地点に置く
				if (pos == l - 1 || (pos == 0 && l == 0)) {
					var cups = this.getCourseHoleHazard(args);
					
					if (cups) {
						shot.LAT = (cups[0].LAT + shot.LAT) / 2;
						shot.LON = (cups[0].LON + shot.LON) / 2;
					}
				} else {
					shot.LAT = (obj[pos+1].LAT + obj[pos].LAT) / 2;
					shot.LON = (obj[pos+1].LON + obj[pos].LON) / 2;
				}
			}
			
			
			shot.SHOT_NO++;
			//shot.SHOT_TRACE_ID = this.getShotTraceIdMax(args) + 1;
			shot.SHOT_TRACE_ID++;
			
			if (!obj) {
				this.setShotTraceList(null, shot);
			} else {
				obj.splice(pos+1, 0, shot);
			}
		},
		
		
		
		updateShotTraceYard : function(args, id, yard) {
			var obj = this.getShotTraceList(args),
				l = obj.length,
				i,
				ret;
			
			for (i = 0; i < l; i++) {
				if (obj[i]['SHOT_TRACE_ID'] == id) {
				//if (obj[i].SHOT_NO == id) {
					
					obj[i].CARRY_YARD = yard;
					
					return;
				}
			}
		},
		
		
		
		getShotTraceIdMax : function(args) {
			var obj = this.getShotTraceList(args),
				l,
				ret;
			
			if (!obj) {
				return 0;
			}
			
			l = obj.length;
			if (obj.length == 0) {
				return 0;
			} else {
				return obj[l-1].SHOT_TRACE_ID;
			}
		},
		
		
		
		testShotNoDuplicate : function(data, test) {
			var i, j, l = data.length;
			
			if (l < 2) {
				return false;
			}
			
			for (i = 0; i < l; i++) {
				if (test) {
					if (data[i].SHOT_NO == test) {
						return true;
					}
				} else {
					for (j = 0; j < l; j++) {
						if (i == j) {
							continue;
						}
						if (data[i].SHOT_NO == data[j].SHOT_NO) {
							return true;
						}
					}
				}
			}
			return false;
		},
		
		
		
		deleteShot : function(args) {
			var obj = this.getShotTraceList(args),
				pos,
				i = 0,
				l;
			
			pos = this.detectShot(args.shotTraceId, obj);
			
			if (pos > 0) {
				obj[pos - 1].CARRY_YARD = 0;
			}
			
			obj.splice(pos, 1);
			
			obj.sort(this.sortShotTrace);
			
			/*
			l = obj.length;
			for (i = pos; i < l; i++) {
				if (obj[i].SHOT_NO > 1) {
					obj[i].SHOT_NO--;
				}
				if (obj[i].SHOT_TRACE_ID > 1) {
					obj[i].SHOT_TRACE_ID--;
				}
			}
			*/
		},
		
		
		
		increaseShotNo : function(args) {
			var i,
				obj = this.getShotTraceList(args),
				l = obj.length,
				flag = false;
			
			for (i = 0; i < l; i++) {
				if (obj[i].SHOT_TRACE_ID == args.shotTraceId) {
					flag = true;
					
					if (i != 0) {
						if (args && args.NotClearCarryYard) {
							
						} else {
							obj[i-1].CARRY_YARD = 0;
						}
					}
				}
				
				if (flag == true) {
					obj[i].SHOT_NO++;
				// SHOT_TRACE_IDはインクリメントしません
				}
			}
		},

		increaseShotID : function(args) {
			var i,
				obj = this.getShotTraceList(args),
				l = obj.length,
				flag = false;
			
			for (i = 0; i < l; i++) {
				if (obj[i].SHOT_TRACE_ID == args.shotTraceId) {
					flag = true;
				}
				
				if (flag == true) {
					obj[i].SHOT_TRACE_ID++;
				}
			}
		},
		
		
		
		decreaseShotNo : function(args) {
			var i,
				obj = this.getShotTraceList(args),
				l = obj.length,
				flag = false,
				pos;
			
			if (args.shotNo == 1) {
				// 先頭のショットの打数を減らそうとした場合
				alert(this.ErrorMessage.DecreaseFirstShotNo);
				return;
			}
			
			pos = this.detectShot(args.shotTraceId, obj);
			
			
			// 前のSHOT_NOが連続していた場合は減打不可
			if (pos > 0 && (obj[pos-1].SHOT_NO + 1 == obj[pos].SHOT_NO || obj[pos-1].SHOT_NO == obj[pos].SHOT_NO)) {
				alert(this.ErrorMessage.ShotNoDecrementDuplicate);
				return;
			}
			
			for (i = pos; i < l; i++) {
				obj[i].SHOT_NO--;
				// SHOT_TRACE_IDはデクリメントしません
			}
		},
		
		
		
		setShotTraceMyWeapon : function(shotParams, myweapon) {
			var shot_trace_list = this.getShotTraceList(shotParams),
				shot_trace_length = shot_trace_list.length,
				i;
			
			for (i = 0; i < shot_trace_length; i++) {
				if (shot_trace_list[i].SHOT_TRACE_ID == shotParams.shot.SHOT_TRACE_ID) {
					
					shot_trace_list[i].MY_WEAPON_ID = myweapon.MY_WEAPON_ID;
					shot_trace_list[i].CLUB_NAME = myweapon.CLUB_NAME;
					
					return;
				}
				
			}
		},
		
		
		
		getMyWeapon : function(args) {
			var ret = [],
				i, l,
				weapon,
				club,
				short_name;
			
			if (!this._data.myweapon || !this._data.myweapon.M_MY_WEAPON) {
				return;
			}
			
			l = this._data.myweapon.M_MY_WEAPON.length;
			for (i = 0; i < l; i++) {
				weapon = this._data.myweapon.M_MY_WEAPON[i];
				club = ggsb.ClubItems[weapon.CLUB_NAME];
				short_name = club.s_name;
				// フィルタリング指定で、該当データ配列を返送
				if (args && args.filter) {
					if (parseInt(ggsb.ClubTypes[short_name] & args.filter) != 0) {
						ret.push(weapon);
					}
				}
				// マイウェポンID指定で該当データのみ返送
				else if (args && args.myWeaponId) {
					if (weapon.MY_WEAPON_ID == args.myWeaponId) {
						return weapon;
					}
				}
				// 全データ返送
				else {
					ret.push(weapon);
				}
			}
			
			return ret;
		},
		
		
		
		updateComment : function(args) {
			var i,
				obj = this.getShotTraceList(args),
				l = obj.length,
				pos;
			
			pos = this.detectShot(args.shotTraceId, obj);
			
			obj[pos].COMMENT = args.comment;
		},
		
		
		
		getUser : function() {
			return this._data.round.M_USER;
		},
		
		
		
		getClub : function(args) {
			return this._data.cdclub.M_CD_CLUB_List;
        },
        getReviseFlg: function (args) {
            return this._data.round.T_ROUND_RECORD.REVISE_FLG
        },
        
        getFromDeviceType: function (args) {
            return this._data.round.T_ROUND_RECORD.FROM_DEVICE_TYPE
        },
		
		// My戦略ノート
		getStrategyList : function(args) {
			var obj = this._data.mystrategy.T_MY_STRATEGY_POINT_LIST,
				ret,
				i, l;
			
			if (!obj) {
				this._data.mystrategy.T_MY_STRATEGY_POINT_LIST = [];
				return null;
			}
			l = obj.length;
			
			
			for (i = 0; i < l; i++) {
				ret = obj[i];
//				if (ret && ret[0] && ret[0].HOLE_NO == args.holeId) {
				if (ret && ret[0] && ret[0].GOLF_COURSE_ID == args.courseId && ret[0].GOLF_COURSE_HOLE_ID == args.courseHoleId) {
					
					return ret;
				}
			}
			
			return null;
		},
		
		
		
		setStrategyPoint : function(args) {
			var obj = this.getStrategyList(args),
				i,
				l;
			
			if (!obj) {
				return;
			}
			
			l = obj.length;
			for (i = 0; i < l; i++) {
				if (obj[i].STRATEGY_POINT_ID == args.pointId) {
					obj[i].STRATEGY_POINT_TYPE = ~~(args.type);
					return;
				}
			}
		},
		
		
		
		deleteStrategyPoint : function(args) {
			var obj = this.getStrategyList(args),
				i,
				l;
			
			if (!obj) {
				return;
			}
			
			l = obj.length;
			for (i = 0; i < l; i++) {
				if (obj[i].STRATEGY_POINT_ID == args.pointId) {
					
					obj.splice(i, 1);
					
					
					return;
				}
			}
		}
	};
	
	Data.prototype = prot;
	
	ggsb.Data = $.extend(Data, {});
	
};

