/*
 * 7.4.2.1 (2021/05/21) スタートボタンで映像を「映像表示エリア」に表示
 *
 *	<button type='button' id="vidStart" onClick="videoStart()">映像表示開始</button>
 *	<button type='button' id="capStart" onClick="capture()">Capture</button>
 *
 *	<div id="videotop" style="display:flex;" >
 *		<video id="player" autoplay style="background-color: black;position: absolute;z-index: 1;"></video>
 *		<canvas id="snapshot" style="visibility:hidden;z-index: 2; "></canvas>
 *	</div>
 *
 *	<progress id="progressbar" > </progress>	進捗バー
 *	<textarea name='outdata' id='outdata > </textarea>		OCRテキスト出力
 */
function videoStart() {
	// 操作する画面エレメント変数定義します。
	const player = document.getElementById('player');		// 映像表示エリア
	navigator.mediaDevices.getUserMedia({ video: true, audio: false })
		.then(stream => player.srcObject = stream)
		.catch(err => alert(`${err.name} ${err.message}`));
}

// 「静止画取得」ボタンが押されたら、canvas に映像のコマ画像を表示します。
function capture() {
	const snapshot = document.getElementById('snapshot');
	if( snapshot.style.visibility == "visible" ) {
		snapshot.style.visibility = "hidden" ;
	}
	else {
		snapshot.style.visibility = "visible" ;

		// 操作する画面エレメント変数定義します。
		const player = document.getElementById('player');		// 映像表示エリア
		const context = snapshot.getContext('2d');
		snapshot.width  = player.videoWidth;
		snapshot.height = player.videoHeight;

		context.drawImage(player, 0, 0);

		const outdata  = document.getElementById('outdata');
		if(outdata) {
//			outdata.innerHTML = "";
			outdata.value = "";
			ocr( snapshot,outdata );
		}
	}
}

/*
 * 7.4.2.1 (2021/05/21) File API による画像のOCR処理
 *
 *	<input type="file" name="imgfile" id="imgfile" accept="image/*" onChange="readOCR(this)" >  File API
 *	<img id="preview">							画像表示
 *	<progress id="progressbar" > </progress>	進捗バー
 *	<textarea name="outdata" id="outdata"  > </textarea>		OCRテキスト出力
 */
function readOCR( target ) {
	const file = target.files[0];

	// imgタグのpreview領域があれば、イメージを表示する
	const preview = document.getElementById('preview');
	if( preview ) {
		var reader = new FileReader();
		reader.onload = function (evt) {
			preview.src=evt.target.result;
		}
		reader.readAsDataURL(file);
	}

	const outdata = document.getElementById('outdata');
	ocr( file,outdata );
}

function ocr( img,outdata ) {
	const progressbar = document.getElementById('progressbar');
	Tesseract.recognize(img,'jpn',{logger:m => { progressbar.value = m.progress;}})
		.then(({ data:{ text } }) => {
//			outdata.innerHTML = text;
//			outdata.textContent = text;
			outdata.value = text;
		});
}

/*
 * 7.4.2.1 (2021/05/21) 映像から定期的に静止画を抽出する。
 *
 *	<button type='button' id="vidStart" onClick="videoStart();qrScan();">映像表示開始</button>
 *
 *	<video id="player" autoplay style="background-color: black;"></video>
 *	<textarea name='outdata' id='outdata'> </textarea>		QRコードを出力
 */
function qrParse(video){
	const canvas = new OffscreenCanvas(240, 320);
	const render = canvas.getContext("2d");

	return new Promise((res)=>{
		const loop = setInterval(()=>{
			render.drawImage(video, 0, 0, canvas.width, canvas.height);

			const img = render.getImageData(0, 0, canvas.width, canvas.height);
			const result = jsQR(img.data, img.width, img.height);

			// 解析結果が存在したら、100ms 繰り返し処理の解除を行い、QRデータを解決します
			if(result){
				clearInterval(loop);
				return res(result.data);
			}
		}, 100);
	});
}

// 「QR scan」ボタンが押されたらスキャンを開始する。
async function qrScan() {
	// 操作する画面エレメント変数定義します。
	const player = document.getElementById('player');		// 映像表示エリア
	const outdata  = document.getElementById('outdata');
//	outdata.innerHTML = await qrParse(player);
//	outdata.textContent = await qrParse(player);
	outdata.value = await qrParse(player);

	// 5秒後に スキャンを再開する。
	setTimeout( qrScan(),5000 );
}

/*
 * 7.4.2.1 (2021/05/21) ブラウザ上でQRコードを生成する。
 *
 * canvas に描画後に、img に変換することで、Webの印刷が出来るようにする
 *
 *	<div id='divname1' class='QRDATA'>QRコードを生成します</div>
 *	<canvas id='canname1' class='QRCANVAS' style='display:none;' ></canvas>
 *	<img src="" id="imgname1"  class='QRIMG' />
 *	<script>qrView('name1');</script>
 */
function qrGenerate(data){
	const canvas = new OffscreenCanvas(1, 1);

	return new Promise((res, rej) =>
		 QRCode.toCanvas(canvas, data, {}, err => !err ? res(canvas) : rej(err)));
}

async function qrView( name ) {
	const indata = document.getElementById('div' + name);		// 値が設定されている div
	const canvas = document.getElementById('can' + name);		// 一時的に作成する canvas
	const imgtag = document.getElementById('img' + name);		// 最後にセットする img

	canvas.getContext("bitmaprenderer")
		.transferFromImageBitmap((await qrGenerate(indata.textContent))
		.transferToImageBitmap());

	imgtag.src = canvas.toDataURL();
}

/*
 * 7.4.2.1 (2021/05/21) カメラ映像から静止画をキャプチャして、ajaxでbase64でアップロードする。
 *
 * アップロードは、ｻｰﾌﾞﾚｯﾄ(/gf/jsp/imageSave)で処理する。
 *
 *	<button type='button' id='vidStart' onClick="videoStart()">映像表示開始</button>
 *	<button type='button' id='capStart' onClick="capture()">Capture</button>
 *
 *　例1　dir、file、debug という引数がある
 *	<button type='button' id='upBtn1' onClick="upload( { dir:'jsp/GF6500/script' , file:'snap.png', debug: true } )">Upload1</button>
 *
 *　例2　dirは初期値(jsp/snapshot) を使う
 *	<button type='button' id='upBtn2' onClick="upload( { file:'snap.png' } )">Upload2</button><br />
 *
 *	<div id="videotop" style="display:flex;" >
 *		<video id="player" autoplay style="background-color: black;position: absolute;z-index: 1;"></video>
 *		<canvas id="snapshot" style="visibility:hidden;z-index: 2; "></canvas>
 *	</div>
 */
function upload( args ) {
	var img = document.getElementById('snapshot').toDataURL();		// img変換

	img = img.replace('data:image/png;base64,', ''); 	// 初めの属性情報を削除

	var param = 'img='+img ;
	if( args.dir   ) { param += '&dir='   + encodeURIComponent( args.dir   ); }
	if( args.file  ) { param += '&file='  + encodeURIComponent( args.file  ); }
	if( args.debug ) { param += '&debug=' + encodeURIComponent( args.debug ); }

	var xhr = new XMLHttpRequest();
	xhr.open( 'POST', '/gf/jsp/imageSave' );			// ｻｰﾌﾞﾚｯﾄで処理する。
	xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
	xhr.send( param );
}

/*
 * 7.4.2.1 (2021/05/21) スタートボタンで映像を「映像表示エリア」に表示
 *
 * 他のvideo系と異なるのは、画像をvideoに表示せず、canvasの書き換えで行っています。
 * ｵﾘｼﾞﾅﾙのｻﾝﾌﾟﾙを改造しきれませんでした。
 * https://mam-mam.net/javascript/js_quagga.html
 *
 *	<button type='button' id="barStart" onClick="barcodeStart()">映像表示開始</button>
 *	<div><canvas id="preview" style='background-color: black;' ></canvas></div>
 *
 *	<textarea id="outdata" rows="8" cols="40"></textarea>
 */
function barcodeStart() {
	var player=document.createElement('video');
	player.setAttribute("autoplay","");
	player.setAttribute("muted","");
	player.setAttribute("playsinline","");
	player.onloadedmetadata = function(e){player.play();};

	//カメラ使用の許可ダイアログが表示される
	navigator.mediaDevices.getUserMedia(
		//マイクはオフ, カメラの設定	 背面カメラを希望する 640×480を希望する
		{"audio":false,"video":{"facingMode":"environment","width":{"ideal":640},"height":{"ideal":480}}}
	).then( //許可された場合
		function(stream){
			player.srcObject = stream;
			//0.5秒毎にスキャンする
			setTimeout(Scan,500,player);	// 少し待たないとエラーになる。
		}
	).catch( //許可されなかった場合
		function(err){ alert( err ); }
	);
}

function Scan(player){
//	var DetectedCount=0,DetectedCode="";

	var canvas=document.getElementById("preview");
	var render=canvas.getContext("2d");
	var tmp = document.createElement('canvas');
	var tmp_ctx = tmp.getContext("2d");

	//選択された幅高さ
	var w=player.videoWidth;
	var h=player.videoHeight;
	//画面上の表示サイズ
	canvas.style.width=(w/2)+"px";
	canvas.style.height=(h/2)+"px";
	//内部のサイズ
	canvas.setAttribute("width",w);
	canvas.setAttribute("height",h);
	var mw=w*0.5;
	var mh=w*0.2;
	var x1=(w-mw)/2;
	var y1=(h-mh)/2;

	setInterval(()=>{
		render.drawImage(player,0,0,w,h);
		render.beginPath();
		render.strokeStyle="rgb(255,0,0)";
		render.lineWidth=2;
		render.rect(x1,y1,mw,mh);
		render.stroke();
		tmp.setAttribute("width",mw);
		tmp.setAttribute("height",mh);
		tmp_ctx.drawImage(canvas,x1,y1,mw,mh,0,0,mw,mh);

		tmp.toBlob(function(blob){
			let reader = new FileReader();
			reader.onload=function(){
				let config={
					decoder: {
	//					readers: ["ean_reader","ean_8_reader"],
						readers: ["code_39_reader"],
						multiple: false, //同時に複数のバーコードを解析しない
					},
					locator:{patchSize:"large",halfSample:false},
					locate:false,
					src:reader.result,
				};
				Quagga.decodeSingle(config,function(){});
			}
			reader.readAsDataURL(blob);
		});
	},50 );

	// 読み取り時に呼ばれる。
	// code39 では、ｽﾀｰﾄ/ｽﾄｯﾌﾟｷｬﾗｸﾀ(*)は除去される。
	// ﾁｪｯｸﾃﾞｼﾞｯﾄ(ﾓｼﾞｭﾗｽ43)は、考慮しない。
	Quagga.onDetected(function (result) {
//		if(DetectedCode==result.codeResult.code){
//			DetectedCount++;
//		}else{
//			DetectedCount=0;
//			DetectedCode=result.codeResult.code;
//		}
//		if(DetectedCount>=3){
			let outdata=document.getElementById("outdata");
			outdata.value = result.codeResult.code;
//			DetectedCode='';
//			DetectedCount=0;
//		}
	});
}

// const MODULUS_43 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" ;

/*
 * 7.4.2.1 (2021/05/21) ブラウザ上でBARコード(code39)を生成する。
 *
 * JsBarcode は、ｽﾀｰﾄ/ｽﾄｯﾌﾟｷｬﾗｸﾀ(*)を自動で付けるので、値にｾｯﾄしない。
 * ﾁｪｯｸﾃﾞｼﾞｯﾄ(ﾓｼﾞｭﾗｽ43)は、統一の意味で、考慮しない。
 *
 * <script src='{@SYS.JSP}/common/option/JsBarcode.code39.min.js'><!-- --></script> が必要です。
 *
 *	<div id='divname1' class='BARDATA'>code 39</div>
 *	<img src="" id="imgname1"  class='BARIMG' style="height:100px;" />
 *	<script>barView('name1',true);</script>
 */
function barView( name,flag ) {
	const indata = document.getElementById('div' + name);		// 値が設定されている div
	const imgtag = document.getElementById('img' + name);		// 最後にセットする img
	var value  = indata.textContent;

//	// ﾓｼﾞｭﾗｽ43 の計算
//	var kei = 0;
//	var ary = value.split('');
//	ary.forEach( ele => kei += MODULUS_43.indexOf( ele ) );
//	value = value + MODULUS_43.charAt( kei % 43 );

	// imgtag の代わりに、'#img'+name でも動作する。
	JsBarcode(imgtag, value, {
		format: "code39",
		displayValue: flag
	});
}
