;(function($){

	//vrbk
	jQuery.fn.panoramaViewer=function(optUser){

		//options
		const optDef={
			src			: "",
			rotationY	: 0
		};
		const opt=$.extend(optDef,optUser);

		//canvas
		const myCanvas=$(this);
		var cv=new Canvas();
		function Canvas(){
			this._id		=myCanvas.attr("id");
			this._box		=myCanvas.closest(".canvas_box");
			this._loader	=myCanvas.closest(".canvas_box").find(".canvas_loader");
			this._start		=myCanvas.closest(".canvas_box").find(".canvas_start");

			this._w			=this._box.width();
			this._h			=this._box.height();
		}
		myCanvas.attr({
			'width'  : cv._w,
			'height' : cv._h
		});

		//three.js
		var renderer;
		var scene;
		var camera;
		var controls;

		//group
		var grpWorld;
		var grpBase;

		//loader
		var loader={};

		//timer
		var timerLoading;

		//ジャイロセンサー確認
		var isGyro=false;
		if((window.DeviceOrientationEvent)&&('ontouchstart' in window)){
			isGyro=true;
		}

		//PCなど非ジャイロ
		if(!isGyro){
			setCanvas();

		//一応ジャイロ持ちデバイス
		}else{
			//ジャイロ動作確認
			var resGyro=false;
			window.addEventListener("deviceorientation",doGyro,false);
			function doGyro(){
				resGyro=true;
				window.removeEventListener("deviceorientation",doGyro,false);
			}

			//数秒後に判定
			setTimeout(function(){
				//ジャイロが動いた
				if(resGyro){
					setCanvas();

				//ジャイロ持ってるくせに動かなかった
				}else{
					//iOS13+方式ならクリックイベントを要求
					if(typeof DeviceOrientationEvent.requestPermission==="function"){
						//ユーザアクションを得るための要素を表示
						cv._start.show();
						cv._start.on("click",function(){
							cv._start.hide();
							DeviceOrientationEvent.requestPermission().then(res => {
								//「動作と方向」が許可された
								if(res==="granted"){
									setCanvas();
								//「動作と方向」が許可されなかった
								}else{
									isGyro=false;
									setCanvas();
								}
							});
						});

					//iOS13+じゃない
					}else{
						//早くアップデートしてもらうのを祈りながら諦める
						isGyro=false;
						setCanvas();
					}
				}
			},300);
		}


		///////////////////////////////////////////////////////////////////////////////////////////
		// Canvas
		///////////////////////////////////////////////////////////////////////////////////////////

		function setCanvas(){
			if(!Detector.webgl){Detector.addGetWebGLMessage();}
			cv._loader.show();

			renderer=new THREE.WebGLRenderer({
				canvas    : document.querySelector('#'+cv._id),
				antialias : true,
				alpha     : true
			});

			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(cv._w,cv._h);

			scene=new THREE.Scene();
			grpWorld=new THREE.Group();
			grpBase=new THREE.Group();

			//スマホなどジャイロセンサーが有効なときはDeviceOrientationControls
			if(isGyro){
				camera=new THREE.PerspectiveCamera(60,cv._w/cv._h,1,20000);
				camera.position.set(0,0,0.01);
				camera.lookAt(new THREE.Vector3(0,0,0));

				controls=new THREE.DeviceOrientationControls(camera);
				controls.connect();
				controls.update();

			//PCなどジャイロセンサーがない場合はOrbitControlsのみ
			}else{
				camera=new THREE.PerspectiveCamera(60,cv._w/cv._h,1,20000);
				camera.position.set(0,0,0.01);
				camera.lookAt(new THREE.Vector3(0,0,0));
				controls=new THREE.OrbitControls(camera,renderer.domElement);

				controls.autoRotate		=false;
				controls.enableRotate	=true;
				controls.rotateSpeed	=-0.05;
				controls.enableDamping	=true;
				controls.dampingFactor	=0.1;
				controls.enableZoom		=false;
				controls.enablePan		=false;
			}


			///////////////////////////////////////////////////////////////////////
			// 3Dオブジェクト配置
			///////////////////////////////////////////////////////////////////////

			//base
			var gmBase=new THREE.SphereBufferGeometry(1000,60,40);
			gmBase.scale(-1,1,1);
			var mtrBase;
			if(opt.src==""){
				mtrBase=new THREE.MeshNormalMaterial();
			}else{
				loader[opt.src]=false;
				var texture=new THREE.TextureLoader().load(opt.src,function(){
					loader[opt.src]=true;
				});

				texture.minFilter=texture.magFilter=THREE.LinearFilter;
				texture.mapping=THREE.UVMapping;

				mtrBase=new THREE.MeshBasicMaterial({
					map : texture
				});
			}
			var base=new THREE.Mesh(gmBase,mtrBase);
			base.rotation.y=(opt.rotationY*Math.PI/180);
			grpBase.add(base);

			grpWorld.add(grpBase);
			scene.add(grpWorld);

			//checkLoading
			var check_sec=500;
			var check_cnt=0;
			var check_limit=30000;

			checkLoading();
			function checkLoading(){
				var flag_loading=false;
				Object.keys(loader).forEach(function(key){
					if(!loader[key]){
						flag_loading=true;
					}
				},loader);

				//読み込み中
				if(flag_loading){
					timerLoading=setTimeout(function(){
						check_cnt+=check_sec;
						if(check_cnt<check_limit){
							checkLoading();
						}else{
							//エラー処理など
							alert("読み込みに失敗しました。");
						}
					},check_sec);

				//読み込み完了
				}else{
					clearTimeout(timerLoading);
					cv._loader.hide();

					runAnimate();
				}
			}

			//runAnimate
			function runAnimate(){
				controls.update();

				renderer.render(scene,camera);
				requestAnimationFrame(runAnimate);
			}
		}


		///////////////////////////////////////////////////////////////////////////////////////////
		// Window Resize
		///////////////////////////////////////////////////////////////////////////////////////////

		var timerResize=false;
		$(window).on("resize",function(){
			if(timerResize!==false){
				clearTimeout(timerResize);
			}
			timerResize=setTimeout(function(){
				resizeCanvas();
			},500);
		});

		function resizeCanvas(){
			cv._w=cv._box.width();
			cv._h=cv._box.height();
			myCanvas.attr({
				'width'  : cv._w,
				'height' : cv._h
			});

			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(cv._w,cv._h);
			camera.aspect=cv._w/cv._h;
			camera.updateProjectionMatrix();
		}

	};

})(jQuery);