/**
 * 全景构造函数
 * @param viewer 当前场景食堂
 * @param options 配置参数
 * @constructor
 */
function Panorama(viewer, options) {
    let _self = this;
    _self.id = 0;
    _self.viewer = viewer;
    _self.options = options;
    _self.road = null;
    _self.handler = null;
    _self.angle = null;
    _self.entity = null;
    _self.scene = null;
    _self.renderer = null;
    _self.material = null;
    _self.camera = null;
    _self.index = null;
    _self.minindex = 1900;
    _self.maxindex = 3175;
    _self.isFocus3D = false;
    _self.width = 960;
    _self.height = 938;
    _self.isUserInteracting = false,
        _self.onMouseDownMouseX = 0, _self.onMouseDownMouseY = 0,
        _self.lon = 180, _self.onMouseDownLon = 0,
        _self.lat = 0, _self.onMouseDownLat = 0,
        _self.phi = 0, _self.theta = 0;
    init();

    /**
     * 获得当前三维场景焦点
     */
    $('#mainscene').mouseenter(function () {
        _self.isFocus3D = true;
    });
    /**
     * 获得当前二维地图焦点
     */
    $('#panorama').mouseenter(function () {
        _self.isFocus3D = false;
    });

    /**
     * 加载全景路线
     */
    function init() {
        loadRoad();
    }

    /**
     * 获取前进方向
     * @param point1 前点
     * @param point2 后点
     * @returns {number|*} 方位角
     */
    function getDirection(point1, point2) {
        return turf.rhumbBearing(turf.point(point1, {}), turf.point(point2, {}));
    }

    /**
     * 创建全景场景
     * @param num 全景编号
     */
    function createScene(num) {
        _self.scene = new THREE.Scene();
        _self.renderer = new THREE.WebGLRenderer({antialias: true});
        _self.renderer.setSize(_self.width, _self.height);
        _self.renderer.setViewport(0, 0, _self.width, _self.height);
        document.body.appendChild(_self.renderer.domElement);
        document.getElementById("panorama").appendChild(_self.renderer.domElement);
        _self.camera = new THREE.PerspectiveCamera(45, _self.width / _self.height, 1, 10000);
        _self.camera.target = new THREE.Vector3(0, 0, 0);
        var geometry = new THREE.SphereBufferGeometry(500, 60, 40);
        geometry.scale(-1, 1, 1);
        _self.material = new THREE.MeshBasicMaterial({
            map: new THREE.TextureLoader().load(_self.options.name + num + _self.options.format)
        });
        _self.mesh = new THREE.Mesh(geometry, _self.material);
        _self.scene.add(_self.mesh);
        window.onresize = onWindowResize;
        document.addEventListener('mousedown', onPointerStart, false);
        document.addEventListener('mousemove', onPointerMove, false);
        document.addEventListener('mouseup', onPointerUp, false);
    }

    /**
     * 鼠标点击事件
     * @param event
     */
    function onPointerStart(event) {
        _self.isUserInteracting = true;
        var clientX = event.clientX || event.touches[0].clientX;
        var clientY = event.clientY || event.touches[0].clientY;
        _self.onMouseDownMouseX = clientX;
        _self.onMouseDownMouseY = clientY;
        _self.onMouseDownLon = _self.lon;
        _self.onMouseDownLat = _self.lat;
    }

    /**
     * 鼠标移动事件
     * @param event
     */
    function onPointerMove(event) {
        if (_self.isUserInteracting === true) {
            var clientX = event.clientX || event.touches[0].clientX;
            var clientY = event.clientY || event.touches[0].clientY;
            _self.lon = (_self.onMouseDownMouseX - clientX) * 0.1 + _self.onMouseDownLon;
            _self.lat = (clientY - _self.onMouseDownMouseY) * 0.1 + _self.onMouseDownLat;
            syncPanoramaView();
        }
    }

    /**
     * 全景拖动开关
     */
    function onPointerUp() {
        _self.isUserInteracting = false;
    }

    /**
     * 实时渲染相机视角
     */
    function update() {
        _self.lat = Math.max(-85, Math.min(85, _self.lat));
        _self.phi = THREE.Math.degToRad(90 - _self.lat);
        _self.theta = THREE.Math.degToRad(_self.lon);
        _self.camera.target.x = 500 * Math.sin(_self.phi) * Math.cos(_self.theta);
        _self.camera.target.y = 500 * Math.cos(_self.phi);
        _self.camera.target.z = 500 * Math.sin(_self.phi) * Math.sin(_self.theta);
        _self.camera.lookAt(_self.camera.target);
        _self.renderer.render(_self.scene, _self.camera);
    }

    /**
     * 三维视角
     */
    function sync3DView() {
        if (_self.isFocus3D) {
            _self.lat = Freedo.Math.toDegrees(_self.viewer.camera.pitch);
            _self.lon = Freedo.Math.toDegrees(_self.viewer.camera.heading - Freedo.Math.toRadians(_self.angle)) + 180;
        }
    }

    /**
     * 全景视角
     */
    function syncPanoramaView() {
        if (!_self.isFocus3D) {
            _self.viewer.camera.setView({
                orientation: new Freedo.HeadingPitchRoll(Freedo.Math.toRadians(_self.lon + _self.angle + 180), Freedo.Math.toRadians(_self.lat), 0),
            });
        }
    }

    /**
     * 三维视角向前
     * @param num
     */
    function forward(num) {
        new THREE.TextureLoader().load(_self.options.name + ++num + _self.options.format, function (texture) {
            _self.material.map = texture;
            _self.material.map.needsUpdate = true;
        });


    }

    /**
     * 三维视角向后
     * @param num
     */
    function backward(num) {
        new THREE.TextureLoader().load(_self.options.name + --num + _self.options.format, function (texture) {
            _self.material.map = texture;
            _self.material.map.needsUpdate = true;
        });
    }

    /**
     * 屏幕自适应
     */
    function onWindowResize() {
        _self.camera.aspect = _self.width / _self.height;
        _self.camera.updateProjectionMatrix();
        _self.renderer.setSize(_self.width, _self.height);
    }

    /**
     * 实时渲染
     */
    function animate() {
        update();
        _self.id = requestAnimationFrame(animate);
    }

    /**
     * 加载全景路线
     */
    function loadRoad() {
        let road = Freedo.GeoJsonDataSource.load(_self.options.url, {clampToGround: true});
        road.then(function (dataSource) {
            for (let i = 0; i < dataSource.entities._entities._array.length; i++) {
                dataSource.entities._entities._array[i].billboard = new Freedo.BillboardGraphics({
                    show: true,
                    position: dataSource.entities._entities._array[i]._position._value,
                    pixelOffset: new Freedo.Cartesian2(0, 0),
                    eyeOffset: new Freedo.Cartesian3(0.0, 0.0, 0.0),
                    horizontalOrigin: Freedo.HorizontalOrigin.CENTER,
                    verticalOrigin: Freedo.VerticalOrigin.BOTTOM,
                    width: 1,
                    height: 1,
                    image: "Build/Static/img/vr.png",
                    color: new Freedo.Color(1.0, 1.0, 1.0, 1.0),
                    sizeInMeters: true
                });
            }
            _self.road = dataSource;
            viewer.dataSources.add(_self.road);
            _self.handler = new Freedo.ScreenSpaceEventHandler(viewer.scene.canvas);
            _self.handler.setInputAction(function onClick(movement) {
                var position = viewer.scene.pickPosition(movement.position);
                if (position) {
                    let pickedFeature = viewer.scene.pick(movement.position);
                    if (pickedFeature) {
                        if (pickedFeature.id instanceof Freedo.Entity && pickedFeature.primitive) {
                            if (pickedFeature.id.properties.ImageName && pickedFeature.primitive._index) {
                                if (_self.entity) {
                                    _self.entity.show = true;
                                }
                                _self.entity = pickedFeature.id;
                                _self.entity.show = false;
                                $('#mainscene').width('50%');
                                $('#panorama').show();
                                let index = pickedFeature.primitive._index;
                                let name = _self.entity.properties.ImageName.getValue();
                                let num = parseInt(name.substring(20, 24));
                                let bpoint = _self.entity.position.getValue(),
                                    fpoint = _self.road.entities.values[num - 1900 + 1].position.getValue();
                                let bcpoint = cartesian2LonLat(bpoint);
                                _self.angle = getDirection(cartesian2LonLat(bpoint), cartesian2LonLat(fpoint));
                                if (_self.scene) {
                                    if (_self.index) {
                                        (num > _self.index) ? forward(num) : backward(num);
                                    }
                                } else {
                                    createScene(num);
                                }
                                _self.index = num;
                                _self.viewer.camera.changed.addEventListener(sync3DView);
                                viewer.camera.lookAt(new Freedo.Cartesian3.fromDegrees(bcpoint[0], bcpoint[1], bcpoint[2] + 2), new Freedo.HeadingPitchRange(Freedo.Math.toRadians(_self.angle), 0, 1));
                                animate();
                            }
                        }
                    }
                }
            }, Freedo.ScreenSpaceEventType.LEFT_CLICK);
        });
    }

    /**
     * 球星坐标转经纬度
     * @param cartesian 球星坐标
     * @returns {*[]} 经纬度坐标
     */
    function cartesian2LonLat(cartesian) {
        var cartographic = Freedo.Cartographic.fromCartesian(cartesian);
        var lon = Freedo.Math.toDegrees(cartographic.longitude);
        var lat = Freedo.Math.toDegrees(cartographic.latitude);
        return [lon, lat, cartographic.height];
    }


    Panorama.prototype.destroy = function () {
        cancelAnimationFrame(_self.id);
        _self.viewer.dataSources.remove(_self.road);
        _self.viewer.camera.changed.removeEventListener(sync3DView);
        _self.viewer.camera.lookAtTransform(Freedo.Matrix4.IDENTITY);
        _self.handler.removeInputAction(Freedo.ScreenSpaceEventType.LEFT_CLICK);
        $('#mainscene').width('100%');
        $('#panorama').hide();
        $("#panorama").text('');
    }


}