var Viewport = new Class({
    initialize: function()
    {
        this.width = window.innerWidth;
        this.height = window.innerHeight;

        document.body.setStyles({ margin: 0, padding: 0, overflow: 'hidden', background: 'black' });
    },

    aspectRatio: function()
    {
        return this.width / this.height;
    }
});

var Scene = new Class({
    Extends: Viewport,

    initialize: function(fov, znear, zfar)
    {
        this.parent();

        this.scene = new THREE.Scene();

        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setSize(this.width, this.height);
        document.body.appendChild(this.renderer.domElement);

        this.camera = new THREE.PerspectiveCamera(fov, this.aspectRatio(), znear, zfar);
        this.scene.add(this.camera);
    },

    render: function()
    {
        this.renderer.render(this.scene, this.camera);
        this.updateAnimation();
    },

    animate: function()
    {
        requestAnimationFrame(this.animate.bind(this));
        this.render();
    }
});

var Application = new Class({
    Extends: Scene,

    isMouseDown: false,
    prev: new THREE.Vector2(),
    rot: new THREE.Vector2(),
    speed: new THREE.Vector2(0, 0.01),

    initialize: function()
    {
        this.parent(60, 1, 1337);

        this.camera.position.z = 300;

        var geometry = new THREE.CubeGeometry(100, 100, 100);
        var material = new THREE.MeshPhongMaterial({ color: 0x123456, specular: 0xffffff });
        this.mesh = new THREE.Mesh(geometry, material);
        this.scene.add(this.mesh);

        this.light = new THREE.PointLight(0xffffff);
        this.light.position.x = 10;
        this.light.position.y = 50;
        this.light.position.z = 200;
        this.scene.add(this.light);

        document.addEventListener('mousedown', this.onMouseDown.bind(this), false);
        document.addEventListener('mouseup', this.onMouseUp.bind(this), false);
        document.addEventListener('mousemove', this.onMouseMove.bind(this), false);
    },

    updateAnimation: function()
    {
        this.mesh.rotation.x = this.rot.x;
        this.mesh.rotation.y = this.rot.y;
        if (!this.isMouseDown)
        {
            this.rot.x += this.speed.x;
            this.rot.y += this.speed.y;
            if (this.rot.x < -Math.PI/2) this.rot.x = -Math.PI/2;
            if (this.rot.x > Math.PI/2) this.rot.x = Math.PI/2;
            this.speed.multiplyScalar(0.99);
        }
    },

    onMouseDown: function(event)
    {
        this.isMouseDown = true;
        this.prev.x = event.clientX;
        this.prev.y = event.clientY;
        this.speed.x = 0;
        this.speed.y = 0;
    },

    onMouseUp: function(event)
    {
        this.isMouseDown = false;
    },

    onMouseMove: function(event)
    {
        if (!this.isMouseDown)
            return;
        this.speed.x = (event.clientY - this.prev.y) * 0.005;
        this.speed.y = (event.clientX - this.prev.x) * 0.005;
        this.rot.x += this.speed.x;
        this.rot.y += this.speed.y;
        this.prev.x = event.clientX;
        this.prev.y = event.clientY;
        if (this.rot.x < -Math.PI/2) this.rot.x = -Math.PI/2;
        if (this.rot.x > Math.PI/2) this.rot.x = Math.PI/2;
    }
});

window.addEvent("domready", function() {
    var app = new Application();
    app.animate();
});

