var express = require("express");
var cookieParser = require("cookie-parser");
var path = require("path");
var errorHandler = require("errorhandler");
var app = express();
var cors = require("cors");

var config = require("./config")


const corsWhitelist = [ "http://minis.walamana.de",
                        "https://minis.walamana.de",
                        "https://minis.walmana.de/beta",
                        "https://minis.walamana.de/beta/",
                        "https://www.minis.walamana.de",
                        "minis.walamana.de",
                        "walamana.de",
                        "https://walamana.de",
                        "localhost:80",
                        "http://localhost:80",
                        "http://localhost:4200",
                        undefined] // FIXME: REMOVE THIS AFTER DEBUGGING!


var bodyParser = require('body-parser')
app.use( bodyParser.json() );       // to support JSON-encoded bodies
app.use(cors({
    origin: function (origin, callback) {
        if (corsWhitelist.indexOf(origin) !== -1) {
          callback(null, true)
        } else {
          callback(new Error(origin + ": " + 'Not allowed by CORS'))
        }
      }
}))
app.use(cookieParser());
app.use(express.static(path.join(process.cwd(), "StaticPages")));
app.use(errorHandler({ dumpExceptions: true, showStack: true }));

var uuid = require("uuid/v4");
var mysql = require("mysql");
var fs = require("fs");
var cause;

var con = mysql.createConnection(config.database);

con.connect(err => {
    if (err) {
        console.log("Cant connect to MySQL database");
        console.log(err);
        cause = err;
    }
    console.log("Connected to database!");
});

// Global headers

app.all('/*',function(req,res,next){
    res.header('Access-Control-Allow-Credentials' , true );
    next();
});


app.get('/', (req, res) => {
    console.log(con);
    res.send("Welcome to the miniplan api!: " + cause);
});

app.get('/login', (req, res) => {
    var id = req.query.id;
    var password = req.query.password;
    
    if(id == undefined || password == undefined){
        res.send({success: false, error: "Missing parameters"});
        return;
    }

    id = id.toLowerCase();

    con.query("SELECT PASSWORT, USERNAME FROM ministranten WHERE (USERNAME='" + id + "' OR EMAIL='" + id + "')", (err, result) => {
        if (err) throw err;
        if(password == result[0]["PASSWORT"]){
            var usertoken = uuid();
            res.cookie("loginToken", usertoken);
            res.cookie("user", result[0]["USERNAME"]);
            con.query("UPDATE `ministranten` SET `USER_TOKEN` = '" + usertoken + "' WHERE `ministranten`.`USERNAME` = '" + result[0]["USERNAME"] + "';");
            res.send({success: true, token: usertoken});
        }else{
            res.send({success: false});
        }
    });
});

app.post("/logout", (req, res) => {
    var token = req.body.credentials.token;
    var user = req.body.credentials.username;

    tokenIsValid(user, token).then(valid => {
        if(valid){
            con.query("UPDATE `ministranten` SET `USER_TOKEN` = '' WHERE `ministranten`.`USERNAME` = '" + user + "';");
            res.cookie("loginToken", "");
            res.cookie("user", "");
            res.send({success: true});
        }else{
            res.send({success: false});
        }
    });


});

app.post("/loggedIn", (req, res) => {
    var token = req.body.credentials.token;
    var user = req.body.credentials.username;

    tokenIsValid(user, token).then(valid => {
        if(valid){
            res.send({success: true, loggedIn: true, user: user});
        }else{
            res.send({success: true, loggedIn: false, user: user});
        }
    })

});

/**
 * 
 * 
 *                              WIP
 * 
 * 
 * 
 */

app.post("/:user/update", (req, res) => {
    var token = req.body.credentials.token;
    var userI = req.body.credentials.username;
    var user = req.params.user;
    var changes = JSON.parse(req.query.changes);


    tokenIsValid(userI, token).then(valid => {
        if(valid){
            if(userI != "admin" && userI != user){
                res.send({success: false, error: "Unauthorized"});
                return;
            }
            
            console.log("Changing for " + user + " as " + userI + " following states: ");
            console.log(changes);
            for(var i = 0; i < Object.keys(changes).length; i++){
                var gdID = Object.keys(changes)[i];
                var anwesenheit = changes[Object.keys(changes)[i]];
                con.query("INSERT INTO `anwesenheit` (USERNAME, gottesdienst_ID, ANWESENHEIT) VALUES('" + user + "', " + gdID + ", " + anwesenheit + ") ON DUPLICATE KEY UPDATE USERNAME='" + user + "', gottesdienst_ID=" + gdID + ", ANWESENHEIT=" + anwesenheit + "")
            }
        
            res.send({success: true});
        }else{
            console.log("Unauthorized not valid");
            res.send({success: false, error: "Unauthorized"});
        }
    });

});

app.post("/gd/:id/update", (req, res) => {
    var token = req.body.credentials.token;
    var user = req.body.credentials.username;
    var id = req.params.id;
    var fixed = req.query.fixed == "true";

    validateAdmin(user, token).then(valid => {
        if(valid){
            con.query("UPDATE `gottesdienst` SET `FESTGESETZT` = " + (fixed ? 1 : 0) + " WHERE `gottesdienst`.`ID` = " + id + ";", (err, res1) => {
                console.log("SUCCESSFUL", id, fixed, "UPDATE `gottesdienst` SET `FESTGESETZT` = " + (fixed ? 1 : 0) + " WHERE `gottesdienst`.`ID` = " + id + ";");
                res.send({success: true});
            })
        }else{
            console.log("Unauthorized not valid");
            res.send({success: false, error: "Unauthorized"});
        }
    });
})


app.get("/gottesdienste", (req, res) => {
    var groupid = req.params.groupid;
    con.query("SELECT ID from gruppe ORDER BY ID DESC LIMIT 1", (err, result) => {
        if (err) throw err;
        if(result.length <= 0){
            res.send("null");
            return;
        }
        con.query("SELECT * from gottesdienst WHERE gruppe_ID='" + result[0]["ID"] + "' ORDER BY `gottesdienst`.`DATUM` ASC LIMIT 0 , 30 ", (err, result) => {
            if (err) throw err;
            res.send(JSON.stringify(result));
        });
    });
});

app.get("/gottesdienst/:id/ministranten", (req, res) => {
    var gdID = req.params.id;
    console.log(gdID)

    con.query("SELECT `anwesenheit`.`USERNAME` FROM `anwesenheit` WHERE `anwesenheit`.`gottesdienst_ID` = " + gdID, (err, result) => {
        if (err) throw err;
        res.send(JSON.stringify(result))
    });
});

app.get("/gottesdienste/:groupid", (req, res) => {
    var groupid = req.params.groupid;
    con.query("SELECT * from gottesdienst WHERE gruppe_ID='" + groupid + "' ORDER BY  `gottesdienst`.`DATUM` ASC LIMIT 0 , 30", (err, result) => {
        if (err) throw err;
        res.send(JSON.stringify(result));
    });
});

app.get("/groups", (req, res) => {
    con.query("SELECT * from gruppe ORDER BY  `gruppe`.`ID` DESC  LIMIT 0, 5", (err, result) => {
        if (err) throw err;
        res.send(JSON.stringify(result));
    });
});

app.post("/ministranten", (req, res) =>{
    var token = req.body.credentials.token;
    var user = req.body.credentials.username;
    tokenIsValid(user, token).then(valid => {
        con.query("SELECT * FROM `gruppe` ORDER BY `gruppe`.`START` DESC", (err, groupResults) => {
            var groupID = req.query.group;
            if(groupID == -1){
                groupID = groupResults[0]["ID"];
            }else{
                var valid = false;
                for(let id of groupResults){
                    if(id.ID == groupID){
                        valid = true;
                    }
                }
                if(!valid){
                    res.send("{error: 'Invalid group id'}");
                }
            }
            con.query("SELECT `ministranten`.`USERNAME`, `ministranten`.`VORNAME`, `ministranten`.`NACHNAME`, `anwesenheit`.`ANWESENHEIT`, `anwesenheit`.`gottesdienst_ID` FROM `ministranten` LEFT JOIN `anwesenheit` ON `anwesenheit`.`USERNAME` = `ministranten`.`USERNAME`, `gottesdienst` WHERE `gottesdienst`.`ID` = `anwesenheit`.`gottesdienst_ID` AND `gottesdienst`.`gruppe_ID` = " + groupID + " ORDER BY `ministranten`.`NACHNAME`, `ministranten`.`VORNAME`, `anwesenheit`.`gottesdienst_ID`", (err, results) => {

                con.query("SELECT `ministranten`.`USERNAME`, `ministranten`.`VORNAME`, `ministranten`.`NACHNAME` FROM `ministranten` ORDER BY `ministranten`.`NACHNAME`, `ministranten`.`VORNAME`", (err, allMinis) => {
                    
                    if (err) throw err;
                    var minis = [];
                    
                    for(var i = 0; i < allMinis.length; i++){
                        
                        var result = allMinis[i];
                        if(result["USERNAME"] == "admin"){
                            continue;
                        }
                        minis.push({
                            firstname: result["VORNAME"],
                            lastname: valid ? result["NACHNAME"] : result["NACHNAME"].substring(0, 1) + ".",
                            username: result["USERNAME"],
                            registered: {}
                        })


                        // if(result["USERNAME"].includes(curMini.username))
                        //     curMini.registered[result["gottesdienst_ID"]] =  result["ANWESENHEIT"];
                    }

                    var curMini = null;
                    for(let result of results){
                        if(!curMini || curMini.username != result["USERNAME"]){
                            var skip = false;
                            for(let mini of minis){
                                if(skip) continue;
                                if(result["USERNAME"] == mini.username){
                                    curMini = mini;
                                    skip = true;
                                }
                            }
                        }

                        curMini.registered[result["gottesdienst_ID"]] =  result["ANWESENHEIT"];
                    }
                
                    res.send(JSON.stringify(minis));

                })
            });
        });
        
    })
        
});

app.post("/add/group", (req, res) => {

    validateAdmin(req.body.credentials.username, req.body.credentials.token).then(success => {
        if(success){
            var start = req.body.start;
            var end = req.body.end;
        
            con.query("INSERT INTO `gruppe` (`ID`, `START`, `END`) VALUES (NULL, '" + start + "', '"  + end  + "');", (err, result) => {
                if (err) throw err;
                con.query("SELECT ID FROM `gruppe`", (err2, result2) => {
                    res.send(JSON.stringify({id: result2[result2.length - 1].ID}));
                });
            })
        }else{
            res.send(JSON.stringify({err: "Not enough permissions"}));
        }
    });

    
    // con.query("SELECT * from gruppe ORDER BY  `gruppe`.`ID` DESC  LIMIT 0, 5", (err, result) => {
    // });
});

app.post("/add/gottesdienst", (req, res) => {


    console.log(JSON.stringify(req.body));
    validateAdmin(req.body.credentials.username, req.body.credentials.token).then(success => {
        if(success){
            var name = req.body.data.name != undefined ? '"' + req.body.data.name + '"' : "NULL";
            var date = req.body.data.date != undefined ? req.body.data.date : "NULL";
            var time = req.body.data.time != undefined ? req.body.data.time : "NULL";
            var presence = req.body.data.presence != undefined ? '"' + req.body.data.presence + '"' : "NULL";
            var location = req.body.data.location != undefined ? '"' + req.body.data.location + '"' : "NULL";
            var trial = req.body.data.trial != undefined ? '"' + req.body.data.trial + '"' : "NULL";
            var group = req.body.data.group != undefined ? req.body.data.group : -1;

            var finalDate = '"' + date + " " + time + '"';
        
            con.query("INSERT INTO `gottesdienst` (`ID`, `NAME`, `DATUM`, `ANWESENHEIT`, `PROBE`, `ORT`, `gruppe_ID`, `FESTGESETZT`) VALUES (NULL, " + name + ", " + finalDate + ", " + presence + ", " + trial + ", " + location + ", " + group + ", '0');", (err, result) => {
                if (err) throw err;
                con.query("SELECT ID FROM `gottesdienst`", (err2, result2) => {
                    res.send(JSON.stringify({id: result2[result2.length - 1].ID}));
                });
            })
        }else{
            res.send(JSON.stringify({err: "Not enough permissions"}));
        }
    });
    // con.query("SELECT * from gruppe ORDER BY  `gruppe`.`ID` DESC  LIMIT 0, 5", (err, result) => {
    // });
});

app.post("/remove/gottesdienst", (req, res) => {
    validateAdmin(req.body.credentials.username, req.body.credentials.token).then(success => {
        if(success){
            var id = req.body.id;

            con.query("DELETE FROM `gottesdienst` WHERE `ID` = '" + id + "'", (err, result) => {
                if(err){
                    res.send(JSON.stringify({success: false}));
                    return;
                }
                res.send(JSON.stringify({success: true}));
            });
        }else{
            res.send(JSON.stringify({err: "Not enough permissions"}));
        }
    })
})


var attachToMini = function(mini, pos, then){
    mini.registered = [];
    con.query("SELECT * FROM `" + mini.Name.toLowerCase() + "` ORDER BY  `" + mini.Name.toLowerCase() + "`.`GottesdienstIDs` DESC LIMIT 0 , 30", (err, data) => {
        if(data == null){
            then(mini, pos);
        }
        for(var j = 0; j < data.length; j++){
            
            mini.registered[j] = {
                id: data[j]["GottesdienstIDs"],
                value: data[j]["Anwesend"]
            };
        }
        then(mini, pos);
    });
}


app.listen(config.port);
console.log("Starting api-server on " + config.port);



function tokenIsValid(username, token){
    return new Promise((resolve, reject) => {
        con.query("SELECT USER_TOKEN FROM ministranten WHERE USERNAME='" + username + "'", (err, result) => {
            if (err) {
                reject(err);
                return;
            };

            if(result.length == 0){
                resolve(false);
                return;
            }
    
            if(result[0]["USER_TOKEN"] != "" && result[0]["USER_TOKEN"] == token){
                resolve(true);
            }else{
                resolve(false);
            }
        });
    })
}

function validateAdmin(username, token){
    return new Promise((resolve, reject) => {
        if(username == "admin"){
            tokenIsValid(username, token).then(success => {
                console.log(success)
                resolve(success);
            });
        }else{
            console.log("wrong username")
            resolve(false);
        }
    });
}


function removeFromArrayByValue(value, array) {
    var index = array.indexOf(value);
    if(index > -1){
        array.splice(index, 1);
    }
}

function removeFromArray(index, array) {
    var index = array.indexOf(value);
    if(index > -1){
        array.splice(index, 1);
    }
}