import * as dotenv from "dotenv";
import chai from "chai";
import * as _ from "lodash";
const chaiHttp = require("chai-http");

chai.use(chaiHttp);

const should = chai.should();

dotenv.config({ path: __dirname + "/.env" });

import * as TestUtils from "../utils/TestUtils";
import * as QueueTestProxy from "../utils/QueueTestProxy";
import { Cloud } from "../../cloud/src/Cloud";
import * as Models from "../../cloud/src/Models";
import { MessageQueue, Queue, BigscreenCloudCommands, MediaServerCommands } from "../../cloud/src/MessageQueue";
import CloudApiServer from "../../cloud/cloud_api/cloud_api";

const cloudApiKey = "f4czwPZdYidGTcWRbhcWAcFiTaDYhYDraDsjYLYO2YXd4LxQqpMpbcdmyxZEBKNZ";
const cloudAdminApiKey = "f4czwPZdYidGTcWRbhcWAcFiTaDYhYDraDsjYLYO2YXd4LxQqpMpbcdmyxZEBKNZ";

describe("Test room expiration.", () => {
    const VERSION = "0.9.0";
    let testUser: CloudSchemas.BigscreenUser = null;
    let testUser2: CloudSchemas.BigscreenUser = null;
    let testRoomSettings : Models.RoomSettings = null;

    let roomId = null;
    const nextRoomId = null;
    let mediaServerAlpha = null;

    before(async () => {
        await Cloud.initialize({ watchExpired: true });
        await Cloud.flushAll();
        testUser = await CloudTestUtils.generateTestUser(0, VERSION);
        testUser2 = await CloudTestUtils.generateTestUser(1, VERSION);
        testRoomSettings = CloudTestUtils.generateCreateRoomRequest(VERSION, 4);
        await QueueTestProxy.startTestQueue();
        
        mediaServerAlpha = CloudTestUtils.generateMediaServer(VERSION);

        const env = process.env;
        env.NODE_ENV = "TEST_ROOM_EXPIRATION";
        process.env = env;
    });

    it("Media server alpha registration succeeds", async () => {
        MessageQueue.sendMessage(Queue.BigscreenCloud, {
            command: BigscreenCloudCommands.RegisterMediaServer,
            payload: {
                ...mediaServerAlpha
            }
        });

        const bigscreenCloudMessage = await QueueTestProxy.getLastBigscreenCloudMessage();
        bigscreenCloudMessage.should.have.property("command").eql(BigscreenCloudCommands.RegisterMediaServer);
        bigscreenCloudMessage.should.have.property("payload");

        const mediaServer = await Cloud.registerMediaServer(bigscreenCloudMessage.payload);
        
        mediaServer.should.have.property("id").eql(mediaServerAlpha.id);
        mediaServer.should.have.property("createdAt");
        mediaServer.should.have.property("version").eql(VERSION);
        mediaServer.should.have.property("ipAddress").eql(mediaServerAlpha.ipAddress);
        mediaServer.should.have.property("load").eql(mediaServerAlpha.load);
    });

    it("connection succeeds", async () => {
        await Cloud.addBigscreenUser(testUser);
        await Cloud.addBigscreenUser(testUser2);
        const userIds = await Cloud.getUserIds();
        userIds.should.include.members([testUser.id, testUser2.id]);
    });

    it("create a room succeeds", async () => {
        const res = await chai.request(CloudApiServer)
            .post("/room")
            .set("Authorization", `Bearer ${apiKey}`)
            .set("x-access-token", testUser.accessToken)
            .send(testRoomSettings.toObject());
        res.should.have.status(200);
        const room = res.body;
        roomId = room.roomId;
    });

    it("room should exist and have values", async () => {
        const retrievedRoom = await Cloud.getLiveRoom(roomId);
        retrievedRoom.should.have.property("roomId").eql(roomId);
    });

    it("room should be in latest-rooms", async () => {
        const publicRooms = await Cloud.getPublicRooms();
        publicRooms.should.be.an("array");
        publicRooms[0].should.have.property("roomId").eql(roomId);
    });

    it("Wait for 6 seconds for the room to expire.", async () => {
            await TestUtils.sleep(6000);
            /*
            for (let i = 0; i < 21; ++i) {
            const res = await chai.request(CloudApiServer)
                .get("/room")
                .set("Authorization", `Bearer ${apiKey}`)
                .set("x-access-token", testUser2.accessToken)
        }*/
    });

    it("room should not exist", async () => {
        const retrievedRoom = await Cloud.getLiveRoom(roomId);
        chai.expect(retrievedRoom).to.be.null;
    });

    it("user can not join the room with an HTTP request - get a 404", async () => {
        const res = await chai.request(CloudApiServer)
            .post("/join_room")
            .set("Authorization", `Bearer ${apiKey}`)
            .set("x-access-token", testUser2.accessToken)
            .send({ roomId, version: VERSION });
        res.should.have.status(400);
    });

    after(async() => {
        await QueueTestProxy.stopTestQueue();
        
        const env = process.env;
        delete env["NODE_ENV"];
        process.env = env;
    });
});
