define(["three", "camera", "skySphere", "meshTree", "util", "random", "objects"],
    function(THREE, camera, skySphere, MeshTree, Util, Random, objects) {
        var scene = new THREE.Scene();

        var hat;

        var light, hemiLight
        var textMaterial;
        var textPlaneMesh;

        var frontLight;

        var hatGridSize = 15,
            hatSize     = 3,
            hatScale    = 0.6;

        var hats = [];

        var sceneTime = 0;

        scene.init = function() {
            light = new THREE.SpotLight(0xFFFFFF, 2);
            light.position.set(-5, 10, 0);

            hemiLight = new THREE.HemisphereLight(0xFFFFFF, 0x666666, 1);
            frontLight = new THREE.PointLight(0xFFFFFF, 0.1, 150);
            frontLight.position.set(0, 0, 50);

            scene.add(frontLight);

            var textPlaneMesh = objects.textPlane.clone();
            textPlaneMesh.position.set(-25, 0, 0);

            var hatGrid = new THREE.Object3D();
            hatGrid.position.set(25, 0, 0);

            var sz = (hatGridSize * hatSize) / 2;

            for(var x = 0; x < hatGridSize; ++x) {
                for(var y = 0; y <  hatGridSize; ++y) {
                    var hat = objects.hat.clone();
                    hat.position.set(x * hatSize - sz, y * hatSize - sz, Math.random() * 4);
                    hat.originalPos = hat.position.clone();
                    hat.rotation.copy(Util.randomEuler());
                    hat.scale.set(hatScale, hatScale, hatScale);
                    hat.material = hat.material.clone();

                    if(!(x in hats))
                        hats[x] = [];

                    hats[x][y] = hat;

                    hatGrid.add(hat); 
                }
            }

            scene.add(hatGrid);

            scene.add(textPlaneMesh);
            scene.add(hemiLight);
            scene.add(skySphere.clone());
            scene.add(light);
        }        

        scene.enter = function() {
            camera.position.set(-30, 0, 100);
            camera.rotation.set(0, -0.2, 0);

            sceneTime = 0;
        }

        scene.update = function(t, dt) {
            var beatTime = Util.beatsToTime(130, {
                bars: 2
            });

            sceneTime += dt;

            for(var x = 0; x < hatGridSize; ++x) {
                for(var y = 0; y < hatGridSize; ++y) {
                    var hat = hats[x][y];
                    hat.position.setX(
                        hat.originalPos.x + Math.sin(t * Util.PI2 / beatTime + y) * 3
                    );

                    hat.position.setY(
                        hat.originalPos.y + Math.cos(t * Util.PI2 / beatTime + x) * 3
                    );

                    var red = Math.sin(t+y) * 0.5 + 0.5;
                    var blue = Math.sin(t+x) * 0.5 + 0.5;

                    hat.material.color.setRGB(red, 0.2, blue);
                }
            }

            camera.rotation.y -= dt * 0.02;
            camera.position.x += dt * 1.5;

            this.fadeAmount = (1.0 - (sceneTime * 2)).clamp(0, 1);
        }

        return scene;
    });
                  