'use strict';

// modules
const express = require('express');
const async = require('async');

// HTTP status codes by name
const codes = require('./http-codes');

const routerHandling = require('../middleware/router-handling');

// Mongoose Model using mongoDB
const LogBudgetModel = require('../models/logs/budget');
const LogRespawnModel = require('../models/logs/respawn');
const LogReviveModel = require('../models/logs/revive');
const LogKillModel = require('../models/logs/kill');
const LogVehicleModel = require('../models/logs/vehicle');
const LogTransportModel = require('../models/logs/transport');
const LogFlagModel = require('../models/logs/flag');
const LogPointsModel = require('../models/logs/points');
const LogPlayerCountModel = require('../models/logs/player-count');
const LogServerFpsModel = require('../models/logs/server-fps');

const logsRouter = new express.Router();

const processLogRequest = (model, filter, res, next) => {
  model.find(filter, {}, {sort: {time: 1}}, (err, log) => {
    if (err) return next(err);
    if (!log || log.length === 0) {
      const err = new Error('No logs found');
      err.status = codes.notfound;
      return next(err);
    }
    res.locals.items = log;
    next();
  });
};

// routes **********************
logsRouter.route('/:warId')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            const sort = {sort: {time: 1}};

            const pointsObjects = LogPointsModel.find(filter, {}, sort);
            const budgetObjects = LogBudgetModel.find(filter, {}, sort);
            const respawnObjects = LogRespawnModel.find(filter, {}, sort);
            const reviveObjects = LogReviveModel.find(filter, {}, sort);
            const killObjects = LogKillModel.find(filter, {}, sort);
            const vehicleObjects = LogVehicleModel.find(filter, {}, sort);
            const transportObjects = LogTransportModel.find(filter, {}, sort);
            const flagObjects = LogFlagModel.find(filter, {}, sort);
            const playerCountObjects = LogPlayerCountModel.find(filter, {}, sort);
            const resources = {
              points: pointsObjects.exec.bind(pointsObjects),
              budget: budgetObjects.exec.bind(budgetObjects),
              respawn: respawnObjects.exec.bind(respawnObjects),
              revive: reviveObjects.exec.bind(reviveObjects),
              kill: killObjects.exec.bind(killObjects),
              vehicle: killObjects.exec.bind(vehicleObjects),
              transport: transportObjects.exec.bind(transportObjects),
              flag: flagObjects.exec.bind(flagObjects),
              playerCount: playerCountObjects.exec.bind(playerCountObjects),
            };

            async.parallel(resources, (error, results) => {
              if (error) {
                res.status(500);
              }
              res.locals.items = results;
              next(error);
            });
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/budget')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.fraction) filter['fraction'] = req.query.fraction;
            processLogRequest(LogBudgetModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/respawn')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.player) filter['player'] = req.query.player;
            processLogRequest(LogRespawnModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/revive')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.medic) filter['medic'] = req.query.medic;
            if (req.query.patient) filter['patient'] = req.query.patient;
            if (req.query.stabilized) filter['stabilized'] = true;
            if (req.query.revive) filter['stabilized'] = false;
            if (req.query.fraction) filter['fraction'] = req.query.fraction;
            processLogRequest(LogReviveModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/kills')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.shooter) filter['shooter'] = req.query.shooter;
            if (req.query.target) filter['target'] = req.query.target;
            if (req.query.friendlyFire) filter['friendlyFire'] = true;
            if (req.query.noFriendlyFire) filter['friendlyFire'] = false;
            if (req.query.fraction) filter['fraction'] = req.query.fraction;
            processLogRequest(LogKillModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/transport')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.driver) filter['driver'] = req.query.driver;
            if (req.query.passenger) filter['passenger'] = req.query.passenger;
            if (req.query.fraction) filter['fraction'] = req.query.fraction;
            processLogRequest(LogTransportModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/flag')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.player) filter['player'] = req.query.player;
            if (req.query.capture) filter['capture'] = true;
            if (req.query.defend) filter['capture'] = false;
            if (req.query.fraction) filter['fraction'] = req.query.fraction;
            processLogRequest(LogFlagModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/points')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            if (req.query.fraction) filter['fraction'] = req.query.fraction;
            processLogRequest(LogPointsModel, filter, res, next);
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.route('/:warId/performance')
          .get((req, res, next) => {
            const filter = {war: req.params.warId};
            LogServerFpsModel.find(filter, (err, items) => {
              if (err) return next(err);
              if (!items) {
                const err = new Error('No logs found');
                err.status = codes.notfound;
                return next(err);
              }
              res.locals.items = items;
              next();
            });
          })
          .all(
            routerHandling.httpMethodNotAllowed
          );

logsRouter.use(routerHandling.emptyResponse);

module.exports = logsRouter;