import '@k-core/polyfills';
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import 'rxjs/Rx';
import * as path from 'path';
import * as auth from 'http-auth';

import * as express from 'express';
import * as cookieParser from 'cookie-parser'
import session from 'express-session'


import { Request, Response } from 'express';
import { platformServer, renderModuleFactory } from '@angular/platform-server';
import { ServerAppModule } from './server-app.module';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { ROUTES } from './server-routes';
import { enableProdMode } from '@angular/core';
import { urlkey } from '@k-settings/app-setup'
import { storeId } from '@k-settings/store-helper'
import { DataLayerManager } from '../../../node_modules/@agm/core';
import * as proxy from 'express-http-proxy'

enableProdMode();

const url = require('url')
const app = express();
const port = process.env.PORT || 8000;
const baseUrl = `http://localhost:${port}`;
const cookieTime = 24 * 60 * 60 * 1000


const axios = require('axios')

app.engine('html', ngExpressEngine({
	bootstrap: ServerAppModule
}));

app.set('view engine', 'html');
app.set('views', 'src');

function cacheControl(req, res, next) {
	// instruct browser to revalidate in 60 seconds
	res.header('Cache-Control', 'max-age=432000');
	next();
}

app.use('/configuratorapi',  proxy('https://bmsproductconfigurator-prod.azurewebsites.net/'))
app.use('/catalogapi',  proxy('https://bmscatalogquery-prod.azurewebsites.net'))
app.use('/variantqueryapi',  proxy('https://bmsproductvariantquery-prod.azurewebsites.net'))
app.use('/variantcommandapi',  proxy('https://bmsproductvariantcommand-prod.azurewebsites.net'))

// Auth Config
// var USER    = 'Rulle',
// 	PASS    = 'Gardin',
// 	USEAUTH = false;

// var basic = auth.basic({
// 		realm: 'Kake'
// 	}, function(username, password, callback) {
// 		callback(username === USER && password === PASS);
// 	});

// if (USEAUTH) {
// 	app.use(auth.connect(basic));
// }

/**
 * **** LOGIN PAGE REDIRECT ****
 */

// Define the session secret, TODO: Change this to be a dynamic session secret based on project
var secret = 'PHPSESSIDB2B'

// Session specs
var sess = {
	resave: false,
	saveUninitialized: true,
	secret: secret,
	cookie: {
		maxAge: cookieTime
	}
}

app.set('trust proxy', 1)

// Define the session code
app.use(session(sess))
app.use(cookieParser())


/**
 * Password protects the site, if the backend informs it to, this utilizes a cookie to verify the session
 * is kept in "check", and skips localhost for verification, so password protected pages can be visited from
 * localhost, for development / testing purposes
 * 
 * @param req
 * @param res
 * @param next
 */
function passwordProtection(req: any, res: Response, next) {

	let sessionId = req.session.id
	let host = req.get('host')
	let cookie = req.cookies.kakesession


	// Checks if he cookie exists, if it does, re-aquire the session Id, else, define the the cookie based on the sessionId
	if (cookie === undefined) {
		res.cookie('kakesession', req.session.id, { maxAge: cookieTime })
	} else {
		sessionId = cookie
	}

	// Verify if host is localhost, or it has to display login
	if(host.indexOf('localhost') === -1) {

		axios.get('https://' + host + '/login/check.php?storeId='+storeId + '&guid=' + sessionId).then((response) => {
	
			// Isolate the response data
			let data = response.data
	
			// Checks if the server requires login, and if the user is already logged in - if not true, skip on to the next request
			if(data.has_login && !data.logged_in) {
	
				res.send('<script>window.location.href="/login?redirect=' + urlkey + '&guid='+ req.session.id +'";</script>');
			} else {
	
				next()
			}
	
		}).catch((e) => {
	
			// Errors out, displaying the error if login fails for some reason, this will happen if the login request bounces
			console.error('login does not display correctly,', e)
			res.status(500).send('Internal Server Error - 500')
		})

	} else {

		new Promise((resolve) => {

			// Any localhost specific logic
			resolve(null)
		}).then(() => {
			
			// Localhost is found, bypassing the login request, so the code will execute accordingly
			next()
		})
	}
}


/**
 * Typecasting `req` to `any` so it doesn't fail over `session.id`
 */
app.get('*', (req: any, res, next) => {
	passwordProtection(req, res, next)
})


// Serve static files
app.use('/assets', cacheControl, express.static('source/assets', {maxAge: 432000}));

// Serve application on route access
app.use('/', express.static('dist', {index: false}));


ROUTES.forEach((route: string) => {
	app.get(route, (req: Request, res: Response) => {
		console.time(`GET: ${req.originalUrl}`);
		res.render('../dist/index', {
			req: req,
			res: res
		});
		console.timeEnd(`GET: ${req.originalUrl}`);
	});
});

app.listen(port, () => {
	console.log(`Listening at ${baseUrl}`);
});
