import Mapping from "../domain/Mapping";
import WebSite from "../domain/WebSite";
import WebSiteService from "../application/WebSiteService";
import IdGeneratorService from "../_infra/IdGeneratorServiceWithShortId";
import { Request, Express, Response } from "express";

const INVALID_PARAMETERS_STATUS = 400;
const INTERNAL_SERVER_ERROR_STATUS = 500;
const CONFLICT_STATUS_CODE = 409;

export default function attachRoutes(app : Express, webSiteService: WebSiteService, idGeneratorService : IdGeneratorService): void {

    app.get("/website/ping", (req:Request, res: Response) => {
        res.send('alive');
    });

    app.get("/website/:id", (req, res) => {
        const id = req.params.id;
        // console.log("WebSite GET: ",id);
        if (id === undefined) {
            res.status(INVALID_PARAMETERS_STATUS).send("id is undefined");
            return;
        }
        else {
            webSiteService.findWebSiteById(id)
                .then(webSite => {
                    if (!(webSite instanceof WebSite)) {
                        res.status(INTERNAL_SERVER_ERROR_STATUS).send("wrong type, not a webSite");
                    }
                    res.json({
                        id: webSite.id,
                        name: webSite.name,
                        url: webSite.url,
                        mappingList: webSite.mappingList
                    });
                })
                .catch((e) => {
                    // tslint:disable-next-line: no-console
                    console.error(e);
                    res.status(INTERNAL_SERVER_ERROR_STATUS).send(e);
                });
        }
    });

    app.post("/website/create",  (req: Request, res: Response) => {
        const {name, url} = req.body;
        const mappingListData : {
            match: {
                event: string,
                css?: string | undefined,
                xpath?: string | undefined,
                code?: string | undefined,
                key?: string | undefined,
            },
            output: {
                prefix: string,
                suffix?: string
            },
            context?: {
                url?: string,
                css?: string,
                xpath?: string
            },
            description?: string
        }[] = req.body.mappingList;
        const mappingList: Mapping[] = [];
        try {
            mappingListData.forEach((mappingData) => {
                mappingList.push(new Mapping(mappingData.match, mappingData.output, mappingData.context, mappingData.description));
            });
        } catch (e) {
            console.error(e);
            return res.status(INVALID_PARAMETERS_STATUS).send({message: e.message});
        }
        const webSite = new WebSite(idGeneratorService, name, url);
        webSite.addMappingList(mappingList);
        webSiteService.createWebSite(webSite)
            .then(webSiteId => {
                    res.json(webSiteId);
                })
            .catch ((e) => {
                console.error(e);
                res.status(CONFLICT_STATUS_CODE).send({message: e.message});
            });
     });

    app.post("/website/update",  (req: Request, res: Response) => {
        const {id, name, url} = req.body;
        const mappingListData : {
            match: {
                event: string,
                css?: string | undefined,
                xpath?: string | undefined,
                code?: string | undefined,
                key?: string | undefined,
            },
            output: {
                prefix: string,
                suffix?: string
            },
            context?: {
                url?: string,
                css?: string,
                xpath?: string
            },
            description?: string
        }[] = req.body.mappingList;
        const mappingList: Mapping[] = [];
        try {
            mappingListData.forEach((mappingData) => {
                mappingList.push(new Mapping(mappingData.match, mappingData.output, mappingData.context, mappingData.description));
            });
        } catch (e) {
            return res.status(INVALID_PARAMETERS_STATUS).send({message: "Invalid mapping file"});
        }
        try {
            const webSite = new WebSite(idGeneratorService, name, url, id);
            webSite.addMappingList(mappingList);
            // console.log('website update:', webSite);
            webSiteService.updateWebSite(webSite)
                .then((webSiteId) => {
                    res.json(webSiteId);
                });
        } catch (e) {
            res.status(CONFLICT_STATUS_CODE).send({message: e.message});
        }
    });
}
