text: const Device = require('./models/Device')
  const User = require('./models/User')
  const jwt = require('jsonwebtoken');
  const {secret} = require("./config")
  const fs = require('fs')
  
  ///// Config Section
  // const PATH_SYSLOG = '/var/local/API-Log/DVR.log';
  // const PATH_JSON_SYSLOG = '/var/local/API-Log/DVR_JSON.log'
  const PATH_SYSLOG = 'DVR.log';
  const PATH_JSON_SYSLOG = 'DVR_JSON.log'
  const Enable_Syslog = true;
  const Enable_Json_Syslog = true;
  const TimeToAlert = '600000' // ms how long must elapse since the last successful ping before the event is triggered DISSCONECTED
  const Freq_Check_Devices = 600000   // the interval through which the last ping is checking
  /////
  
  const generateAccessToken = (username) => {
  
      return jwt.sign({username},
           secret,
          {expiresIn: "24h"} )
  }
  
  const CheckerDates = async () => {
      let today = new Date();
      const dev = await Device.find()
  
      for (let i = 0; i < dev.length; i++) {
          const diffTime = Math.abs(dev[i].lastseen - today);
          if(diffTime > TimeToAlert){
              if(!dev[i].alert){
                  if (Enable_Syslog){saveLog(dev[i].devicename,dev[i].location,"DEVICE","DISCONNECTED")}
                  if (Enable_Json_Syslog){saveJSONlog(dev[i].devicename,dev[i].location,"DEVICE","DISCONNECTED")}
                  const dev1 = await Device.updateOne({devicename:dev[i].devicename}, {alert:"true"})
              }
          }
      }
  }
  
  const GetCurrentDate = () => {
      let date_ob = new Date();
      let date = ("0" + date_ob.getDate()).slice(-2);
      let month = date_ob.toLocaleString('default', { month: 'short' });
      let year = date_ob.getFullYear();
      let hours = ("0" + date_ob.getHours()).slice(-2);
      let minutes = ("0" +date_ob.getMinutes()).slice(-2);
      let seconds = ("0" +date_ob.getSeconds()).slice(-2);
      return date = month + "-" + date + "-" + hours + ":" + minutes + ":" + seconds + "-" + year
  }
  
  const saveLog = (device,location,object,status) => {
      let date = GetCurrentDate()
      let text = "1 " +  date + " " +"EVIAN " + "EvianDevice 1001:"  + " [" + device +"]"+" [" + location +"] ["+ object +"] "+ status + '\r\n';
      fs.open(PATH_SYSLOG, 'r', (err, fd) => {
          if (err) {
              if (err.code === 'ENOENT') {
                  fs.writeFile(PATH_SYSLOG, text, function (err) {
                      if (err) throw err;
                  });
              }else {
                  fs.appendFile(PATH_SYSLOG, text, function (err) {
                      if (err) return console.log(err);
                  });
              }
          }else {
              fs.appendFile(PATH_SYSLOG, text, function (err) {
                  if (err) return console.log(err);
              });
          }
  
       });
  
  
  }
  
  const saveJSONlog = (device,location,object,status) => {
      let date = GetCurrentDate()
      let JSON_log = {
          Device: device,
          Location: location,
          Object: object,
          Status: status
      };
      let data = JSON.stringify(JSON_log);
      let text ="1 " +  date + " " +"EVIAN " + "EvianDevice 1001:" + data + '\r\n';
      fs.open(PATH_JSON_SYSLOG, 'r', (err, fd) => {
          if (err) {
              if (err.code === 'ENOENT') {
                  fs.writeFile(PATH_JSON_SYSLOG, text, function (err) {
                      if (err) throw err;
                  });
              }else {
                  fs.appendFile(PATH_JSON_SYSLOG, text, function (err) {
                      if (err) return console.log(err);
                  });
              }
          }else {
              fs.appendFile(PATH_JSON_SYSLOG, text, function (err) {
                  if (err) return console.log(err);
              });
          }
  
      });
  }
  
  class authController {
  
      //POST
      async CreateUser(req,res){
          try {
              const {username,token} = req.body
  
              const cand_token = await User.findOne({token:token})
              if (!cand_token) {return res.status(400).json({message: "Access blocked."})}
  
              const candidate = await User.findOne({username:username})
              if (candidate) {return res.status(400).json({message: "User Exist."})}
  
              const user = new User({username:username, token:generateAccessToken()})
              await user.save()
  
              res.status(200).json({user})
          }
          catch (e) {
              res.status(500).json({message:'Internal error idi na hiu'})
          }
  
      }
  
      async GetTokens(req,res){
          try {
              const {root_token} = req.body
              const root_user = await User.findOne({token:root_token}) //Root token
              if (!root_user || root_user.username !== 'hui') {return res.status(400).json({message: "Access blocked. Fuck you!(idi nahui)"})}
  
              const token_list = await User.find()
              if (!token_list) {return res.status(400).json({message: "no one token."})}
  
              res.status(200).json({token_list})
          }
          catch (e) {
              console.log(e)
              res.status(500).json({message:'Internal error idi na hiu'})
          }
  
      }
  
      async ResetUserToken(req,res){
          try {
              const {username,root_token} = req.body
              const root_user = await User.findOne({token:root_token}) //Admin token
              if (!root_user || root_user.username !== 'hui') {return res.status(400).json({message: "Access blocked. Fuck you!(idi nahui)"})}
  
              const candidate = await User.findOne({username:username})
              if (!candidate) {return res.status(400).json({message: "User does not exist."})}
  
              const new_token = generateAccessToken(username)
  
              const user = await User.updateOne({username:username}, {token:new_token})
  
              res.status(200).json({"new user token":new_token})
          }
          catch (e) {
              console.log(e)
              res.status(500).json({message:'Internal error idi na hiu'})
          }
  
      }
  
      async CreateDevices(req,res){
          try {
              const {admin_token, device,location,other} = req.body
              const candidate = await User.findOne({token:admin_token})
              if (!candidate || candidate.username !== 'admin') {return res.status(400).json({message: "Access blocked."})}
  
              const candidate_device = await Device.findOne({device:device})
              if (candidate_device) {return res.status(400).json({message: "Device with that name already exist."})}
  
              const dev = new Device({devicename:device, location: location, lastseen:'never', alert:'false', other:other})
              await dev.save()
  
              res.status(200).json({dev})
          }
          catch (e) {
              res.status(500).json({message:'Internal error idi na hiu'})
          }
  
      }
  
      async getdevices(req,res){
          try {
              const {admin_token, device} = req.body
              const candidate = await User.findOne({token:admin_token})
              if (!candidate || candidate.username !== 'admin') {return res.status(400).json({message: "Access blocked. sosi hui"})}
              if(device && device !== "all"){
                  const dev = await Device.findOne({devicename:device})
                  return res.status(200).json({dev})
              }else {
                  const dev_list = await Device.find()
                  return res.status(200).json({dev_list})
              }
          }
          catch (e) {
              return res.status(500).json({message:'Internal error idi na hiu'})
          }
  
      }
  
      async createalert(req,res){
          try {
              const {device_token,device,location,object,status} = req.body
  
              const candidate = await User.findOne({token:device_token})
              if (!candidate || candidate.username !== "devices") {return res.status(400).json({message: "idi nahui."})}
  
                  if (Enable_Syslog){saveLog(device,location,object,status)}
  
                  if (Enable_Json_Syslog){saveJSONlog(device,location,object,status)}
  
                  return res.status(200).json({message: "done"})
          }
          catch (e) {
              return res.status(500).json({message:'Internal error. idi nahui gandon'})
          }
      }
  
  //======================================================================
      //GET
      //ROOT
      async SyncChecker(req,res){
          const candidate = await User.findOne({token:req.params.token})
          if (!candidate || candidate.username !== 'hui' ) {
              console.log('===Verify ROOT token for checker!===')
              return res.status(400).json({message: "Access blocked. sosi hui"})
          }
          console.log('===Checker working!===')
          setInterval(CheckerDates, Freq_Check_Devices)
          res.status(200).json({message:'working... and SOSI HUI'})
      }
  
      async SetHealth(req,res){
          const candidate = await User.findOne({token:req.params.token})
          if (!candidate || candidate.username !== 'hui') {return res.status(400).json({message: "Access blocked. sosi hui"})}
  
          const dev = await Device.updateOne({devicename:req.params.device}, {alert:"false"})
  
          res.status(200).json({message:'Healthy now <3'})
      }
  
      //DEVICES
      async create_get_alert(req,res){
          try {
              const candidate = await User.findOne({token:req.params.token})
              if (!candidate || candidate.username !== 'devices') {return res.status(400).json({message: "Access blocked. idi nahui."})}
  
                  if (Enable_Json_Syslog){saveJSONlog(req.params.device,req.params.location,req.params.object,req.params.status)}
  
                  if (Enable_Syslog){saveLog(req.params.device,req.params.location,req.params.object,req.params.status)}
  
                  return res.status(200).json({message: "done"})
          }
          catch (e) {
              console.log(e)
              return res.status(500).json({message:'Internal error. idi na hiu'})
          }
  
      }
  
      //ADMIN
      async getdevicesGET(req,res){
          try {
              const candidate = await User.findOne({token:req.params.token})
              if (!candidate || candidate.username !== 'admin') {return res.status(500).json({message: "Access blocked. sosi hui"})}
  
              if(req.params.device && req.params.device !== "all"){
                  const dev = await Device.findOne({devicename:req.params.device})
                  return res.status(200).json({dev})
              }else {
                  const dev_list = await Device.find()
                  return res.status(200).json({dev_list})
              }
          }
          catch (e) {
              return res.status(500).json({message:'Internal error idi na hiu'})
          }
  
      }
  
      //DEVICES
      async ping(req,res){
          let today = new Date();
  
          const candidate = await User.findOne({token:req.params.token})
          if (!candidate || candidate.username === "hui" || candidate.username === "admin") {
              return res.status(400).json({message: "idi nahui."})
          }
  
          const dev_candidate = await Device.findOne({devicename:req.params.device})
          if (!dev_candidate){
              const dev = new Device({devicename:req.params.device, location: req.params.location,lastseen:today.valueOf(),alert:"false"})
              await dev.save()
              return res.status(200).json({message:'Device Created'})
          }
  
          let before = dev_candidate.alert
  
          const dev = await Device.updateOne({devicename:req.params.device}, {lastseen:today.valueOf(),alert:"false"})
          const new_candidate = await Device.findOne({devicename:req.params.device})
  
          let after = new_candidate.alert
  
          if(before !== after){
              if (Enable_Syslog){saveLog(new_candidate.devicename,new_candidate.location,"DEVICE","CONNECTED")}
              if (Enable_Json_Syslog){saveJSONlog(new_candidate.devicename,new_candidate.location,"DEVICE","CONNECTED")}
  
          }
  
          return res.status(200).json({message:'ping ok'})
      }
  
      //ALL POST/GET
      async test(req,res){
          console.log("asdasdas")
          res.status(200).json({message:'working... and SOSI HUI'})
      }
  
  }
  
  module.exports = new authController()
  