const fetch = require('node-fetch');
const config = require('../config');
const { token2WebSite } = require('../tokenUtilities');
const addWebSite = require('../tokenUtilities').addWebSite;
const removeWebSite = require('../tokenUtilities').removeWebSite;
const requestWebSiteFromToken = require('../tokenUtilities').requestWebSiteFromToken;

module.exports = function attachRoutes(app, config) {

    app.get('/dashboard/website/start', (req, res) => {
        res.render('website/start.ejs', {account:req.session});
    });

    app.get('/dashboard/website/create', (req, res) => {
        let firstWebSite = token2WebSite(req.session.jwt).length == 0;
        res.render('website/create.ejs', {
            account:req.session,
            webSite: undefined,
            errorMessage: null,
            firstWebSite
        });
    });

    app.post('/dashboard/website/create', (req, res) => {
        let {name, url, mappingList, stepList} = req.body;

        let evaluationStepList;
        console.log(req.body)

        if (stepList) {
            evaluationStepList = JSON.parse(stepList)
                .filter(step => step.value.length > 0)
                .map(step => {
                    const expression = step.value.replace(/  +/g, ' ').trim()
                    return {
                        name: step.name,
                        expression
                    }
                })
        }
        let webSite = {
            name,
            url,
            mappingList
        }
        let renderOption = {
            account: req.session,
            webSite: { 
                id: webSite.id,
                name: webSite.name, 
                url, 
                mappingList: webSite.mappingList
            },
            successMessage: undefined,
            errorMessage: undefined,
            firstWebSite: false
        }
        try  {
            webSite.mappingList = JSON.parse(mappingList);
        } catch(e) {
            console.error('cannot parse:',e);
            renderOption.errorMessage = e.message;
            res.render('website/create.ejs', renderOption);
            return;
        }

        renderOption.errorMessage = checkMappingRuleList(webSite.mappingList);
        if (renderOption.errorMessage !== undefined) {
            res.render('website/create.ejs', renderOption);
            return;
        }

        const webSiteCreateURL = 'http://' + config.website.host + ':' + config.website.port + '/website/create';
        let optionWebSiteCreate = {
            method: 'POST',
            body:    JSON.stringify(webSite),
            headers: { 'Content-Type': 'application/json' },
        }
        fetch(webSiteCreateURL, optionWebSiteCreate)
            .then(response => {
                if (response.ok) {
                    return response.json()
                } else {
                    throw response.statusText
                }
            })
            .then(webSiteId => {
                renderOption.webSite.id = webSiteId;
                return addWebSite(req.session.jwt , webSiteId)
            })
            .then(token => {
                req.session.jwt = token.jwt;
                renderOption.successMessage = "WebSite has been created";
            })
            .then(() => {
                return createEvaluator(renderOption.webSite.id, evaluationStepList)
            })
            .then(() => res.render('website/update.ejs',renderOption)
            )
            .catch((error) => {
                console.error(error);
                renderOption.errorMessage = 'Creation Failed';
                res.render('website/create.ejs', renderOption);
            })
    })

    app.post('/dashboard/website/update', (req, res) => {
        let {id, name, url, mappingList} = req.body;

        let webSite = {
            id,
            name,
            url,
            mappingList
        }
        let renderOption = {
            account: req.session,
            webSite: {
                id,
                name, 
                url, 
                mappingList
            },
            successMessage: undefined,
            errorMessage: undefined
        }
        try  {
            webSite.mappingList = JSON.parse(mappingList);
        } catch(e) {
            console.error('cannot parse:',e);
            renderOption.errorMessage = e.message;
            res.render('website/update.ejs', renderOption);
            return;
        }

        renderOption.errorMessage = checkMappingRuleList(webSite.mappingList);
        if (renderOption.errorMessage !== undefined) {
            console.error('cannot check:',e);
            res.render('website/update.ejs', renderOption);
            return;
        }

        const webSiteUpdateURL = 'http://' + config.website.host + ':' + config.website.port + '/website/update';
        let optionWebSiteCreate = {
            method: 'POST',
            body:    JSON.stringify(webSite),
            headers: { 'Content-Type': 'application/json' },
        }
        fetch(webSiteUpdateURL, optionWebSiteCreate)
            .then(response => {
                if (response.ok) {
                    renderOption.successMessage = 'WebSite has been saved';
                    res.render('website/update.ejs', renderOption);
                } else {
                    renderOption.errorMessage = response.statusText;
                    res.render('website/update.ejs', renderOption);
                }
            })
            .catch( error => {
                console.error(error);
                renderOption.errorMessage = "update failed.";
                res.render('website/update.ejs', renderOption);
            })
    });

    app.get('/dashboard/website/update/:webSiteId', (req, res) => {
        const {webSiteId} = req.params;
        requestWebSiteFromToken(req.session.jwt).then(webSiteList => {

            let webSiteData = webSiteList.find(webSite => webSite.id === webSiteId);
            if (webSiteData) {
                webSite = { 
                    id: webSiteData.id,
                    url: webSiteData.url,
                    name: webSiteData.name, 
                    mappingList: webSiteData.mappingList
                }
                res.render('website/update.ejs', {account:req.session, webSite, errorMessage: undefined, successMessage: undefined});
            } else {
                res.render('error.ejs', {account:req.session, message: "Update "+webSiteId+" forbidden", error:undefined })
            }
        })
    });

    app.get('/dashboard/website/remove/:webSiteId', (req, res) => {
        const {webSiteId} = req.params;
        removeWebSite(req.session.jwt , webSiteId)
            .then(token => {
                req.session.jwt = token.jwt;
                res.redirect('/account/account');
            })
    });

    app.get('/dashboard/website/:name', (req, res) => {
        const {name} = req.params;
        const webSiteURL = 'http://' + config.website.host + ':' + config.website.port + '/website/'+name;
        fetch(webSiteURL)
            .then(response => {
                if (!response.ok) {
                    throw new Error('website cannot be created', response.message);
                }
                return response.json();
            })
            .then( webSite => {
                res.status(200).send(webSite);
            })
    });
}

function checkMappingRuleList(mappingRuleList) {
    for (let index = 0; index < mappingRuleList.length; index++) {
        let mappingRule = mappingRuleList[index];
   
        if (!mappingRule.hasOwnProperty('match')) {
            return `No match part found for rule number ${index+1}`;
            
        }
        if (!mappingRule.match.hasOwnProperty('css') && !mappingRule.match.hasOwnProperty('xpath')) {
            return `No selector part found for rule number ${index+1}`;
            
        }
        if (!mappingRule.match.hasOwnProperty('event')) {
            return `No event part found for rule number ${index+1}`;
            
        }
        if (!mappingRule.hasOwnProperty('output')) {
            return `No output part found for rule number ${index+1}`;
            
        }
        if (!mappingRule.output.hasOwnProperty('prefix')) {
            return `No prefix part found for rule number ${index+1}`;
        }
    }
}

function createEvaluator(webSiteId, stepList) {
    console.log("createEvaluator", stepList)

    if (!stepList || stepList.length === 0) {
        return Promise.resolve();
    } else {
        const URL = 'http://' + config.evaluator.host + ':' + config.evaluator.port + '/evaluator/create'
        console.log(stepList);
        return fetch(URL, {
            method: 'POST',
            body: JSON.stringify({
                webSiteId,
                name: `Mandatory steps`,
                stepList
            }),
            headers: { 'Content-Type': 'application/json' },
        })
    }
}
