/**
    针对于表类型的数据进行管理
    
    Feartures : 
        1. 提供CRUD接口
        2. 内置状态控制


    Update Note:
        + 2014.7 :Created

    @module DataManager
    @submodule DataManager-Table
*/
_stDefine("dataManager-table", function(st) {
	var isArray = st.isArray,
		isPlainObj = st.isPlainObject,
		_states = ["_$new", "_$selected", "_$updated", "_$deleted"],
		_dtConfig = {
			//分页设置
			pageInf: {
				pageSize: 20,
				groupSize: 20,
				page : 1,
				total: 0
			},
			getField : {
				pageInf : "pageInf",
				result :"result"
			}
		};

	st.dataManager.add("DataTable", {
		init: function(op) {
			var dm = this;
			st.mix(true, op, _dtConfig);

			dm.$store = [];

			if (op.crud) {
				dm.crud.forEach(function(type, conf) {
					dm.initPolicy(conf);
					conf.set && dm.initPolicy(conf.set);
				})
			} else
				op.crud = {};

			//注册处理设置数据方法
			dm._Flow.onBefore("setData", "handleResult", handleResult);
		},
		getKey: function() {
			return this.op.key;
		},
		checkEmpty: function(data, filter) {
			return data == null || data.length === 0;
		},
		clear: function() {
			this.$store = [];
		},
		_innerUpdate: function(config) {
			if (!config)
				return;

			var isReplace = config.updateMode === 'replace',
				updateType = config.updateType,
				filter = config.filter,
				dm = this,
				data = config.data,
				store = dm.$store,
				isOneData = !isArray(data);

			if (updateType === 'find')
				updateFindData(dm, data);
			else if (updateType === 'insert') {
				insertData(dm, data);
			} else if (updateType === 'delete') {
				deleteData(dm, config);
			} else {
				(isArray(data) ? updateData : updateOneData)(dm, data, config, isReplace, updateType === 'save');
			}
			return data;
		},
		store: function(data) {
			if (checkArray(data)) {
				this.$store = data;
			}
		},
		//单条数据更新
		updateOne: function(config) {
			if (!config)
				return;

			buildParamByOne(this, config);
			return this.update(config);
		},
		update: function(config) {
			buildCRUDConfig(this, 'update', config);
			return this.set(config);
		},
		insert: function(config) {
			buildCRUDConfig(this, 'insert', config);
			return this.set(config);
		},
		save: function(config) {
			buildCRUDConfig(this, 'save', config);
			return this.set(config);
		},
		_innerSearch: function(config) {
			return findDm(this, config);
		},
		findOne: function(config) {
			var success;
			if (config) {
				buildParamByOne(this, config);
				success = config.success;
			} else {
				config = {};
			}

			if (success) {
				config.success = function(data) {
					success(data && data[0]);
				}
			}
			return this.find(buildCRUDConfig(this, 'findOne', config, true));
		},
		find: function(config) {
			buildCRUDConfig(this, 'find', config, true)
			initFindConfig(this.op, config);
			return this.get(config);
		},
		removeOne: function(config) {
			if (!config)
				return;

			buildParamByOne(this, config);
			return this.remove(config);
		},
		remove: function(config) {
			return this.update(buildCRUDConfig(this, 'remove', config));
		},
		findWithStates: function(states, config) {
			var stateFilter = [];

			states.forEach(function(state) {
				result[state] = [];
			})

			stateFilter = function(item) {
				states.some(function(state) {
					if (item[state]) {
						result[state].push(item);
						return true;
					}
				})
			}
			return result;
		},
		findByState: function(state, config) {

		},
		setDataSerive: function(conf) {

		}
	});

	function checkArray(data) {
		if (isArray(data))
			return true;

		console.log("存储的数据不正确!");
	}

	function buildCRUDConfig(dm, type, conf, isFind) {
		var defConf = dm.op.crud[type];
		if (!conf)
			conf = {};

		defConf && dm.buildPolicy(conf, defConf);

		if (!isFind && conf.updateType == null)
			conf.updateType = type;

		return conf;
	}

	function initFindConfig(op, config) {
		var changed, pageInf = config.pageInf,
			oldPageInf = op.pageInf;

		if (config.update && !config.updateType)
			config.updateType = 'find';

		if (config.way)
			return;

		if(pageInf && checkChanged(pageInf,oldPageInf,["page","pageSize"]))
			changed = true;
		else
			changed = checkChanged(config,op,["order","group"]);;

		changed && (config.way = 'ds');
	}

	function checkChanged(obj,oldObj,fields){
		var value,changed;
		fields.some(function(field){
			value = obj[field];
			if((value != null) && value == oldObj[field]){
				changed = true;
				return true;
			}
		})
		return changed;
	}

	//生成操作单个的param
	function buildParamByOne(dm, policy) {
		var params, key, keyValue, type;

		if (policy && (params = policy.params) != null) {
			type = typeof params;
			if (type !== 'function') {
				if (type !== 'object' && (key = dm.getKey())) {
					keyValue = params;
					policy.params = params = {};
					params[key] = keyValue;
				}
			}
		}
	}

	function handleResult(e, dm, op, policy, isTrigger) {
		var data = policy.data,pageInf;
		if(data && (pageInf = data[op.getField.pageInf])){
			st.mergeObj(op.pageInf,pageInf);
			policy.data = data[op.getField.result];
		}
	}

	function updateFindData(dm, data) {
		dm.store(data || []);
	}

	function insertData(dm, data) {
		var store = dm.$store;
		if (isArray(data))
			dm.$store = store.concat(data);
		else
			store.push(data);
	}

	function updateItemByFilter(store, data, filter, isReplace) {
		var isUpdated;
		//根据条件检索
		store.forEach(function(item, i) {
			if (filter(item, i)) {
				if (isReplace)
					store[i] = data;
				else
					st.mergeObj(item, data);

				isUpdated = true;
				return false;
			}
		})
		return isUpdated;
	}

	function updateOneData(dm, data, config, isReplace, saveMode) {
		var isUpdated, store = dm.$store;

		if (store.length && config.filter) {
			isUpdated = updateItemByFilter(store, data, config.filter, isReplace);
		}

		//没有更新时插入数据
		saveMode && isUpdated || insertData(dm, [data]);
		return true;
	}

	function updateData(dm, data, config, isReplace, saveMode) {
		var filter, store = dm.$store,
			key = dm.getKey(),
			keyValue, updateNum = 0;

		if (store.length && key) {
			//通过Key来更新
			data.forEach(function(updateItem, i) {
				keyValue = updateItem[key];
				if (!updateItemByFilter(store, updateItem, function(item) {
					return item[key] === keyValue;
				}, isReplace)) {
					//找不到更新项时,插入数据
					if (saveMode) {
						updateNum++;
						insertData(dm, updateItem);
					}
				} else
					updateNum++;
			})
		} else if (saveMode) {
			insertData(dm, data);
			updateNum = data.length;
		}
		return updateNum;
	}

	function findDm(dm, config) {
		var store = dm.$store,
			result = [];

		if (store.length === 0)
			return result;

		if (config && config.filter) {
			forEachByFitler(store, config, function(item) {
				result.push(item);
			}, true);
			return result;
		}
		return result.concat(store);
	}

	function forEachByFitler(data, config, handle, filterMode) {
		var filter, pageInf, index,
			start = 0,
			end = data.length,
			item;

		if (end === 0)
			return;

		if (config) {

			filter = config.filter;
			//判断filterMode下,filter为空时退出
			if (!filter && filterMode)
				return;

			pageInf = config.pageInf;
			//根据分页信息设置检索范围
			if (pageInf && pageInf.page) {
				st.mix(pageinf, _dtConfig.pageInf);
				start = (pageInf.page - 1) * pageInf.pageSize;
				start + pageInf.pageSize > end && (end = start + pageInf.pageSize);
			}
		}

		if (filter) {
			for (; start < end; start++) {
				item = data[start];
				if (filter(item, start, data)) {
					index = handle(item, start, data);
					if (index != null) {
						start = index;
					}
				}
			}
		} else {
			for (; start < end; start++) {
				index = handle(item, start, data);
				if (index != null) {
					start = index;
				}
			}
		}
	}

	function deleteData(dm, config) {
		var filter, store = dm.$store,
			count = 0,
			start = 0,
			end = store.length,
			index, item, handle;

		if (end === 0)
			return;

		if (config && (filter = config.filter)) {
			if (config.preDelete) {
				handle = function(item, index) {
					setState(item, _states[3], true);
				}
			} else {
				handle = function(item, index) {
					store.splice(index, 1);
					count++;
					return --index;
				}
			}
			forEachByFitler(store, config, handle, true);
		} else
			dm.$store = [];

		return count;
	}

	function setState(item, type, value) {
		item[type] = value;
	}
})

// policy = {
// 	get: {
// 		//获取的方式,auto默认方式;dm,只用dm获取;ds,从
// 		way: ""
// 	},
// 	set: {

// 	},
// 	dataServices: [{
// 		//数据服务类型
// 		dsType: str,
// 		//过滤参数
// 		param: obj,
// 		//过滤器
// 		fitler: fn | obj
// 		//更新的数据
// 		data: obj,
// 		//成功以后执行的方法
// 		success: success,
// 		//失败以后执行的方法
// 		error: error

// 	}]
// }

// //服务端的user数据转成前端model数据
// var userData = {
// 	id: 1,
// 	name: "user1",
// 	age: 20,
// 	role: "tester",
// 	//关联projectid
// 	projectId: 1
// }
// //项目数据的model数据
// var projectData = {
// 	id: 1
// 	name: "smartjs",
// 	ver: "0.3"
// }

// //创建一个object的对象
// var user = dataManager.create("object", {
// 	//设置主键字段
// 	key: "id",
// 	//get动作的策略
// 	get: {
// 		//定义数据服务
// 		dataServices: {
// 			//ajax数据服务
// 			dsType: "ajax",
// 			//默认的请求url地址;根据id查询
// 			url: "services/user/{id}",
// 			//url规则映射
// 			fieldMapping: {
// 				//project的查询地址
// 				project: "services/project/{projectId}"
// 			}
// 		}
// 	}
// })

// //首先通过id=1的条件,查询user
// user.get({
// 	//设置查询参数,默认匹配key字段
// 	params: 1,
// 	//执行成功,数据填充到dm,并执行成功方法
// 	success: function(result) {
// 		//进行数据渲染
// 		renderUser(result);
// 	}
// })

// //当需要查询项目信息时
// user.get({
// 	//查询的字段;dm会根据field匹配到fieldMapping的ajax设置,从而拿到数据
// 	field: "project",
// 	//执行成功,数据填充到dm,并执行成功方法
// 	success: function(result) {
// 		//进行数据渲染
// 		renderProject(result);
// 	}
// })

// //如果采用第二种方式,我们在查询玩user后,想延迟10s在加载project信息,那么应该怎么做?
// //答案是:使用dataManager的trigger

// var user = dataManager.create("object", {
// 	//设置主键字段
// 	key: "id",
// 	//get动作的策略
// 	get: {
// 		//定义数据服务
// 		dataServices: {
// 			//ajax数据服务
// 			dsType: "ajax",
// 			//默认的请求url地址;根据id查询
// 			url: "services/user/{id}"
// 		},
// 		//定义触发器
// 		trigger: [{
// 			name: "get project",
// 			//延迟10s
// 			delay: 10000,
// 			field: "project",
// 			dataServices: {
// 				//ajax数据服务
// 				dsType: "ajax",
// 				//project的查询地址
// 				url: "services/project/{projectId}",
// 			},
// 			//触发器执行成功,数据填充到dm数据的project字段中,并执行成功方法
// 			success: function(result) {
// 				//进行数据渲染
// 				renderProject(result);
// 			}
// 		}]
// 	}
// })
// //首先通过id=1的条件,查询user
// user.get({
// 	//设置查询参数,默认匹配key字段
// 	params: 1,
// 	//执行成功,数据填充到dm,并执行成功方法
// 	success: function(result) {
// 		//进行数据渲染
// 		renderUser(result);
// 	}
// })
    
Top