
// 例、loadScript('path/to/your/script.js')
// loadConst2("OPE");
// alert(typeof C2_OPE);
function loadScript(uri) {
    var script = document.createElement('script');
    script.src = uri;
    script.type = 'text/javascript';
    script.async = true;  // スクリプトを非同期に実行
    document.head.appendChild(script);
        
    return new Promise((resolve, reject) => {
		script.onload = function() { 
			//alert(uri + " is loaded.");
			resolve("OK");
		};
	});
}

async function loadConst2(nm) {
    if (typeof window["C2_" + nm] === 'undefined') {
    	var uri = "./const2/" + nm + ".js";
    	await loadScript(uri).then((message) =>{
    		//alert(typeof C2_OPE);
    		null;
    	});
    }
}

function scrollToId_Evt(ele){
	let $ele = $(ele);
	let id = $ele.attr("m_ref_id");
	let scrollFlg = true;
	
	if(id === null || id === undefined){
		id = $ele.attr("id");
		scrollFlg = false;
	}

	// idが定義されない場合、処理終了
	if(id === null || id === undefined){
		return;
	}
	
	scrollToId(id, scrollFlg);
}

// 例、onclick="scrollToId('MCS_0149_5')"
function scrollToId(id, scrollFlg){
	// 対象の要素を取得
	var trgtEle = document.getElementById(id);
	var $trgtEle= $(trgtEle);
	
	if(scrollFlg){
		// 親要素を取得
		var prntEle = $trgtEle.closest('pre').get(0);

		// 要素の位置を取得
		const rect = trgtEle.getBoundingClientRect();
		const parentRect = prntEle.getBoundingClientRect();
		const offsetTop = rect.top - parentRect.top + prntEle.scrollTop;
		// 要素の位置までスクロール
		prntEle.scrollTo({ top: offsetTop - 8, behavior: 'smooth' });
	}

	let setMarkFlg = true;
	if($trgtEle.hasClass("mark")){
		setMarkFlg = false;
	}
	
	// highlight表示を
    let $eles = $('.mark'); // クラス名を持つ要素を取得
    $eles.removeClass("mark");
    
	if(setMarkFlg == true){
		$eles = $('#' + id + ', [m_ref_id="' +  id + '"]');
		$eles.addClass("mark");
	}
}

function getLvl($cur_lvl){
	var lvl_num = "";
	
	// 要素の _lvlX を取得
	if($cur_lvl.hasClass("_lvl1")){
		lvl_num = "_lvl1";
	}
	else if($cur_lvl.hasClass("_lvl2")){
		lvl_num = "_lvl2";
	}
	else if($cur_lvl.hasClass("_lvl3")){
		lvl_num = "_lvl3";
	}
	else if($cur_lvl.hasClass("_lvl4")){
		lvl_num = "_lvl4";
	}
	
	return lvl_num;
}

function toggle_tree(ele){
	$ele = $(ele);
	
	// 前の_lvl 要素を検索
	$cur_lvl = $ele.prevAll("._lvl").first();
	var lvl_num = getLvl($cur_lvl);
	
	if($cur_lvl.length>0){
		// 次の_lvl 要素を検索
		$next_lvl = $ele.nextAll("._lvl").first();
		
		if($next_lvl.length>0 && getLvl($next_lvl) > lvl_num){			
			$chd_lvls = $next_lvl.nextUntil("."+lvl_num);
			
			if($ele.hasClass("collpdBtn")){
				// 閉めるボタン
				$next_lvl.addClass("collpd");		// collapse非表示
				$chd_lvls.addClass("collpd");		// collapse非表示
			}
			else{
				// 展開
				$next_lvl.removeClass("collpd");
				$chd_lvls.removeClass("collpd");
			}
		}
	}
	
	if($ele.hasClass("collpdBtn")){
		// 閉めるボタン
		$ele.removeClass("collpdBtn");
		$ele.addClass("expdBtn");
	}
	else{
		// 展開
		$ele.removeClass("expdBtn");
		$ele.addClass("collpdBtn");
	}
}
	
function popup(url) {
    window.open(url, '_blank', 'menubar=0,width=1000,height=500,top=100,left=100');
}

// ClipBoardへコピー
function copyToClipboard(codeId) {
    // コピー対象をJavaScript上で変数として定義する
    var copyTarget = document.getElementById(codeId);
	
	// no-selectの内容を待機
	var noSelEles = $(copyTarget).find('.no-select');
	const noSelTxts = new Array(noSelEles.length);
	
	for (let i = 0; i < noSelEles.length; i++) {
		$ele = $(noSelEles[i]);
		//alert($ele.text());
		noSelTxts[i] = $ele.text();
		$ele.text("");
	}

    navigator.clipboard.writeText(copyTarget.innerText.replace(/\u00A0/g, ' '));

    // コピー対象のテキストを選択する
    //copyTarget.select();

    // 選択しているテキストをクリップボードにコピーする
    //document.execCommand("Copy");
    
    // o-selectの内容を復旧
	for (let i = 0; i < noSelEles.length; i++) {
		$ele = $(noSelEles[i]);
		$ele.text(noSelTxts[i]);
	}
}

// 頭文字を大文字へ変更
function firstUpper(s)
{
    return s && s[0].toUpperCase() + s.slice(1);
}

// Proper
function properCase(str, removeUnderBar) {
	if(typeof removeUnderBar === 'undefined'){
		removeUnderBar = false;
	}
	
    str = str.toLowerCase().replace(/\b\w/g, function(char) {
        return char.toUpperCase();
    }).replace(/_\w/g, function(char) {
        return char.toUpperCase();
    });
    
    if(removeUnderBar){
		str = str.replaceAll("_", "");
	}
	
	return str;
}

// 半角→全角(英数字)
function replaceHalfToFull(str){
  return str.replace(/[!-~]/g, function(s){
    return String.fromCharCode(s.charCodeAt(0) + 0xFEE0);
  });
}

// 全角→半角(英数字)
function replaceFullToHalf(str){
  return str.replace(/[！-～]/g, function(s){
    return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
  });
}

// 順番数字を算出
// cur: 現在値、orgVal: 開始の順番値、変更後の値
function getSeq(curOrgVal, val, orgVal){
	var orgValh = replaceFullToHalf(orgVal);
	var fullWidthFlg = false;
		
	if( orgValh != orgVal){
		fullWidthFlg = true;	// 全角出力
	}
	
	curOrgVal =  replaceFullToHalf(curOrgVal);
	val =  replaceFullToHalf(val);
	
	var tmp = Number(curOrgVal) - Number(orgValh) + Number(val);
	
	if(fullWidthFlg == true){
		tmp = replaceHalfToFull( String(tmp) );
	}

	return tmp;
}

$(document).ready(function(){	
	// テンプレート
	$('.tmpl').click(function() {
		var $target = $(event.target);
		
		$('#txt_TmplDialog_Val1').text($target.text());
		tmplDialog.showModal();
	});
	
	// _midx
	$('._midx').each(function(idx, ele) {
		$ele = $(ele);
		var s_html = "<span class='no-select i'>" + $ele.attr('m_index') + "．" + "</span>";
		
		var $prevEle = $ele.prev();
		$ele.before(s_html);
	});
		
	// markdown処理
    var md = window.markdownit({ html: true });
	mermaid.initialize({ startOnLoad: true });

	function convertMarkdownToHtml($ele) {
		var markdownText = $ele.text();
		var html = md.render(markdownText);
		//alert(html);
		$ele.html(html);
		
		//<pre><code class="language-mermaid"
		const codeMermaids = $ele.find('code.language-mermaid');
		
		for (let i = 0; i < codeMermaids.length; i++) {
			$code = $(codeMermaids[i]);
			$pre = $code.closest('pre');
			$pre.html("<div class='mermaid'>" + $code.text() + "</div>")
		}
	
		mermaid.init();
		
	}

	$('.markdown').each(function(idx, ele){
		$ele = $(ele);
		convertMarkdownToHtml($ele);
	});

	setupOptDialog();
	setupVarDialog();
	setupModeDialog();
	
	// id
	$('.todo, .e, .i, .refMrk').click(function() {
		scrollToId_Evt(this);
	});
});

function setModeBefore(){
	// class = "_m" 項目を取得ループ
	$('._m').each(function(idx, ele) {
		$ele = $(ele);
		var eleVal = $ele.attr('m_value');
		var eleOpts = $ele.attr('m_option');
		var s_html = "<span class='no-select' m_value='" + eleVal + "' title='" + eleOpts + "'>[" + $ele.attr("title") + ":" + eleVal + "]</span>";
		
		var $prevEle = $ele.prev();
		if($prevEle.hasClass("no-select")){
			if( eleVal != $prevEle.attr('m_value')){
				$prevEle.remove();
				$ele.before(s_html);
			}
		}
		else{
			$ele.before(s_html);
		}
	});
}

// Mode更新
function setMode($ele, $rgn, slowFlg){	
	var modeNm = $ele.attr('name');
	var val = $ele.attr('m_value');
	var subModeNms = $ele.attr('m_sub');
	var $subEle = null;
	
	// pre取得 ※ソースの単位
	varDialog_pre = $ele.closest('pre');
	
	if($rgn == null){
		$rgn = varDialog_pre;
	}
	
	// class= <modeNm> の項目を取得 ループ
	$rgn.find('.' + modeNm).each(function(index) {
		// class= <name> + <val> 表示 以外の項目を不表示
		var $ele = $(this);
		var $tgt = $ele;
		
		// 行単位で表示制御
		if( $ele.hasClass("mline")){
			$tgt = $ele.closest('li');
		}
		
		// $tgtが_m_の親がない 又は 表示する時
		// _m_ _m1_ _m1_y mnow ※ 現在値
		var $par_mode = $ele.parent().closest('._m_');

		// 親モード存在しない OR 親モード＝表示
		if( $par_mode.length ==0 || $par_mode.hasClass('mnow')){
			if( $ele.hasClass( modeNm + val) ){
				$ele.addClass("mnow");
				if(slowFlg) $tgt.show('slow');
				else $tgt.show();
				
				// subModeNmsが定義された場合、Elementの値を取得
				if(subModeNms){
					var arr_subModeNm = subModeNms.split(',');

					for( subModeNm of arr_subModeNm){
						var tarTmp = varDialog_pre.find("._m[name='" + subModeNm + "']");
						if(tarTmp.length > 0){
							$subEle = $(tarTmp[0]);
							setMode($subEle, $tgt, false)
							//subModeVal = $(tarTmp[0]).attr('m_value');
						}
					}
				}
			}
			else{
				$ele.removeClass("mnow");
				if(slowFlg) $tgt.hide('slow');
				else $tgt.hide();
			}
		}
	});
	
	setModeBefore();
}

// 変数置換Dialog設定
function setupModeDialog(){
	var modeDialog = document.getElementById('modeDialog');
	var $curModeEle = null;
	
	// class = "_m" 項目を取得ループ
	$('._m').each(function(index) {
		var $ele = $(this);
		
		// class = "_m" 項目の名称<name>と値<val>を取得		
		setMode($ele,null, false);
	});
	
	$('._m').click(function() {
		var $ele = $(this);
		var eleName = $ele.attr('name');
		var eleTitle = $ele.attr('title');
		var eleVal = $ele.attr('m_value');
		var eleOpts = $ele.attr('m_option');
			
		// Modeを取得
		$('#lbl_ModeDialog_ModeNm').text(eleTitle);
		
		var $cmb = $('#cmb_ModeDialog_Mode');
		
		$cmb.children('option').remove();
		
		var opts = eleOpts.split(',');
		
		for(let i = 0; i < opts.length; i++) {
  			$cmb.append($("<option>").val(opts[i].split(":")[0]).text(opts[i]));
		}

		$cmb.val(eleVal);
		
		$curModeEle= $ele;
		modeDialog.showModal();
	});

	$('._ml').click(function() {
		var $ele = $(this);
		var eleName = $ele.attr('name');
		var scope = "pre";
		
		// pre取得
		$pre = $ele.closest('pre');
		$rgn = $pre;
		
		if(eleName.startsWith('_g_')){
			scope = "tr";
		}
		
		if(eleName.startsWith('_g2_')){
			scope = "tbody";
		}
		
		if(scope=="tr"){
			$rgn = $pre.closest('tr');
		}
		
		if(scope=="tbody"){
			$rgn = $pre.closest('tbody');
		}
		
		// Linkするeleを取得
		$rgn.find("._m[name='" + eleName +"']").click();
	});
	
	$('#btn_ModeDialog_Cancle').click(function() {
		// Mode Dialogをクローズ
		modeDialog.close();
	});
	
	 $('#btn_ModeDialog_OK').click(function() {
	 	var $cmb = $('#cmb_ModeDialog_Mode');
	 	$curModeEle.attr('m_value',$cmb.val());
	 	setMode($curModeEle,null, true);
	 	
		// Mode Dialogをクローズ
		modeDialog.close();
	});

	$('#btn_TmplDialog_OK').click(function() {
		// Tmpl Dialogをクローズ
		tmplDialog.close();
	});
}

// 選択Dialog設定
// <span class='_opt' m_const2='OPE' m_null='y' m_input='y'>crossJoin</span>
function setupOptDialog(){
	var optDialog = document.getElementById('optDialog');
	var const2_nms = [];
	var optDialog_target;
	
	// 定数定義をロード
	$('._opt').each(function(index) {
		var $ele = $(this);
		var m_const2 = $ele.attr('m_const2');
		
		if(const2_nms.indexOf(m_const2) == -1){
			const2_nms.push(m_const2);
			loadConst2(m_const2);
		}
	});
	
	$('._opt').click(function() {
		var $ele = $(this);
		
		var m_const2 = $ele.attr('m_const2');
		var m_null = $ele.attr('m_null');
		var m_input = $ele.attr('m_input');
		
		var v2 = window["C2_" + m_const2];
		
		// Dialogの表示設定
		$('#lbl_OptDialog_title').text(v2.label);
		
		var $dlg_help = $('#lbl_OptDialog_help');
		$dlg_help.attr('title', v2.help);
		$dlg_help.off('click');
		$dlg_help.click(function() {
			popup(v2.help);
		});
		
		var $cmb = $('#cmb_OptDialog');
		
		$cmb.children('option').remove();
		
		for(let i = 0; i < v2.options.length; i++) {
  			$cmb.append($("<option>").val(v2.options[i].id).text(v2.options[i].id + " : " + v2.options[i].label));
		}
		
		// 選択Dialog表示
		optDialog_target = $ele;
		$cmb.val(optDialog_target.text());
		optDialog.showModal();
	});

	$('#btn_OptDialog_Cancle').click(function() {
		optDialog.close();
	});

	$('#btn_OptDialog_OK').click(function() {
		var $cmb = $('#cmb_OptDialog');
		optDialog_target.text($cmb.val());
		optDialog.close();
	});	 
}

// 変数置換Dialog設定
function setupVarDialog(){
	var varDialog = document.getElementById('varDialog');
	var varDialog_rgn;
	var varScope;		// 0:pre,1:tr,2:tbody
	var varDialog_target;
	var varDialog_name;
	var varDict = {};	// Title Dictionary
	
	/// タイトル設定
	// Title Dictionary作成
	$('._var').each(function(index) {
		var $eleVar = $(this);
		if($eleVar.attr('title')){
			varDict[$eleVar.attr('name')]=$eleVar.attr('title');
		}
	});

	$('._var').each(function(index) {
		var $eleVar = $(this);
		if(!$eleVar.attr('title')){
			$eleVar.attr('title', varDict[$eleVar.attr('name')]);
		}
	});
	
	$('._var').click(function() {
		var $target = $(event.target);
		//$('#VarDialog_val').val($target.text());

		// 変数の範囲
		varScope = "pre";
		
		// pre取得
		varDialog_rgn = $target.closest('pre');
		
		if(varDialog_rgn.length == 0){
			varDialog_rgn = $target.closest('td._src');
		}
		
		var $varObj = $target.closest('._var');
		varDialog_target = $varObj;
		varDialog_name = $varObj.attr('name');
		
		if(varDialog_name.startsWith('vg_')){
			varScope = "tr";
			varDialog_rgn = varDialog_rgn.closest('tr._src');
		}
		
		if(varDialog_name.startsWith('vg2_')){
			varScope = "tbody";
			varDialog_rgn = varDialog_rgn.closest('tbody');
		}
		
		if(varDialog_name.endsWith('UF') || varDialog_name.endsWith('PU') ){
			varDialog_name = varDialog_name.substring(0, varDialog_name.length -2);
		}
		else if(varDialog_name.endsWith('U') || varDialog_name.endsWith('L') || varDialog_name.endsWith('P')){
			varDialog_name = varDialog_name.substring(0, varDialog_name.length -1);
		}
		
		var lblVarNm = $varObj.attr("title");
		
		if($varObj.attr('inptval')){
			$('#VarDialog_val').val($varObj.attr('inptval'));
		}else{
			$('#VarDialog_val').val($varObj.text());
		}
		
		if(!lblVarNm){
			lblVarNm = "変更後の値を入力してください。";
		}

		$('#lbl_VarDialog_varNm').text(lblVarNm);
		
		// var1を取得
		varDialog.showModal();
	});

	 $('#btn_VarDialog_Cancle').click(function() {
		// var1を取得
		varDialog.close();
	});

	 $('#btn_VarDialog_OK').click(function() {
	 	var tmp = $('#VarDialog_val').val();

	 	varDialog_rgn.find('[name=' + varDialog_name + ']').each( function() {
	 		var this$ = $(this);
	 		if(this$.attr('inptval')!== undefined){
				this$.attr('inptval', tmp);
			}
			
	 		if(this$.attr('orgval')){
	 			this$.text( getSeq(this$.attr('orgval'), tmp, varDialog_target.attr('orgval')));
	 		}
	 		else if(this$.attr('match')){ 
	 			set_var_text(this$, tmp, null); // 一部抽出
	 		}
	 		else if(this$.attr('slice')){ // 分割の部分を抽出
	 			set_var_text(this$, tmp, null); // 一部抽出
	 		}
	 		else if(this$.attr('user_conv_nm') && user_conv !== undefined){
		 		// user_conv 関数が存在する場合
  				this$.text(user_conv(tmp, this$.attr('user_conv_nm')));
	 		}
	 		else{
	 			 this$.text(tmp);
			}
	 	});
	 	var tmps$ = varDialog_rgn.find('[name=' + varDialog_name + 'L]');
	 	set_vars_text(tmps$, tmp, "L");
	 	set_inptval(tmps$, tmp);
	 	
	 	var tmps$ = varDialog_rgn.find('[name=' + varDialog_name + 'U]');
	 	set_vars_text(tmps$, tmp, "U");
	 	set_inptval(tmps$, tmp);
	 	
	 	var tmps$ = varDialog_rgn.find('[name=' + varDialog_name + 'UF]');
	 	set_vars_text(tmps$, tmp, "UF");
	 	set_inptval(tmps$, tmp);
	 	
	 	var tmps$ = varDialog_rgn.find('[name=' + varDialog_name + 'P]');
	 	set_vars_text(tmps$, tmp, "P");
	 	set_inptval(tmps$, tmp);
	 	
	 	var tmps$ = varDialog_rgn.find('[name=' + varDialog_name + 'PU]');
	 	set_vars_text(tmps$, tmp, "PU");
	 	set_inptval(tmps$, tmp);
	 	
		// var1を取得
		varDialog.close();
	});
}

function set_vars_text(eles$, text, c_typ){
	eles$.each( function(index, element) {
	 	var ele$ = $(element);
		set_var_text(ele$, text, c_typ);
	});
}

// c_typ: L,U,UF,P,PU
function set_var_text(ele$, text, c_typ){
	if(ele$.attr('match')){ // 一部抽出
		text = text.match(new RegExp(ele$.attr('match')));
	}
	else if(ele$.attr('slice')){ // 分割の部分を抽出
		var tmp_parts = text.split("_");
		var p_parts = ele$.attr('slice').split(",");	// 指定の部分(1～）又は指定範囲
		
		var tmp_val = text;
		
		if(tmp_parts.length >= parseInt(p_parts[0],10)){
			tmp_val = tmp_parts[parseInt(p_parts[0],10) -1];

			var part_to = tmp_parts.length;
					 				
			if(p_parts.length==2 && tmp_parts.length < parseInt(p_parts[1],10)){
				part_to = parseInt(p_parts[1],10);
			}
			
			for (let i = parseInt(p_parts[0],10); i < part_to; i++) {
				tmp_val = tmp_val + "_" + tmp_parts[i];
			}
		}
		
		text = tmp_val;
	}
	 		
	// 大文字、小文字置換
	if(c_typ == "L"){
		text = text.toLowerCase();
	}
	else if(c_typ == "U"){
		text = text.toUpperCase();
	}
	else if(c_typ == "UF"){
		text = firstUpper(text.toLowerCase());
	}
	else if(c_typ == "P"){
		text = properCase(text);
	}
	else if(c_typ == "PU"){
		text = properCase(text, true);
	}
	
	// text設定
	ele$.text(text);
}

function set_inptval(tmps$, val){
	tmps$.each( function(index, element) {
	 	var ele$ = $(element);
	 		
 		if(ele$.attr('inptval')){
			ele$.attr('inptval', val);
		}
	});
}