import "jasmine";
import { PositionNotifier } from "../src/Model/PositionNotifier";
import { User, UserSocket } from "../src/Model/User";
import { Zone } from "_Model/Zone";
import { Movable } from "_Model/Movable";
import { PositionInterface } from "_Model/PositionInterface";
import { ZoneSocket } from "../src/RoomManager";

describe("PositionNotifier", () => {
    it("should receive notifications when player moves", () => {
        let enterTriggered = false;
        let moveTriggered = false;
        let leaveTriggered = false;

        const positionNotifier = new PositionNotifier(
            300,
            300,
            (thing: Movable) => {
                enterTriggered = true;
            },
            (thing: Movable, position: PositionInterface) => {
                moveTriggered = true;
            },
            (thing: Movable) => {
                leaveTriggered = true;
            },
            () => {},
            () => {}
        );

        const user1 = new User(
            1,
            "test",
            "10.0.0.2",
            {
                x: 500,
                y: 500,
                moving: false,
                direction: "down",
            },
            false,
            positionNotifier,
            {} as UserSocket,
            [],
            null,
            "foo",
            []
        );

        const user2 = new User(
            2,
            "test",
            "10.0.0.2",
            {
                x: -9999,
                y: -9999,
                moving: false,
                direction: "down",
            },
            false,
            positionNotifier,
            {} as UserSocket,
            [],
            null,
            "foo",
            []
        );

        positionNotifier.addZoneListener({} as ZoneSocket, 0, 0);
        positionNotifier.addZoneListener({} as ZoneSocket, 0, 1);
        positionNotifier.addZoneListener({} as ZoneSocket, 1, 1);
        positionNotifier.addZoneListener({} as ZoneSocket, 1, 0);
        /*positionNotifier.setViewport(user1, {
            left: 200,
            right: 600,
            top: 100,
            bottom: 500
        });*/

        user2.setPosition({ x: 500, y: 500, direction: "down", moving: false });

        expect(enterTriggered).toBe(true);
        expect(moveTriggered).toBe(false);
        enterTriggered = false;

        // Move inside the zone
        user2.setPosition({ x: 501, y: 500, direction: "down", moving: false });

        expect(enterTriggered).toBe(false);
        expect(moveTriggered).toBe(true);
        moveTriggered = false;

        // Move out of the zone in a zone that we don't track
        user2.setPosition({ x: 901, y: 500, direction: "down", moving: false });

        expect(enterTriggered).toBe(false);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(true);
        leaveTriggered = false;

        // Move back in
        user2.setPosition({ x: 500, y: 500, direction: "down", moving: false });
        expect(enterTriggered).toBe(true);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(false);
        enterTriggered = false;

        // Leave the room
        positionNotifier.leave(user2);
        //positionNotifier.removeViewport(user2);
        expect(enterTriggered).toBe(false);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(true);
        leaveTriggered = false;
    });

    it("should receive notifications when camera moves", () => {
        let enterTriggered = false;
        let moveTriggered = false;
        let leaveTriggered = false;

        const positionNotifier = new PositionNotifier(
            300,
            300,
            (thing: Movable, fromZone: Zone | null) => {
                enterTriggered = true;
            },
            (thing: Movable, position: PositionInterface) => {
                moveTriggered = true;
            },
            (thing: Movable) => {
                leaveTriggered = true;
            },
            () => {},
            () => {}
        );

        const user1 = new User(
            1,
            "test",
            "10.0.0.2",
            {
                x: 500,
                y: 500,
                moving: false,
                direction: "down",
            },
            false,
            positionNotifier,
            {} as UserSocket,
            [],
            null,
            "foo",
            []
        );

        const user2 = new User(
            2,
            "test",
            "10.0.0.2",
            {
                x: 0,
                y: 0,
                moving: false,
                direction: "down",
            },
            false,
            positionNotifier,
            {} as UserSocket,
            [],
            null,
            "foo",
            []
        );

        const listener = {} as ZoneSocket;
        positionNotifier.addZoneListener(listener, 0, 0);
        positionNotifier.addZoneListener(listener, 0, 1);
        positionNotifier.addZoneListener(listener, 1, 1);
        positionNotifier.addZoneListener(listener, 1, 0);
        /*let newUsers = positionNotifier.setViewport(user1, {
            left: 200,
            right: 600,
            top: 100,
            bottom: 500
        });*/
        positionNotifier.enter(user1);
        positionNotifier.enter(user2);

        //expect(newUsers.length).toBe(2);
        expect(enterTriggered).toBe(true);
        enterTriggered = false;

        //positionNotifier.updatePosition(user2, {x:500, y:500}, {x:0, y: 0})
        user2.setPosition({ x: 500, y: 500, direction: "down", moving: false });

        expect(enterTriggered).toBe(true);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(true);
        enterTriggered = false;
        leaveTriggered = false;

        // Add a listener, but the user in not in this zone.
        positionNotifier.addZoneListener(listener, 10, 10);

        /*positionNotifier.setViewport(user1, {
            left: 201,
            right: 601,
            top: 100,
            bottom: 500
        });*/

        expect(enterTriggered).toBe(false);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(false);

        // Stop listening to zone
        positionNotifier.removeZoneListener(listener, 1, 1);
        // Move the viewport out of the user.
        /*positionNotifier.setViewport(user1, {
            left: 901,
            right: 1001,
            top: 100,
            bottom: 500
        });*/

        expect(enterTriggered).toBe(false);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(false);

        // Move the viewport back on the user.
        positionNotifier.addZoneListener(listener, 1, 1);
        /*newUsers = positionNotifier.setViewport(user1, {
            left: 200,
            right: 600,
            top: 100,
            bottom: 500
        });*/

        expect(enterTriggered).toBe(false);
        expect(moveTriggered).toBe(false);
        expect(leaveTriggered).toBe(false);
        enterTriggered = false;
        //expect(newUsers.length).toBe(2);
    });
});