import multer from "multer";
import SessionService from "../application/SessionService";
import ActionInteraction from "../domain/ActionInteraction";
import AnswerInteraction from "../domain/AnswerInteraction";
import CommentInteraction from "../domain/CommentInteraction";
import { Express } from "express";
import * as winston from "winston";

const ERROR_STATUS: number = 500;
const SUCCESS_STATUS: number = 200;

export default function attachRoutes(app : Express, sessionService: SessionService, logger: winston.Logger): void {

    app.get("/session/ping", (req, res) => {
        logger.info("routeREST:ping");
        res.send("alive");
    });

    app.post("/session/create", (req, res) => {
        logger.info("routeREST:create");
        const {webSiteId, baseURL} = req.body;
        sessionService.createNewSessionForWebSiteId(webSiteId, baseURL)
        .then((sessionId) => {
            res.json(sessionId);
        })
        .catch((e) => {
            console.log(e);
            res.status(ERROR_STATUS).send(e);
        });
    });

    app.get("/session/:sessionId", (req, res) => {
        logger.info("routeREST:sessionId");
        const {sessionId} = req.params;
        sessionService.mountSession(sessionId)
        .then((session) => {
            if (session) {
                logger.info("routeREST:sessionId sending JSON result");
                res.json({
                    id: session.id,
                    baseURL: session.baseURL,
                    webSite: session.webSite,
                    createdAt: session.createdAt,
                    updatedAt: session.updatedAt,
                    explorationList: session.explorationList.map((exploration) => {
                        return {
                            testerName: exploration.tester.name,
                            startDate: exploration.startDate,
                            stopDate: exploration.stopDate,
                            interactionList: exploration.interactionList.map((interaction) => {
                                if (interaction instanceof ActionInteraction) {
                                    return {
                                        concreteType: "Action",
                                        index: interaction.index,
                                        kind: interaction.action.kind,
                                        value: interaction.action.value,
                                        date: interaction.date
                                    };
                                }
                                if (interaction instanceof CommentInteraction) {
                                    return {
                                        concreteType: "Comment",
                                        index: interaction.index,
                                        kind: interaction.comment.kind,
                                        value: interaction.comment.value,
                                        date: interaction.date
                                    };
                                }
                                if (interaction instanceof AnswerInteraction) {
                                    return {
                                        concreteType: "Answer",
                                        index: interaction.index,
                                        kind: interaction.answer.kind,
                                        value: interaction.answer.value,
                                        date: interaction.date
                                    };
                                }
                            }),
                        };
                    }),
                });
            } else {
                logger.error(`routeREST:sessionId error, no session ${req.params}`);
                res.status(ERROR_STATUS).send("error");
            }
        })
        .catch( (e) => {
            logger.error(`routeREST:sessionId error:${e}`);
            res.status(ERROR_STATUS).send("error");
        });
    });

    app.post("/session/:sessionId/exploration/start",  (req, res) => {
        logger.info("routeREST:exploration/start");
        const {sessionId} = req.params;
        const testerName: string = req.body.testerName;
        sessionService.startExploration(sessionId, testerName)
            .then((explorationNumber) => {
                res.json(explorationNumber);
            })
            .catch( (e) => {
                logger.error(`routeREST:exploration/start error ${e}`);
                res.status(ERROR_STATUS).send("error");
            });
    });

    app.post("/session/:sessionId/exploration/:explorationNumber/stop",  (req, res) => {
        logger.info("routeREST:exploration/stop");
        const {sessionId, explorationNumber} = req.params;
        const explorationNumberAsNumber = parseInt(explorationNumber);
        if (isNaN(explorationNumberAsNumber)) {
            logger.error(`routeREST:exploration/stop ${explorationNumberAsNumber} is NaN`);
            res.status(ERROR_STATUS).send("error");
        } else {
            sessionService.stopExploration(sessionId, explorationNumberAsNumber)
            .then((exploNumber) => {
                logger.info(`routeREST:exploration/stop send ${exploNumber} in JSON `);
                res.json(exploNumber);
            })
            .catch( (e) => {
                logger.error(`routeREST:exploration/stop error ${e}`);
                res.status(ERROR_STATUS).send("error");
            });
        }
    });

    app.post("/session/:sessionId/exploration/add",  (req, res) => {
        logger.info(`routeREST:exploration/add`);
        const {sessionId} = req.params;
        const {testerName, interactionList, startDate, stopDate} = req.body;
        //console.log("startDate:", startDate);
        //console.log("stopDate:", stopDate);
        sessionService.addExploration(sessionId, testerName, interactionList, startDate, stopDate)
        .then((explorationNumber) => {
            logger.info(`routeREST:exploration/add send ${explorationNumber} in JSON`);
            res.json(explorationNumber);
        })
        .catch( (e) => {
            logger.error(`routeREST:exploration/add error ${e}`);
            res.status(ERROR_STATUS).send("error");
        });
    });


    app.post("/session/addscreenshotlist",  (req, res) => {
        logger.info(`routeREST:addScreenshotlist`);
        const {screenshotList} = req.body;
        // console.log('receive comments : ', screenshotList.length);

        const addPromise = screenshotList.map( (screenshot : any) => sessionService.addScreenshot(screenshot.sessionId, screenshot.explorationNumber, screenshot.interactionIndex, screenshot.image));

        Promise.all(addPromise)
            .then(() => {
                // console.log('screenshot stored');
                logger.info(`routeREST:addScreenshotlist send ${{nbsaved: screenshotList.length}} in JSON`);
                res.status(SUCCESS_STATUS).json({nbsaved: screenshotList.length});
            })
            .catch( (e) => {
                logger.error(`routeREST:addScreenshotlist error ${e}`);
                res.status(ERROR_STATUS).send(e);
            });
    });

    app.post("/session/addvideo/:sessionId/:explorationNumber", multer().single("video"), (req, res) => {
        logger.info(`routeREST:sessionId/explorationNumber`);
        const {sessionId, explorationNumber} = req.params;
        const video: Express.Multer.File = req.file;
        const fileBuffer: Buffer = video.buffer;
        // console.log('receive comments : ', screenshotList.length);
        // console.log("sessionId:", sessionId);
        // console.log("explorationNumber:", explorationNumber);
        // console.log("video:", video);

        const explorationNumberAsNumber = parseInt(explorationNumber);
        if (isNaN(explorationNumberAsNumber)) {
            logger.error(`routeREST:sessionId/explorationNumber error ${explorationNumber} is NaN`);
            res.status(ERROR_STATUS).send("wrong exploration number");
        } else {
            sessionService.addVideo(sessionId, explorationNumberAsNumber, fileBuffer )
            .then( () => {
                logger.info(`routeREST:sessionId/explorationNumber send result`);
                res.status(SUCCESS_STATUS).json({});
            })
            .catch( (e) => {
                logger.error(`routeREST:sessionId/explorationNumber ${e}`);
                res.status(ERROR_STATUS).send(e);
            });

        }

        
    });

    app.get("/session/:sessionId/screenshotlist", (req, res) => {
        logger.info(`routeREST:sessionId/screenshotlist`);
        const {sessionId} = req.params;

        sessionService.findScreenshotBySession(sessionId)
            .then( (screenshotList) => {
                // console.log('get list', screenshotList);
                logger.info(`routeREST:sessionId/screenshotlist send ${screenshotList} in JSON`);
                res.status(SUCCESS_STATUS).json({screenshotList});
            })
            .catch( (e) => {
                logger.error(`routeREST:sessionId/screenshotlist ${e}`);
                res.status(ERROR_STATUS).send(e);
            });
    });

    app.get("/session/:sessionId/videolist", (req, res) => {
        logger.info(`routeREST:sessionId/videolist`);
        const {sessionId} = req.params;

        sessionService.findVideoBySession(sessionId)
            .then( (videoList) => {
                logger.info(`routeREST:sessionId/screenshotlist send ${videoList} in JSON`);
                res.status(SUCCESS_STATUS).json({videoList});
            })
            .catch( (e) => {
                logger.error(`routeREST:sessionId/screenshotlist ${e}`);
                res.status(ERROR_STATUS).send(e);
            });
    });

}
