var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
import * as THREE from 'three';
var HALF_PI = Math.PI / 2;
var QUARTER_PI = Math.PI / 4;
var WIDTH = 150;
var HEIGHT = 150;
var clickBoxes = [
    // TOP
    {
        position: [0, 0, 1],
        size: [1.5, 1.5, 0.001],
        cameraAngle: [-HALF_PI, 0],
    },
    // BOTTOM
    {
        position: [0, 0, -1],
        size: [1.5, 1.5, 0.001],
        cameraAngle: [-HALF_PI, Math.PI],
    },
    // FRONT
    {
        position: [0, -1, 0],
        size: [1.5, 0.001, 1.5],
        cameraAngle: [-HALF_PI, HALF_PI],
    },
    // BACK
    {
        position: [0, 1, 0],
        size: [1.5, 0.001, 1.5],
        cameraAngle: [HALF_PI, HALF_PI],
    },
    // RIGHT
    {
        position: [1, 0, 0],
        size: [0.001, 1.5, 1.5],
        cameraAngle: [0, HALF_PI],
    },
    // LEFT
    {
        position: [-1, 0, 0],
        size: [0.001, 1.5, 1.5],
        cameraAngle: [-Math.PI, HALF_PI],
    },
    // TOP-FRONT
    {
        position: [0, -0.876, 0.876],
        size: [1.5, 0.25, 0.25],
        cameraAngle: [-HALF_PI, QUARTER_PI],
    },
    // TOP-LEFT
    {
        position: [-0.876, 0, 0.876],
        size: [0.25, 1.5, 0.25],
        cameraAngle: [-Math.PI, QUARTER_PI],
    },
    // TOP-BACK
    {
        position: [0, 0.876, 0.876],
        size: [1.5, 0.25, 0.25],
        cameraAngle: [HALF_PI, QUARTER_PI],
    },
    // TOP-RIGHT
    {
        position: [0.876, 0, 0.876],
        size: [0.25, 1.5, 0.25],
        cameraAngle: [0, QUARTER_PI],
    },
    // BOTTOM-FRONT
    {
        position: [0, -0.876, -0.876],
        size: [1.5, 0.25, 0.25],
        cameraAngle: [-HALF_PI, 3 * QUARTER_PI],
    },
    // BOTTOM-LEFT
    {
        position: [-0.876, 0, -0.876],
        size: [0.25, 1.5, 0.25],
        cameraAngle: [-Math.PI, 3 * QUARTER_PI],
    },
    // BOTTOM-BACK
    {
        position: [0, 0.876, -0.876],
        size: [1.5, 0.25, 0.25],
        cameraAngle: [HALF_PI, 3 * QUARTER_PI],
    },
    // BOTTOM-RIGHT
    {
        position: [0.876, 0, -0.876],
        size: [0.25, 1.5, 0.25],
        cameraAngle: [0, 3 * QUARTER_PI],
    },
    // FRONT-LEFT
    {
        position: [-0.876, -0.876, 0],
        size: [0.25, 0.25, 1.5],
        cameraAngle: [-3 * QUARTER_PI, HALF_PI],
    },
    // FRONT-RIGHT
    {
        position: [0.876, -0.876, 0],
        size: [0.25, 0.25, 1.5],
        cameraAngle: [-QUARTER_PI, HALF_PI],
    },
    // BACK-LEFT
    {
        position: [-0.876, 0.876, 0],
        size: [0.25, 0.25, 1.5],
        cameraAngle: [3 * QUARTER_PI, HALF_PI],
    },
    // BACK-RIGHT
    {
        position: [0.876, 0.876, 0],
        size: [0.25, 0.25, 1.5],
        cameraAngle: [QUARTER_PI, HALF_PI],
    },
    // TOP-FRONT-LEFT
    {
        position: [-0.876, -0.876, 0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [-3 * QUARTER_PI, QUARTER_PI],
    },
    // TOP-FRONT-RIGHT
    {
        position: [0.876, -0.876, 0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [-QUARTER_PI, QUARTER_PI],
    },
    // TOP-BACK-LEFT
    {
        position: [-0.876, 0.876, 0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [3 * QUARTER_PI, QUARTER_PI],
    },
    // TOP-BACK-RIGHT
    {
        position: [0.876, 0.876, 0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [QUARTER_PI, QUARTER_PI],
    },
    // BOTTOM-FRONT-LEFT
    {
        position: [-0.876, -0.876, -0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [-3 * QUARTER_PI, 3 * QUARTER_PI],
    },
    // BOTTOM-FRONT-RIGHT
    {
        position: [0.876, -0.876, -0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [-QUARTER_PI, 3 * QUARTER_PI],
    },
    // BOTTOM-BACK-LEFT
    {
        position: [-0.876, 0.876, -0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [3 * QUARTER_PI, 3 * QUARTER_PI],
    },
    // BOTTOM-BACK-RIGHT
    {
        position: [0.876, 0.876, -0.876],
        size: [0.25, 0.25, 0.25],
        cameraAngle: [QUARTER_PI, 3 * QUARTER_PI],
    },
];
var NavigationBox = /** @class */ (function () {
    function NavigationBox(container, options) {
        if (options === void 0) { options = {}; }
        var _this = this;
        this.getBoxFromPosition = function (x, y) {
            var _a = _this.container.getBoundingClientRect(), left = _a.left, top = _a.top, width = _a.width, height = _a.height;
            var mousePosition = new THREE.Vector2();
            mousePosition.x = ((x - left) / width) * 2 - 1;
            mousePosition.y = -((y - top) / height) * 2 + 1;
            var raycaster = new THREE.Raycaster();
            raycaster.setFromCamera(mousePosition, _this.camera);
            var intersects = raycaster.intersectObjects(_this.boxes.children, true);
            if (intersects.length > 0) {
                return intersects[0].object;
            }
            return undefined;
        };
        this.onMouseMove = function (e) {
            var box = _this.getBoxFromPosition(e.clientX, e.clientY);
            var needsRender = false;
            if (_this.hoverBox) {
                var material = _this.hoverBox.material;
                material.opacity = 0;
                needsRender = true;
            }
            if (box) {
                var material = box.material;
                material.opacity = 0.6;
                _this.hoverBox = box;
                needsRender = true;
            }
            if (needsRender) {
                _this.renderer.render(_this.scene, _this.camera);
            }
        };
        this.onClick = function (e) {
            var onChangeCameraAngle = _this.options.onChangeCameraAngle;
            if (!onChangeCameraAngle)
                return;
            var box = _this.getBoxFromPosition(e.clientX, e.clientY);
            if (box) {
                var clickBox = box.userData;
                onChangeCameraAngle.apply(void 0, clickBox.cameraAngle);
            }
        };
        this.container = container;
        this.options = __assign({}, options, NavigationBox.defaultOptions);
        this.setup();
    }
    NavigationBox.prototype.setup = function () {
        return __awaiter(this, void 0, void 0, function () {
            var rendererParams, renderer, spotLight, spotLight2, boxGeometry, boxLabels, cubeMaterials, cube;
            var _this = this;
            return __generator(this, function (_a) {
                rendererParams = {
                    alpha: true,
                    antialias: true,
                };
                renderer = new THREE.WebGLRenderer(rendererParams);
                renderer.setSize(WIDTH, HEIGHT);
                this.container.appendChild(renderer.domElement);
                this.renderer = renderer;
                this.container.addEventListener('mousemove', this.onMouseMove);
                this.container.addEventListener('click', this.onClick);
                this.containerRect = this.container.getBoundingClientRect();
                this.scene = new THREE.Scene();
                this.scene.add(new THREE.AmbientLight(0x888888));
                spotLight = new THREE.SpotLight(0xeeeeee);
                spotLight.position.set(2, -4, 3);
                this.scene.add(spotLight);
                spotLight2 = new THREE.SpotLight(0xdddddd);
                spotLight2.position.set(-8, 8, -6);
                this.scene.add(spotLight2);
                boxGeometry = new THREE.BoxGeometry(2, 2, 2);
                boxLabels = this.options.boxLabels;
                cubeMaterials = [
                    new THREE.MeshLambertMaterial({
                        map: this.getTextureForText(boxLabels.right, HALF_PI),
                    }),
                    new THREE.MeshLambertMaterial({
                        map: this.getTextureForText(boxLabels.left, -HALF_PI),
                    }),
                    new THREE.MeshLambertMaterial({
                        map: this.getTextureForText(boxLabels.back, Math.PI),
                    }),
                    new THREE.MeshLambertMaterial({
                        map: this.getTextureForText(boxLabels.front),
                    }),
                    new THREE.MeshLambertMaterial({
                        map: this.getTextureForText(boxLabels.top),
                    }),
                    new THREE.MeshLambertMaterial({
                        map: this.getTextureForText(boxLabels.bottom, Math.PI),
                    }),
                ];
                cube = new THREE.Mesh(boxGeometry, cubeMaterials);
                this.scene.add(cube);
                this.boxes = new THREE.Group();
                clickBoxes.forEach(function (clickBox) {
                    var _a, _b;
                    var geometry = new ((_a = THREE.BoxGeometry).bind.apply(_a, [void 0].concat(clickBox.size)))();
                    var material = new THREE.MeshBasicMaterial({
                        color: 0x4dc3ff,
                        transparent: true,
                        opacity: 0,
                    });
                    var box = new THREE.Mesh(geometry, material);
                    (_b = box.position).set.apply(_b, clickBox.position);
                    box.userData = clickBox;
                    _this.boxes.add(box);
                });
                this.scene.add(this.boxes);
                this.setOrtographicCamera(false);
                this.renderer.render(this.scene, this.camera);
                return [2 /*return*/];
            });
        });
    };
    NavigationBox.prototype.getTextureForText = function (text, rotation) {
        if (rotation === void 0) { rotation = 0; }
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        canvas.width = 128;
        canvas.height = 128;
        if (ctx) {
            ctx.font = '20px Roboto,Arial';
            ctx.fillStyle = '#cccccc';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = 'black';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(text, canvas.width / 2, canvas.height / 2);
        }
        var texture = new THREE.Texture(canvas);
        texture.center = new THREE.Vector2(0.5, 0.5);
        texture.rotation = rotation;
        texture.needsUpdate = true;
        return texture;
    };
    NavigationBox.prototype.setOrtographicCamera = function (isOrtographic) {
        if (isOrtographic) {
            this.camera = new THREE.OrthographicCamera(-2, 2, 2, -2, -10, 10);
        }
        else {
            this.camera = new THREE.PerspectiveCamera(50, 1, 0.1, 1000);
            this.camera.aspect = WIDTH / HEIGHT;
        }
        this.camera.up.set(0, 0, 1);
        this.camera.updateProjectionMatrix();
    };
    NavigationBox.prototype.updateCamera = function (x, y, z) {
        this.camera.position.set(x * 5, y * 5, z * 5);
        this.camera.lookAt(this.scene.position);
        this.renderer.render(this.scene, this.camera);
    };
    NavigationBox.defaultOptions = {
        boxLabels: {
            front: 'FRONT',
            back: 'BACK',
            top: 'TOP',
            bottom: 'BOTTOM',
            left: 'LEFT',
            right: 'RIGHT',
        },
    };
    return NavigationBox;
}());
export default NavigationBox;
//# sourceMappingURL=NavigationBox.js.map