;(function($){

	//panoramaView
	jQuery.fn.panoramaViewer=function(prmUser){

		///////////////////////////////////////////////////////////////////////////////////////////
		// Var
		///////////////////////////////////////////////////////////////////////////////////////////

		//parameter
		const prmDef={
			src             : "",
			src_pre         : "",
			autoRotate      : false,
			autoRotateSpeed : 0.2,
			rotationX       : 0,
			rotationY       : 0,
			enableRotate    : true,
			rotateSpeed     : -0.05,
			enableGyro      : true,
			camera          : {
				fov  : 45,
				near : 1,
				far  : 2000
			}
		};
		const prm=$.extend(prmDef,prmUser);

		//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._w      =this._box.width();
			this._h      =this._box.height();
		}
		myCanvas.attr({
			'width'  : cv._w,
			'height' : cv._h
		});

		//操作イベント
		var _start ='touchstart mousedown';
		var _move  ='touchmove mousemove';
		var _end   ='touchend mouseup';

		var isTap=false;
		var isDrag=false;
		var isTouch=('ontouchstart' in window);
		var isGyro=false;
		if((prm.enableGyro)&&(window.DeviceOrientationEvent)&&('ontouchstart' in window)){
			isGyro=true;
		}

		//回転用
		var onMouseDownMouseX;
		var onMouseDownMouseY;
		var lon=0;
		var lat=0;
		var onMouseDownLon;
		var onMouseDownLat;

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

		//loader
		var loader={};
		var loader_pre={};


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

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

			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();
			group=new THREE.Group();

			if(isGyro){
				camera=new THREE.PerspectiveCamera(prm.camera.fov,cv._w/cv._h,prm.camera.near,prm.camera.far);
				camera.position.set(0,0,0);
				controls=new THREE.DeviceOrientationControls(camera,true);
				controls.connect();

				if(prm.enableRotate){
					myCanvas.on(_start,function(e){
						e.preventDefault();
						isTap=true;
					});
					myCanvas.on(_move,function(e){
						e.preventDefault();
						if(isTap){
							isTap=false;
							isDrag=true;

							onMouseDownMouseX=(isTouch ? event.changedTouches[0].clientX : e.clientX);
							onMouseDownMouseY=(isTouch ? event.changedTouches[0].clientY : e.clientY);
							onMouseDownLon=lon;
							onMouseDownLat=lat;
						}else if(isDrag){
							var move_x=(isTouch ? event.changedTouches[0].clientX : e.clientX);
							var move_y=(isTouch ? event.changedTouches[0].clientY : e.clientY);
							lon=(move_x-onMouseDownMouseX)*-0.005+onMouseDownLon;
							lat=(move_y-onMouseDownMouseY)*-0.005+onMouseDownLat;
						}
					});
					myCanvas.on(_end,function(e){
						e.preventDefault();
						isTap=false;
						isDrag=false;
					});
				}

			}else{
				camera=new THREE.PerspectiveCamera(prm.camera.fov,cv._w/cv._h,prm.camera.near,prm.camera.far);
				camera.translateZ(0.01);
				camera.lookAt(new THREE.Vector3(0,0,0));
				controls=new THREE.OrbitControls(camera,renderer.domElement);
				if(prm.autoRotate){
					controls.autoRotate=true;
					controls.autoRotateSpeed=prm.autoRotateSpeed;
				}else{
					controls.autoRotate=false;
				}
				if(prm.enableRotate){
					controls.enableRotate=true;
					controls.rotateSpeed=prm.rotateSpeed;
				}else{
					controls.enableRotate=false;
				}
				controls.enableDamping =true;
				controls.dampingFactor =0.1;
				controls.enableZoom    =false;
				controls.enablePan     =false;
			}

			if(prm.src_pre!=""){
				loader_pre[prm.src_pre]=false;
				var gmPrebase=new THREE.SphereBufferGeometry(900,60,40);
				gmPrebase.scale(-1,1,1);
				var mtrPrebase;

				var texture_pre=new THREE.TextureLoader().load(prm.src_pre,function(){
					loader_pre[prm.src_pre]=true;
				});
				mtrPrebase=new THREE.MeshBasicMaterial({
					map : texture_pre
				});
				texture_pre.minFilter=texture_pre.magFilter=THREE.LinearFilter;
				texture_pre.mapping=THREE.UVMapping;
			}
			var prebase=new THREE.Mesh(gmPrebase,mtrPrebase);
			prebase.rotation.y=(prm.rotationY*Math.PI/180)*-1;
			group.add(prebase);

			var gmBase=new THREE.SphereBufferGeometry(1000,60,40);
			gmBase.scale(-1,1,1);
			var mtrBase;
			if(prm.src==""){
				mtrBase=new THREE.MeshNormalMaterial();
			}else{
				loader[prm.src]=false;
				var texture=new THREE.TextureLoader().load(prm.src,function(){
					loader[prm.src]=true;
					checkLoading();
				});
				mtrBase=new THREE.MeshBasicMaterial({
					map : texture
				});
				texture.minFilter=texture.magFilter=THREE.LinearFilter;
				texture.mapping=THREE.UVMapping;
			}
			var base=new THREE.Mesh(gmBase,mtrBase);
			base.rotation.y=(prm.rotationY*Math.PI/180)*-1;
			group.add(base);

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

				if(flag_loading){
					setTimeout(function(){
						runLoading();
					},500);
				}else{
					scene.add(group);
					runAnimate();
				}
			}
			function checkLoading(){
				var flag_loading=false;
				Object.keys(loader).forEach(function(key){
					if(!loader[key]){
						flag_loading=true;
					}
				},loader);

				if(!flag_loading){
					if(prm.src_pre!=""){
						prebase.visible=false;
					}
					cv._loader.hide();
				}
			}

			function runAnimate(){
				if((isGyro)&&(isDrag)){
					group.rotation.y=lon;
					group.rotation.x=lat;
				}
				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);