;(function($){

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

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

		//parameter
		const prmDef={
			autoRotate      : false,
			autoRotateSpeed : 0.2,
			enableRotate    : true,
			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._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;
		}

		//three.js
		var renderer;
		var scene;
		var group;
		var camera_do,camera_ob;
		var control_do,control_ob;
		var isdo;


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

		setCanvas();
		function setCanvas(){

			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){
				isdo=true;
				camera_do=new THREE.PerspectiveCamera(prm.camera.fov,cv._w/cv._h,prm.camera.near,prm.camera.far);
				camera_do.position.set(0,0,0);
				control_do=new THREE.DeviceOrientationControls(camera_do,true);
				control_do.connect();

				camera_ob=new THREE.PerspectiveCamera(prm.camera.fov,cv._w/cv._h,prm.camera.near,prm.camera.far);
				camera_ob.position.set(0,0,-0.01);
				camera_ob.lookAt(new THREE.Vector3(0,0,0));
				control_ob=new THREE.OrbitControls(camera_ob,renderer.domElement);
				control_ob.rotateSpeed   =0.2;
				control_ob.enableDamping =false;
				control_ob.enableZoom    =false;
				control_ob.enablePan     =false;

				myCanvas.on(_start,function(e){
					istap=true;
				});
				myCanvas.on(_move,function(){
					if(istap){
						camera_do.translateZ(0.01);
						camera_ob.position.x=camera_do.position.x;
						camera_ob.position.y=camera_do.position.y;
						camera_ob.position.z=camera_do.position.z;
						isdo=false;
					}
					istap=false;
				});
				myCanvas.on(_end,function(e){
					camera_do.rotation.x=camera_ob.rotation.x;
					camera_do.rotation.y=camera_ob.rotation.y;
					camera_do.rotation.z=camera_ob.rotation.z;
					camera_do.position.set(0,0,0);
					isdo=true;
					istap=false;
				});
			}else{
				isdo=false;
				camera_ob=new THREE.PerspectiveCamera(prm.camera.fov,cv._w/cv._h,prm.camera.near,prm.camera.far);
				camera_ob.position.set(0,0,-0.01);
				camera_ob.lookAt(new THREE.Vector3(0,0,0));
				control_ob=new THREE.OrbitControls(camera_ob,renderer.domElement);
				control_ob.rotateSpeed   =0.2;
				control_ob.enableDamping =true;
				control_ob.dampingFactor =0.1;
				control_ob.enableZoom    =false;
				control_ob.enablePan     =false;
			}

			//Geometry
			group.add(makeGeometry());

			scene.add(group);
			runAnimate();

			function runAnimate(){
				if(isdo){
					control_do.update();
					renderer.render(scene,camera_do);
				}else{
					control_ob.update();
					renderer.render(scene,camera_ob);
				}
				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();
		}

	};

	function makeGeometry(){
		var group=new THREE.Group();

		const stop=1000;
		const start=stop*-1;
		const max=10;
		const move=stop*2/max;

		const mtr_x=new THREE.LineBasicMaterial({color : 0xff0000});
		const mtr_y=new THREE.LineBasicMaterial({color : 0x00ff00});
		const mtr_z=new THREE.LineBasicMaterial({color : 0x0000ff});
		for(i=0;i<=max;i++){
			now1=start+(move*i);
			for(j=0;j<=max;j++){
				now2=start+(move*j);

				var wkgmr_x=new THREE.Geometry();
				wkgmr_x.vertices.push(
					new THREE.Vector3(start,now2,now1),
					new THREE.Vector3(stop,now2,now1)
				);
				var wkline_x=new THREE.Line(wkgmr_x,mtr_x);
				group.add(wkline_x);

				var wkgmr_y=new THREE.Geometry();
				wkgmr_y.vertices.push(
					new THREE.Vector3(now2,start,now1),
					new THREE.Vector3(now2,stop,now1)
				);
				var wkline_y=new THREE.Line(wkgmr_y,mtr_y);
				group.add(wkline_y);

				var wkgmr_z=new THREE.Geometry();
				wkgmr_z.vertices.push(
					new THREE.Vector3(now2,now1,start),
					new THREE.Vector3(now2,now1,stop)
				);
				var wkline_z=new THREE.Line(wkgmr_z,mtr_z);
				group.add(wkline_z);
			}
		}

		var testGeometry1=new THREE.BoxGeometry(150,150,120);
		var testMaterial1=new THREE.MeshNormalMaterial();
		var testMesh1=new THREE.Mesh(testGeometry1,testMaterial1);
		testMesh1.position.set(100,300,-500);
		group.add(testMesh1);

		var testGeometry2=new THREE.SphereGeometry(70,24,16);
		var testMaterial2=new THREE.MeshNormalMaterial();
		var testMesh2=new THREE.Mesh(testGeometry2,testMaterial2);
		testMesh2.position.set(-120,100,-400);
		group.add(testMesh2);

		var testGeometry3=new THREE.BoxGeometry(150,150,120);
		var testMaterial3=new THREE.MeshNormalMaterial();
		var testMesh3=new THREE.Mesh(testGeometry3,testMaterial3);
		testMesh3.position.set(100,300,500);
		group.add(testMesh3);

		var testGeometry4=new THREE.SphereGeometry(80,24,16);
		var testMaterial4=new THREE.MeshNormalMaterial();
		var testMesh4=new THREE.Mesh(testGeometry4,testMaterial4);
		testMesh4.position.set(-150,-30,500);
		group.add(testMesh4);

		return group;
	}

})(jQuery);