"use strict";

const config = require('config');

const redis = require('../helpers/redis');
const express = require('express');
const crypto = require('crypto');
const router = express.Router();
const mailer = require('../helpers/mailer');
const _ = require('underscore');

const fs = require('fs')
const SamlStrategy = require('passport-saml').Strategy
const passport = require('passport')
const Saml2js = require('saml2js');

const db = require('../models/db');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const uuidv4 = require('uuid/v4');


// =========== PASSPORT =======
  passport.serializeUser(function (user, done) {
    done(null, user);
  });

  passport.deserializeUser(function (user, done) {
    done(null, user);
  });

  var samlStrategy = new SamlStrategy({
      // URL that goes from the Identity Provider -> Service Provider
      callbackUrl: config.path,

      entryPoint: config.entryPoint,
      issuer: config.issuer,
      identifierFormat: null,

      validateInResponseTo: false,
      disableRequestedAuthnContext: true
  },
  function (profile, done) {
    return done(null, {
      id: profile.nameID,
      idFormat: profile.nameIDFormat,
      email: profile.email,
      firstName: profile.givenName,
      lastName: profile.sn
    });
  });

  passport.use(samlStrategy);

 // to generate Service Provider's XML metadata
  router.get('/saml/metadata',
    function(req, res) {
      res.type('application/xml');
      var spMetadata = samlStrategy.generateServiceProviderMetadata(fs.readFileSync('/cert/certificate.pem', 'utf8'));
      res.status(200).send(spMetadata);
    }
  );

router.post('/saml/SSO', passport.authenticate('saml', { failureRedirect: '/login', failureFlash: true}), function(req, res){
    const xmlResponse = req.body.SAMLResponse;
    const parser = new Saml2js(xmlResponse);
    const response = parser.toObject();
    const email = response["mail"];
    console.log(parser.toJSON());
    console.log("Nickname "+ response["givenName"])
    const nickname = response["givenName"];
    //check, if user exists, if not create.
    db.User.findAll({where: {email: email}})
        .then(users => {
          if (users.length == 0) {
            crypto.randomBytes(16, function(ex, buf) {
                var token = buf.toString('hex');

                var u = {
                    _id: uuidv4(),
                    email: email,
                    account_type: "email",
                    nickname: nickname,
                    password_hash: "00000",
                    prefs_language: req.i18n.locale,
                    confirmation_token: token
                };

                db.User.create(u)
                    .error(err => {
                        res.sendStatus(400);
                    })
                    .then(u => {
                        var homeFolder = {
                            _id: uuidv4(),
                            name: req.i18n.__("home"),
                            space_type: "folder",
                            creator_id: u._id
                          };
                          db.Space.create(homeFolder)
                            .error(err => {
                              res.sendStatus(400);
                            })
                            .then(homeFolder => {
                              u.home_folder_id = homeFolder._id;
                              u.save()
                                .then(() => {
                                  // home folder created,
                                  // auto accept pending invites
                                  db.Membership.update({
                                    "state": "active"
                                  }, {
                                    where: {
                                      "email_invited": u.email,
                                      "state": "pending"
                                    }
                                  });
                                  res.status(201).json({});
                                })
                                .error(err => {
                                  res.status(400).json(err);
                                });
                            })
                    });
            });
          }
        }).then(user =>{
         db.User.findOne({where: {email: email}})
                .error(err => {
                  res.sendStatus(404);
                })
                .then(user => {
                    crypto.randomBytes(48, function(ex, buf) {
                                  var token = buf.toString('hex');

                                  var session = {
                                    user_id: user._id,
                                    token: token,
                                    ip: req.ip,
                                    device: "web",
                                    created_at: new Date(),
                                    url : "/"
                                  };

                                  db.Session.create(session)
                                    .error(err => {
                                      console.error("Error creating Session:",err);
                                      res.redirect(500, "/");
                                    })
                                    .then(() => {
                                      var domain = (process.env.NODE_ENV == "production") ? new URL(config.get('endpoint')).hostname : req.headers.hostname;
                                      console.log("session set successfully");
                                      res.cookie('sdsession', token, { domain: domain, httpOnly: true });
                                      res.redirect(302, "/")
                                    });
                        });
                });
         });
});

router.get('/', (req, res) => {
  res.render('index', { config:config, user:req.user });
});

router.get('/ping', (req, res) => {
  res.status(200).json({"status": "ok"})
});

router.get('/spaces', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/not_found', (req, res) => {
  res.render('not_found', {});
});

router.get('/confirm/:token', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/folders/:id', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/signup', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/accept/:id', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/password-reset', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/password-confirm/:token', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/de/*', (req, res) => {
  res.redirect("/t/de");
});

router.get('/de', (req, res) => {
  res.redirect("/t/de");
});

router.get('/fr/*', (req, res) => {
  res.redirect("/t/fr");
});

router.get('/fr', (req, res) => {
  res.redirect("/t/fr");
});

router.get('/oc/*', (req, res) => {
  res.redirect("/t/oc");
});

router.get('/oc', (req, res) => {
  res.redirect("/t/oc");
});

router.get('/en/*', (req, res) => {
  res.redirect("/t/en");
});

router.get('/en', (req, res) => {
  res.redirect("/t/end");
});

router.get('/account', (req, res) => {
  res.render('spacedeck');
});

router.get('/login', passport.authenticate('saml',
                           {
                             successRedirect: '/',
                             failureRedirect: '/login'
                           })
);


//  res.render('spacedeck', { config:config, user:req.user });
//});

router.get('/logout', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

router.get('/t/:id', (req, res) => {
  res.cookie('spacedeck_locale', req.params.id, { maxAge: 900000, httpOnly: true });
  var path = "/";
  if (req.query.r=="login" || req.query.r=="signup") {
    path = "/"+req.query.r;
  }
  res.redirect(path);
});

router.get('/s/:hash', (req, res) => {
  var hash = req.params.hash;
  if (hash.split("-").length > 0) {
    hash = hash.split("-")[0];
  }

  db.Space.findOne({where: {"edit_hash": hash}}).then(function (space) {
    if (space) {
      if (req.accepts('text/html')){
	      res.redirect("/spaces/"+space._id + "?spaceAuth=" + hash);
      } else {
	      res.status(200).json(space);
      }
    } else {
      if (req.accepts('text/html')) {
	      res.status(404).render('not_found', {});
      } else {
	      res.status(404).json({});
      }
    }
  });
});

router.get('/spaces/:id', (req, res) => {
  res.render('spacedeck', { config:config, user:req.user });
});

module.exports = {router: router, passport:passport};
