/**
 * There are basically two kinds of alias in CLDR:
 * 1. locale alias e.g. 
 *    in xml, <alias source="locale" path="......"/>, 
 *    in gernated JSON bunle, xxxx@localeAlias:{'target':'xxx', 'bundle':'xxxx'}
 * 2. other locale alias e.g.
 *    in xml, currently only like <alias source="fr" path="//ldml"/>
 * #1 is supported by this 'alias.js', 
 * #2 is covered by 'specialLocale.js' and may need enhancement for future CLDR versions.
 */

djConfig={baseUrl: "../../../dojo/"};

load("../../../dojo/dojo.js");
load("../jslib/logger.js");
load("../jslib/fileUtil.js");
load("cldrUtil.js");

dojo.require("dojo.i18n");

var dir/*String*/ = arguments[0];// ${dojo}/dojo/cldr/nls
var logDir = arguments[1];
var logStr = "";

//Add new bundles to the list so that they will be aliased according to the ldml spec. 
var BUNDLES = ['gregorian','hebrew','islamic','islamic-civil','buddhist'];

var LOCALE_ALIAS_MARK = '@localeAlias';
var LOCALE_ALIAS_SOURCE_PROPERTY = 'source';
var LOCALE_ALIAS_TARGET_PROPERTY = 'target';
var LOCALE_ALIAS_TARGET_BUNDLE = 'bundle';
var localeAliasPaths = [];/**/
var records = {};/*{property : boolean}, record whether a property has been calculated for alias path*/
var updated = false;

print('alias.js...');

for(var i = 0; i < BUNDLES.length; i++){
	var regExp = new RegExp('\/' + BUNDLES[i] + '\.js$'); //e.g. new RegExp('\/gregorian\.js$')
	var fileList = fileUtil.getFilteredFileList(dir, regExp, true);
	
	for(var j = 0; j < fileList.length; j++){
		var jsFileName = new String(fileList[j]); //Java String
		var jsFilePath = jsFileName.split("/");
		var locale = jsFilePath[jsFilePath.length-2];
		if(locale=="nls"){continue;} // no need for root bundle
		try{
			dojo.i18n._requireLocalization('dojo.cldr', BUNDLES[i], locale); //declare bundle						
			var bundle = dojo.i18n.getLocalization('dojo.cldr', BUNDLES[i], locale); //get bundle
			var nativeSrcBundle = getNativeBundle(jsFileName);//bundle not flattened
		}catch(e){print(e);/* simply ignore if no bundle found*/}
		
		if(!bundle) continue;
		
		updated = false;
		//logStr += locale + ":" + BUNDLES[i] + "=========================================================================\n";
		
		_calculateAliasPath(bundle);
		//logStr += "all alias paths=" + dojo.toJson(localeAliasPaths) + "\n";
				
		_processLocaleAlias(localeAliasPaths, bundle, nativeSrcBundle,locale);
		
		if(updated){
			fileUtil.saveUtf8File(jsFileName, "(" + dojo.toJson(nativeSrcBundle, true) + ")");
		}
		//logStr += '\n';
	}
	cleanLocaleAlias(fileList);
}

//fileUtil.saveUtf8File(logDir + '/alias.log',logStr+'\n');
//print('CLDR finished, please refer to logs at ' + logDir + ' for more details.');


function _calculateAliasPath(bundle){
	for(p in bundle){
		var index = p.indexOf(LOCALE_ALIAS_MARK);
		if(index >= 0 /*p like 'xxx@localeAlias6'*/){
			var localeAliasSource/*String*/ = p.substring(0,index);
			if(records[localeAliasSource]/*calculated*/){
				//logStr += p + " has been calculated, ignored\n"
				continue;
			} 
			
			var path = [];
			var aliasIndex = new Number(p.substring(index + LOCALE_ALIAS_MARK.length));
			//logStr += "aliasIndex for " + p + " is " + aliasIndex + "\n";
			var i = aliasIndex;
			while(bundle[localeAliasSource + LOCALE_ALIAS_MARK + (--i)]){}
			
			var src = localeAliasSource;
			while(bundle[localeAliasSource + LOCALE_ALIAS_MARK + (++i)]){
				var mapping = {};
				mapping[LOCALE_ALIAS_SOURCE_PROPERTY] = src;
				mapping[LOCALE_ALIAS_TARGET_PROPERTY] = bundle[localeAliasSource + LOCALE_ALIAS_MARK + i][LOCALE_ALIAS_TARGET_PROPERTY];
				mapping[LOCALE_ALIAS_TARGET_BUNDLE] = bundle[localeAliasSource + LOCALE_ALIAS_MARK + i][LOCALE_ALIAS_TARGET_BUNDLE];
				path.push(mapping);
				records[src] = true;
				src = bundle[localeAliasSource + LOCALE_ALIAS_MARK + i][LOCALE_ALIAS_TARGET_PROPERTY];
			}
			path = path.reverse();
			//logStr += "alias path calucated for " + localeAliasSource + "=" + dojo.toJson(path) + "\n";
			localeAliasPaths.push(path);
		}
	}
}

function _processLocaleAlias(localeAliasPaths/*Array*/, bundle/*JSON Obj*/, nativeSrcBundle/*JSON Obj*/,locale/*String*/){
	//Summary: Update all properties as defined by 'locale' alias mapping
	//		   E.g.'months-format-abbr@localeAlias6':{'target':"months-format-wide", 'bundle':"gregorian"},
	//		   means the array values of 'months-format-abbr' in current bundle should be
	//		   merged with(inherit or overwrite) that of 'months-format-wide' in 'gregorian' bundle
	//
	//Note:	   Currently no bundle recognition, always assume 'gregorian'.
	var processed = {};
	for(var i = 0; i < localeAliasPaths.length; i++){
		var path = localeAliasPaths[i];
		for(var j = 0; j < path.length; j++){
			var mapping = path[j];
			if(mapping[LOCALE_ALIAS_SOURCE_PROPERTY] != mapping[LOCALE_ALIAS_TARGET_PROPERTY]
			   && bundle[mapping[LOCALE_ALIAS_TARGET_PROPERTY]]/*target existed*/){
				//e.g. {'source':'months-format-abbr','target':"months-format-wide",'bundle':"gregorian"},
				//currently source and target bundles are the same - gregorian
				if(processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]]){/*haven't been processed*/
					//logStr += "!" + mapping[LOCALE_ALIAS_SOURCE_PROPERTY] +" has been processed for alias, escaped\n";
					continue;
				}
				_updateLocaleAlias(bundle, mapping[LOCALE_ALIAS_SOURCE_PROPERTY], bundle, 
								   mapping[LOCALE_ALIAS_TARGET_PROPERTY], nativeSrcBundle);	
				processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]] =  true;
			}else{
				//For other non-gregorian calendars. e.g. "hebrew" etc.
				//Get the bundle according to the locale.
				var targetBundle = dojo.i18n.getLocalization('dojo.cldr', mapping[LOCALE_ALIAS_TARGET_BUNDLE], locale); 
				if(processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]]){//If being processed, continue;
					continue;
				}
				_updateNoneGregAlias(bundle, mapping[LOCALE_ALIAS_SOURCE_PROPERTY], targetBundle, 
								   mapping[LOCALE_ALIAS_TARGET_PROPERTY], nativeSrcBundle);	
				processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]] =  true;
			}
		}
	}
}
/*
* This function will flatten the source bundle for non-gregorian ones by searching in the bundle files generated from the ldml spec which have terms like:
* "'months-standAlone-abbr@localeAlias131':{'target':"months-format-abbr",'bundle':"hebrew"},".
*   Parameters:
*   	sourceBundle: The bundles which need to be aliased.
*   	aliasSource:  The source mark string. 'months-standAlone-abbr' for example.
*   	targetBundle: The aliased bundle. 'hebrew' for example.
*   	aliasTarget:  The target mark string. 'months-format-abbr' for example.
*   	nativeSrcBundle: The final flattened bundle file.
* According to the dojo way of fetching resource bundle, this function will firstly check the bundle under the appointed
* locale. If the wanted calendar bundle is not under the locale, the root calendar bundle will be fetched. If the non-gregorian
* bundle in the root can not be found, dojo will finally get the root gregorian bundle.
*/
function _updateNoneGregAlias(sourceBundle/*JSON Obj*/, aliasSource/*String*/, targetBundle/*JSON Obj*/, aliasTarget/*String*/, nativeSrcBundle/*JSON Obj*/){
    for (var sKey in sourceBundle) {
        if (sKey.indexOf(aliasSource) == 0 && !nativeSrcBundle[sKey] && targetBundle[sKey]&&!compare(sourceBundle[sKey],targetBundle[sKey])) {
            nativeSrcBundle[sKey] = targetBundle[sKey];
            sourceBundle[sKey] = targetBundle[sKey];
            updated = true;
        }
        else 
            if (sKey.indexOf(aliasSource) == 0 && nativeSrcBundle[sKey] && dojo.isArray(sourceBundle[sKey]) && dojo.isArray(targetBundle[sKey])) {
                for (var i = 0; i < sourceBundle[sKey].length; i++) {
                    if (sourceBundle[sKey][i] == undefined) {
                        sourceBundle[sKey][i] = targetBundle[sKey][i];
                        updated = true;
                    }
                }
                if (sourceBundle[sKey].length < targetBundle[sKey].length) {
                    sourceBundle[sKey] = sourceBundle[sKey].concat(targetBundle[sKey].slice(sourceBundle[sKey].length));
                    updated = true;
                }
                if (updated) {
                    nativeSrcBundle[sKey] = sourceBundle[sKey];
                }
            }
    }
}
function _updateLocaleAlias(sourceBundle/*JSON Obj*/,aliasSource/*String*/, targetBundle/*JSON Obj*/,
							aliasTarget/*String*/, nativeSrcBundle/*JSON Obj*/){
		//single property
		if(!nativeSrcBundle[aliasSource] && nativeSrcBundle[aliasTarget]//no this property in current locale
		   && !compare(sourceBundle[aliasSource], targetBundle[aliasTarget])){
			// then should inherit from alias target (as defined by 'locale' alias)
			//logStr += '1 '+aliasSource + "=" + sourceBundle[aliasSource] + " is replaced with " + aliasTarget + "=" + targetBundle[aliasTarget]+'\n';
			//sourceBundle[aliasSource] =  targetBundle[aliasTarget];
			nativeSrcBundle[aliasSource] =  targetBundle[aliasTarget];
			sourceBundle[aliasSource] = nativeSrcBundle[aliasSource];
			updated = true;	
		}else if(nativeSrcBundle[aliasSource] && dojo.isArray(sourceBundle[aliasSource]) 
		         && dojo.isArray(targetBundle[aliasTarget])){
			if(sourceBundle[aliasSource].length > targetBundle[aliasTarget].length){
				//logStr +="Error:" + aliasSource + ".length > " +  aliasTarget + ".length \n";
			}
			//array property, see if need inherit
			for(var i = 0; i < sourceBundle[aliasSource].length; i++){
				if(sourceBundle[aliasSource][i] == undefined){//need inherit
					//logStr += '2 ' + aliasSource + "["+i+"]=" +sourceBundle[aliasSource][i]+" is replaced with " + aliasTarget+"["+i+"]="+targetBundle[aliasTarget][i]+'\n';
					sourceBundle[aliasSource][i] =  targetBundle[aliasTarget][i];
					updated = true;	
				}// otherwise no change and use current value
			}
			if(sourceBundle[aliasSource].length < targetBundle[aliasTarget].length){
				//logStr +='3 ' + aliasSource +' from ' + sourceBundle[aliasSource].length +' to ' 
				//		  + (targetBundle[aliasTarget].length-1) + ' are copied from ' 
				//		  +aliasTarget + '='+ targetBundle[aliasTarget] +'\n';
				sourceBundle[aliasSource] = sourceBundle[aliasSource].concat(
											targetBundle[aliasTarget].slice(sourceBundle[aliasSource].length));
				updated = true;	
			}
			if(updated){
				nativeSrcBundle[aliasSource] = sourceBundle[aliasSource];
			}
		}
}

function cleanLocaleAlias(fileList/*Array*/){
	for(var i = 0; i < fileList.length; i++){
		var fileName = new String(fileList[i]); //Java String
		try{
			var bundle = getNativeBundle(fileName);//bundle not flattened
		}catch(e){print(e);/* simply ignore if no bundle found*/}
		
		var newBundle = {};
		var needUpdate = false;
		for(p in bundle){
			if(p.indexOf(LOCALE_ALIAS_MARK) < 0){
				newBundle[p] = bundle[p];
			}else{
				needUpdate = true;
			}
		}
		if(needUpdate){
			fileUtil.saveUtf8File(fileName, "(" + dojo.toJson(newBundle, true) + ")");
			//logStr += "cleaned @localAlias for " + fileName + "\n";
		} 
	}
}
