'use strict';

const _ = require('underscore');
const React = require('react');
const Router = require('react-router');
const serialize = require('serialize-javascript');

const UserAction = require('../share/actions/UserAction');
const NavigateAction = require('../share/actions/NavigateAction');
const RootComponent = require('../share/components/RootComponent');

const mongoose = require('mongoose');
const passport = require('koa-passport');
const srv = module.exports = require('koa')();
const app = require('../share');

mongoose.connect(process.env.MONGODB_URI);

const CurrentRoute = function(context) {
  return function(callback) {
    Router.run(app.getComponent(), context.path, function(Handler, state) {
      callback(null, {Component: React.createFactory(Handler), state});
    });
  };
};

srv.keys = [process.env.SESSION_SECRET];
process.env.NODE_ENV !== 'test' && srv.use(require('koa-logger')());
srv.use(require('koa-static')(`${__dirname}/../public`));
srv.use(require('koa-json')());
srv.use(require('koa-bodyparser')());
srv.use(require('koa-overwrite')());
srv.use(require('koa-generic-session')({
  store: require('koa-redis')(),
  cookie: { maxage: 365 * 24 * 60 * 60 * 1000 }
}));
srv.use(passport.initialize());
srv.use(passport.session());

require('./models')();
require('./controllers')(srv);

srv.use(function*() {
  let context = app.createContext();
  let {Component, state} = yield CurrentRoute(this);
  if (state.routes.filter((route) => route.name === 'error').length > 0) {
    this.status = 404;
  }
  yield context.executeAction(NavigateAction, {
    actionType: NavigateAction.actionTypes.NAVIGATE,
    state: state
  });

  yield context.executeAction(UserAction, {
    actionType: UserAction.actionTypes.READ_CURRENT_USER,
    cookie: this.headers.cookie
  });

  let states = [
    `window.env=${serialize(_.pick(process.env, ['NODE_ENV', 'TIMEOUT', 'APP_URL']))}`,
    `window.App=${serialize(app.dehydrate(context))}`
  ];
  this.body = React.renderToStaticMarkup(React.createElement(RootComponent, {
    state: `${states.join(';')};`,
    markup: React.renderToString(Component({context: context.getComponentContext()}))
  }));
});
