
var _sysData ={
	_load:function( key , param ,  after , isDef ){
		var url;
		if( isDef ){
			url = _urlMap.sysDef[ key ];
		}else{
			url = _urlMap.sysData[ key ];
		};

		_disp.request( "php/" + url , param , function( obj ){
			_sysData[ key ] = obj;
			if( after && after.constructor == Function ){
				after();
			};
		} );
	},
	//対象テーブルを複数指定して連続ロードする。
	_loadChain:function( aryKey , param ,  after ){
		var idx = 0;
		var functionLoad = function(){
			if( _U.isIdx( idx , aryKey ) ){
				_sysData._load( aryKey[ idx ] , param , functionLoad );
			}else{
				after();
			};
			idx ++ ;
		};
		functionLoad();
	},
	//sysDefを対象に、連続ロードを行う。
	_loadDef:function( after ){

		var aryF = [];
		var aryK = [];
		var i = 0;
		var loadCaller = function( ){
			var key = aryK[i];
			_sysData._load( key , null , aryF[ i + 1 ] , true );
			i ++ ;
		};
		for( var key in _urlMap.sysDef ){
			aryK.push( key );
			aryF.push(loadCaller);
		};
		aryF.push( after );
		loadCaller( );
	},
	_getMode:{
		asTable	:	"asTable" ,
		expDB	:	"expDB" ,
		uqAndPk	:	"uqAndPk" ,
		rlt	:	"rlt",
		asWTable	:	"asWTable",
		joinTbl	:	"joinTbl"
	},
	_rltType:{
		p:"p",
		s:"s",
		c:"c",
		r:"r"
	},
	_getData:function(){
		var sortByOrder = function( a, b ){
			var ret = 0;
			if( a.hasOwnProperty( "order" ) ){
				ret = _MySort.numAsc( a.order , b.order ) 
			};
			if( ret == 0 && a.hasOwnProperty( "id" ) ){
				ret = _MySort.numAsc( a.id , b.id ) 
			};
			return ret;
		};
		//colsが対象テーブルのユニークを含むか、のチェック。
		var checkColsInUq = function( table , cols , uq ){
			var targUq = uq[ table ];
			//対象テーブルのユニークセットでループ
			for( var i = 0 ; _U.isIdx( i , targUq ) ; i ++ ){
				var colsFind = true;
				var uCols = targUq[ i ].cols;
				//ユニークの列の一覧でループ
				for( var k = 0 ; _U.isIdx( k , uCols ) ; k ++ ){
					if( _U.find( uCols[ k ].colId , cols ) == -1 ){
						colsFind = false;
						break;
					};
				};
				//ブレイクしていなければ、即ち、ユニーク列が全て、colsに含まれる。
				if( colsFind ){
					return true;
				};
			};
			return false;
		};
		//joinTblで再帰的に利用する
		var getRTable = function( tableId , rltObj , aryChain ){
			var ret =[];
			if( ! aryChain ){
				aryChain =[tableId];
			};
			var rls = rltObj[ tableId ];
			for( var i = 0 ; _U.isIdx( i , rls ) ; i++ ){
				//親、兄弟であるならば対象とする。
				if( rls[i].type == _sysData._rltType.c || rls[i].type == _sysData._rltType.r ){
					continue;
				};
				//既にchainにtableIdがあれば、対象としない。
				if( _U.find( rls[i].table , aryChain ) != -1 ){
					continue;
				};
				//自身の親情報にIDと表を指定して追加する。
				ret.push( { table: rls[i].table , rlts:[ rls[i].id ]} );

				//再帰的に呼び出す。
				var wkArray = aryChain.concat();
				wkArray.push( rls[i].table );
				var retRc = getRTable( rls[i].table , rltObj , wkArray );
				for( var j = 0 ; _U.isIdx( j ,retRc ) ; j ++ ){
					//戻り値のrltsの先頭に、rls[i].idを追加する。
					retRc[ j ].rlts.unshift( rls[i].id );
				};
				ret = ret.concat( retRc );
			};
			return ret;
		};
		return function( key , mode ){
			var ret =[];
			var data = this[ key ];
			if( ! data ){
				return;
			};
			if( ! mode || mode == this._getMode.asTable ){
				for( var i = 0 ; _U.isIdx( i , data.table ) ; i++ ){
					var objRow ={};
					for( var j = 0 ; _U.isIdx( j , data.head ) ; j ++ ){
						objRow[ data.head[j] ] = data.table[i][j];
					};
					ret.push( objRow );
				};
				ret.sort( sortByOrder );
			}else if( mode == this._getMode.expDB ){
				if( data.files && data.files.constructor == Array ){
					ret = data.files.concat();
				};
			}else if( mode == this._getMode.uqAndPk ){
				ret ={};
				/*以下の形式に整形する。
				{ <tableId>:[
					{ id : "id or PK" , cols:[{id:uqColId , colId:colId }]}
				]}*/

				//data.uq
				//data.col
				//表定義を表形式で取得
				var cols = _sysData._getData( "col" );
				//PKを追加する。
				for( var i = 0 ; _U.isIdx( i , cols ) ; i ++ ){
					if( cols[i].pk > 0 ){
						if( ! ret.hasOwnProperty( cols[i].tableId ) ){
							ret[ cols[i].tableId ] =[{id:"PK",cols:[]}];
						};
						ret[ cols[ i ].tableId ][ 0 ].cols.push( { id : null , colId : cols[i].id} );
					};
				};
				//ユニーク一覧を直接チェックし、情報を追加してゆく。
				for( var i = 0 ; _U.isIdx( i , data.table ) ; i ++ ){
					if( ! ret.hasOwnProperty( data.table[ i ][ 1 ] ) ){
						ret[ data.table[ i ][ 1 ] ] =[];
					};
					var obj = { id:data.table[ i ][ 0 ] , cols : [ ] };
					for( var j = 0 ; _U.isIdx( j , data.table[ i ][ 2 ] ) ; j ++ ){
						obj.cols.push( { 
								id : data.table[ i ][ 2 ][ j ][ 0 ],
								colId : data.table[ i ][ 2 ][ j ][ 2 ]
						} );
					};
					ret[ data.table[ i ][ 1 ] ].push( obj );
				};
			}else if( mode == this._getMode.rlt ){
				ret = {};
				/*以下の形式に整形する。
				{ <tableId>:[
					{ id : "rltId" , table : "tId" , type :_rltType , cols:[
						{id:rCId , myCId:colId , tCId:colId}
					]}
				]}*/
				var uqAndPk =  _sysData._getData( "uq" , _sysData._getMode.uqAndPk  );
				//関連付け一覧を直接チェックし、情報を追加してゆく。
				for( var i = 0 ; _U.isIdx( i , data.table ) ; i ++ ){
					//とりあえず、分かり難いので、一通り変数で拾う。
					var rlt = data.table[ i ];
					var rltId = rlt[ 0 ];
					var cTbl = rlt[ 1 ];
					var pTbl = rlt[ 2 ];
					var rC = rlt[ 3 ];
					var cType = this._rltType.r;
					var pType = this._rltType.r;

					//一通りの列IDを取得する。
					var cCols = [];
					var pCols = [];
					for( var j = 0 ; _U.isIdx( j , rC ) ; j ++ ){
						cCols.push( rC[ j ][ 2 ] );
						pCols.push( rC[ j ][ 3 ] );
					};
					//ユニークであるか、のチェックを行う。
					var cIsUq = checkColsInUq( cTbl , cCols , uqAndPk );
					var pIsUq = checkColsInUq( pTbl , pCols , uqAndPk );
					if( cIsUq && pIsUq ){
						cType = this._rltType.s;
						pType = this._rltType.s;
					}else if( cIsUq ){
						cType = this._rltType.c;
						pType = this._rltType.p;
					}else if( pIsUq ){
						cType = this._rltType.p;
						pType = this._rltType.c;
					};
					if( ! ret.hasOwnProperty( cTbl ) ){
						ret[ cTbl ] = []
					};
					if( ! ret.hasOwnProperty( pTbl ) ){
						ret[ pTbl ] = []
					};
					var objC = {
						id	:	rltId,
						table	:	pTbl,
						type	:	cType,
						cols	:	[]
					};
					var objP = {
						id	:	rltId,
						table	:	cTbl,
						type	:	pType,
						cols	:	[]
					};
					for( var j = 0 ; _U.isIdx( j , rC ) ; j ++ ){
						objC.cols.push({
							id:rC[ j ][ 0 ],
							myCId:rC[ j ][ 2 ],
							tCId:rC[ j ][ 3 ]
						})
						objP.cols.push({
							id:rC[ j ][ 0 ],
							myCId:rC[ j ][ 3 ],
							tCId:rC[ j ][ 2 ]
						})
					};
					ret[ cTbl ].push( objC );
					ret[ pTbl ].push( objP );
				};
			}else if( mode == this._getMode.asWTable ){
				/*以下の形式に整形する。
				[
					{
						head1 : value,
						head2 : value,
						･･･中略･･･
						_children:[
							{
								childHead1:value,
								childHead2:value,
								･･･以下略･･･
							}
						]
					}
				]
				*/
				for( var i = 0 ; _U.isIdx( i , data.table ) ; i++ ){
					var objRow ={};
					for( var j = 0 ; _U.isIdx( j , data.head ) ; j ++ ){
						objRow[ data.head[j] ] = data.table[i][j];
					};

					objRow._children = [];
					var childData = data.table[i][j];
				
					for( var k = 0 ; _U.isIdx( k , childData ) ; k++ ){
						var childRow ={};
						for( var l = 0 ; _U.isIdx( l , data.head2 ) ; l ++ ){
							childRow[ data.head2[l] ] = childData[k][l];
						};
						objRow._children.push( childRow );
					};

					objRow._children.sort( sortByOrder );
					ret.push( objRow );
				};
				ret.sort( sortByOrder );
			}else if( mode == this._getMode.joinTbl ){
				/*以下の形式に整形する。
				{ <tableId>:[
					{ table : "tId" , rlts:[
						relationId
					]}
				]}*/
				ret = {};
				var rlt =  _sysData._getData( "rlt" , _sysData._getMode.rlt  );
				for( var key in rlt ){
					ret[key] = getRTable( key , rlt );
				};
			};
			return ret;
		};
	}(),
	//指定されたtableから、key=valueであるものを探す。
	//第二引数は[ { key : "id" , value : 1},{ key : "order" , value : 0} ]のように指定する。
	//これら第2引数の条件、はandでチェックされる。
	//isUqを指定した場合、1件見つかった時点でbreakし、値を返す。
	//戻り型は配列で、見つかったレコードそのものを返す。
	//呼び出す際は、最終的な比較が!=で行われる点に注意する。
	//"",null,0等は同値と見なされる。
	_tblFind : function( targTable , aryKeyValue , isUq ){
		var ret = [];
		for( var i = 0 ; _U.isIdx( i , targTable ) ; i ++ ){
			var blFind = true;
			for( var j = 0 ; _U.isIdx( j , aryKeyValue ) ; j ++ ){
				if( ! aryKeyValue[j] )continue;
				if( ! aryKeyValue[j].hasOwnProperty( "key" ) )continue;
				if( ! aryKeyValue[j].hasOwnProperty( "value" ) )continue;
				var key = aryKeyValue[j].key;
				var value = aryKeyValue[j].value;
				if( ! targTable[ i ].hasOwnProperty( key ) || targTable[ i ][ key ] != value ){
					blFind = false;
					break;
				};
			};
			if( blFind == false ){
				continue;
			};
			ret.push( targTable[ i ] );
			if( isUq ) break;
		};
		return ret;
	}
};

