"use strict";

const express = require("express"),
  config = require("config"),
  crypto = require("crypto"),
  Promise = require("bluebird");

let photoDB;

require("../db/photos").then(function(db) {
  photoDB = db;
});

const router = express.Router();
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/";

router.put("/:id", function(req, res/*, next*/) {
  if (!req.user.maintainer) {
    return res.status(401).send("Unauthorized to modify photos.");
  }

  return res.status(400).send("Invalid request");
});

router.delete("/:id", function(req, res/*, next*/) {
  console.log(`DELETE /${req.params.id}`);
  
  if (!req.user.maintainer) {
    return res.status(401).send("Unauthorized to delete photos.");
  }

  return photoDB.sequelize.query("UPDATE faces SET faceConfidence=0 WHERE id=:id", {
    replacements: {
      id: req.params.id
    }
  }).then(() => {
    return res.status(200).send({ message: `${req.params.id} deleted` });
  }).catch((error) => {
    return res.status(500).send({ error: error });
  })
});

function getFacesForPhoto(id) {
  /* Get the set of faces in this photo */
  return photoDB.sequelize.query(
    "SELECT * FROM faces WHERE photoId=:id AND faceConfidence>0.9", {
    replacements: {
      id: id,
    },
    type: photoDB.Sequelize.QueryTypes.SELECT,
    raw: true
  }).then((faces) => {
    /* For each face in the photo, get the related faces */
    return photoDB.sequelize.query(
      "SELECT relatedFaces.photoId AS photoId,fd.face1Id,fd.face2Id,fd.distance,relatedFaces.faceConfidence " +
      "FROM (SELECT id,photoId,faceConfidence FROM faces WHERE faces.faceConfidence>=0.9 AND faces.id IN (:ids)) AS faces " +
      "INNER JOIN faces AS relatedFaces ON relatedFaces.faceConfidence>=0.9 AND relatedFaces.id IN (fd.face1Id,fd.face2Id) " +
      "INNER JOIN facedistances AS fd ON fd.distance<=0.5 " +
      "  AND (fd.face1Id=faces.id OR fd.face2Id=faces.id) " +
      "WHERE (faces.id=fd.face1Id OR faces.id=fd.face2Id) " +
      "ORDER BY fd.distance ASC", {
      replacements: {
        ids: faces.map(face => face.id),
      },
      type: photoDB.Sequelize.QueryTypes.SELECT,
      raw: true
    }).then((relatedFaces) => {
      faces.forEach((face) => {
        face.relatedFaces = relatedFaces.filter((related) => {
          return (related.photoId != id && (related.face1Id == face.id || related.face2Id == face.id));
        }).map((related) => {
          return {
            distance: related.distance,
            faceConfidence: related.faceConfidence,
            photoId: related.photoId,
            faceId: related.face1Id != face.id ? related.face1Id : related.face2Id
          }
        });
      });
      return faces;
    });
  });
}

router.get("/:id?", (req, res) => {
  let id;
  if (req.params.id) {
    id = parseInt(req.params.id);
    if (id != req.params.id) {
      return res.status(400).send({ message: "Usage /[id]"});
    }
  }

  let promise;
  if (id) {
    promise = photoDB.sequelize.query(
      "SELECT * FROM faces WHERE id=:id", {
      replacements: {
        id: id
      },
      type: photoDB.Sequelize.QueryTypes.SELECT,
      raw: true
    });
  } else {
    promise = photoDB.sequelize.query(
      "SELECT COUNT(id) AS count FROM faces WHERE faceConfidence>=0.9 AND identityId IS NULL", {
      type: photoDB.Sequelize.QueryTypes.SELECT,
      raw: true
    }).then((results) => {
      if (!results[0].count) {
        return [];
      }
      const random = Math.floor(Math.random() * results[0].count);
      return photoDB.sequelize.query(
        "SELECT * FROM faces WHERE faceConfidence>=0.9 AND identityId IS NULL ORDER BY id LIMIT :index,1", {
        replacements: {
          index: random
        },
        type: photoDB.Sequelize.QueryTypes.SELECT,
        raw: true
      });
    });
  }
  
  return promise.then((faces) => {
    if (!faces.length) {
      return [];
    }
    console.log("Looking up " + faces.map(face => face.id).join(","));
    return photoDB.sequelize.query(
      "SELECT relatedFaces.photoId AS photoId,fd.face1Id,fd.face2Id,fd.distance,relatedFaces.faceConfidence " +
      "FROM (SELECT id,photoId,faceConfidence FROM faces WHERE faces.id IN (:ids)) AS faces " +
      "INNER JOIN faces AS relatedFaces ON relatedFaces.identityId IS NULL AND relatedFaces.faceConfidence>=0.9 AND relatedFaces.id IN (fd.face1Id,fd.face2Id) " +
      "INNER JOIN facedistances AS fd ON fd.distance<=0.5 " +
      "  AND (fd.face1Id=faces.id OR fd.face2Id=faces.id) " +
      "WHERE (faces.id=fd.face1Id OR faces.id=fd.face2Id) " +
      "ORDER BY fd.distance ASC",{
      replacements: {
        ids: faces.map(face => face.id)
      },
      type: photoDB.Sequelize.QueryTypes.SELECT,
      raw: true
    }).then((relatedFaces) => {
      faces.forEach((face) => {
        face.relatedFaces = relatedFaces.filter((related) => {
          return (related.photoId != faces[0].photoId && (related.face1Id == face.id || related.face2Id == face.id));
        }).map((related) => {
          return {
            distance: related.distance,
            faceConfidence: related.faceConfidence,
            photoId: related.photoId,
            faceId: related.face1Id != face.id ? related.face1Id : related.face2Id
          }
        });
      });
      return faces;
    });
  }).then((results) => {
    return res.status(200).json(results);
  }).catch((error) => {
    console.error(error);
    return res.status(500).send("Error processing request.");
  });
});

module.exports = router;
