//a floor of the level that contains windows
//in addition to windows it has information
//such as ledges and doors.
ig.module('game.floor')
.requires(
    'impact.impact',
    'game.entities.window-b',
    'game.entities.door',
    'game.entities.building-bottom',
    'game.entities.building-middle',
    'game.entities.building-top',
    'game.entities.ledge',
    'game.utils'
)
.defines(function () {
    "use strict";
    ig.global.Floor = function (floorNum, options, windowList, positionOffset, positionOffsetX, floorColor) {
        this.getPlayerPosition = getPlayerPosition;
        this.getBuildingSegment = function () { return buildingSegment; };
        this.getLedge1 = function () { return ledge1; };
        this.getLedge2 = function () { return ledge2; };
        var windows;
        var numWindows = 5;
        var floorSize = { x: IMG.SIZE(1010), y: IMG.SIZE(270) };
        var buildingSegment;
        var hasDoor;
        var isAboveDoor;
        var hasLedge;
        var ledge1;
        var offset;
        var offsetX
        var ledge2;
        var color = floorColor || "Green";
        this.getWindows = function () { return windows; };
        var windowEnum = {
            CENTER: 2,
            FAR_LEFT: 0,
            LEFT: 1,
            RIGHT: 3,
            FAR_RIGHT: 4
        };
        if (positionOffset !== undefined) {
            offset = positionOffset;
        } else {
            offset = 0;
        }
        offsetX = positionOffsetX || 0;
        if (windowList !== undefined) {
            windows = windowList;
        } else {
            windows = [];
        }
        if (options !== undefined) {
            hasDoor = options.hasDoor;
            isAboveDoor = options.isAboveDoor;
        } else {
            hasDoor = false;
            isAboveDoor = false;
        }

        if (floorNum === 4) {
            hasLedge = true;
        } else {
            hasLedge = false;
        }
        this.hasDoor = hasDoor;
        this.isAboveDoor = isAboveDoor;
        createFloor();



        function removeFloor() {
            for (var i = 0; i < windows.length; ++i) {
                windows[i].removeWinodw();
                buildingSegment.kill();
                if (ledge1 !== undefined && ledge2 !== undefined) {
                    ledge1.kill();
                    ledge2.kill();
                }
            }
        }
        //private functions, use function name () not var f = function
        //to get the benifits of hoisting
        function getFloorPosition() {
            var retval = getRawFloorPosition();
            retval.x += offsetX;
            retval.y -= offset;
            return retval;
        };
        //this function is like the above but it ignores the offset,
        //getting just the raw position of the floor
        function getRawFloorPosition() {
            var retval = {
                x: (ig.system.width / 2),
                y: (-floorSize.y * floorNum + ig.system.height)
            };
            return retval;
        };
        function getCenterWindowPosition() {
            var retval = {
                x: getFloorPosition().x,
                y: getFloorPosition().y - IMG.SIZE(30)
            };
            return retval;
        }
        //move window window into position
        //windowIndecies go from left to right
        function positionWindow(window, windowIndex) {
            //half distance between the two windows to the side of the center
            var sideWindowDistance = IMG.SIZE(8);
            //distance between the center window and its ajacent windows
            var centerDistance = IMG.SIZE(0);

            var center = Utils.convertFromBottomCenterToCorner(window, getCenterWindowPosition());
            var leftCenter = { x: center.x, y: center.y };
            var rightCenter = { x: center.x, y: center.y };
            //find the distances to the center of the side window clusters
            leftCenter.x = leftCenter.x - window.size.x - centerDistance - window.size.x - sideWindowDistance;
            rightCenter.x = rightCenter.x + window.size.x + centerDistance + window.size.x + sideWindowDistance;


            window.pos.y = center.y;
            if (windowIndex === windowEnum.FAR_LEFT) {
                window.pos.x = leftCenter.x - window.size.x / 2 - sideWindowDistance;
            } else if (windowIndex === windowEnum.LEFT) {
                window.pos.x = leftCenter.x + window.size.x / 2 + sideWindowDistance;
            } else if (windowIndex === windowEnum.CENTER) {
                window.pos.x = center.x;
            } else if (windowIndex === windowEnum.RIGHT) {
                window.pos.x = rightCenter.x - window.size.x / 2 - sideWindowDistance;
            } else if (windowIndex === windowEnum.FAR_RIGHT) {
                window.pos.x = rightCenter.x + window.size.x / 2 + sideWindowDistance;
            }
            window.moveObstacles();
        };
        function zeroOffset() {
            offset = 0;
            offsetX = 0;
        };
        function updateOffset() {
            //note that this is the position of the bottom center of
            //the object, that does not matter since we are only calculateing
            //offsets
            var currentPos = Utils.convertFromCornerToCenter(buildingSegment, buildingSegment.pos);
            var positionNoOffset = getRawFloorPosition();
            offset = positionNoOffset.y - currentPos.y;
            offsetX = currentPos.x -  positionNoOffset.x;
            
        }
        //goes through all the windows and positions them, needed both for level init
        //and for adjusting the positions of stuff after a screen rotation
        function positionWindows() {
            for(var i = 0; i < numWindows; ++i) {
                positionWindow(windows[i], i);
            }
        }
        //repositions the floor after a rotation change
        function reposition() {
             
            buildingSegment.pos = Utils.convertFromBottomCenterToCorner(buildingSegment, getFloorPosition());
            if(hasLedge) {
                ledge1.pos.x = buildingSegment.pos.x;
                ledge1.pos.y = buildingSegment.pos.y;
                ledge2.pos.x = buildingSegment.pos.x + IMG.SIZE(500);
                ledge2.pos.y = buildingSegment.pos.y;
            }
            positionWindows();
        }
        //creates a floor and populates it with windows and the like
        //also will be loading level data from the xml file (not in this function)
        //we get the floor number from the closure
        function createFloor() {
            if (hasDoor) {
                buildingSegment = Utils.spawnEntityAt(EntityBuildingBottom, getFloorPosition());
            } else if (isAboveDoor) {
                buildingSegment = Utils.spawnEntityAt(EntityBuildingTop, getFloorPosition());
            } else {
                buildingSegment = Utils.spawnEntityAt(EntityBuildingMiddle, getFloorPosition());
            }
            if (hasLedge) {
                //if we are done spawning floor 4 go ahead and spawn a ledge between 4 and 5
                ledge1 = ig.game.spawnEntity(EntityLedge, buildingSegment.pos.x, buildingSegment.pos.y);
                //spawn another one to make the ledge go all across
                ledge2 = ig.game.spawnEntity(EntityLedge, buildingSegment.pos.x + IMG.SIZE(500), buildingSegment.pos.y);
                ledge2.currentAnim.flip.x = true;
            }



            //create all the windows we need and move them into place
            //we only do this is the window index is not defiend
            //so that we dont clobber windows passed in via the
            //constructor
            for (var i = 0; i < numWindows; ++i) {
                if (windows[i] === undefined) {
                    windows.push(ig.game.spawnEntity(EntityWindowA, 0, 0, {color: color}));
                    //the top two windows and in fact any windows spawned on
                    //a level with no window spec should be unbreakable
                    windows[i].finalAnim = windows[i].anims.unbreakable;
                    windows[i].currentAnim = windows[i].anims.unbreakable;

                }
                
            }
            positionWindows();
            //remove the center windows on floors zero and one
            //note this is a slight optimization opertunity as we
            //do create and the immediately remove the window,
            //this programmer thinks it is eaiser to follow this way
            //
            //also spawn the door
            if (hasDoor === true) {
                ig.game.removeEntity(windows[windowEnum.CENTER]);
                delete windows[windowEnum.CENTER];
                windows[windowEnum.CENTER] = ig.game.spawnEntity(EntityDoor, 0, 0);
                positionWindow(windows[windowEnum.CENTER], windowEnum.CENTER);
            }
            //move the animation sheet of the 2nd floor window down a little to make sure
            //that it is totally behaind the door
            if (isAboveDoor === undefined) {
                this.windows[windowEnum.CENTER].offset.y = -100;
            }

        }

        
        
        //this is now a compatability thunk
        function getPlayerPosition(windowIndex) {
            return this.windows[windowIndex].getPlayerPosition();
        }
        this.updateOffset = updateOffset;
        this.zeroOffset = zeroOffset;
        this.reposition = reposition;
        this.windows = windows
        this.removeFloor = removeFloor;
    };
});
