const express = require('express');
const router = express.Router(),
  fs = require('fs'),
  path = require('path');

const telegrambot = require('../telegram/telegrambot');

const i18n = require('i18n');

const sharp = require('sharp');

const { authenticate, authenticate_noerror } = require(
  '../middleware/authenticate');

const { ObjectID } = require('mongodb');
// const {ListaIngresso} = require('../models/listaingresso');
const { Graduatoria } = require('../models/graduatoria');

const mongoose = require('mongoose').set('debug', false);
const { CfgServer } = require('../models/cfgserver');

// const uuidv4 = require('uuid/v4'); // I chose v4 ‒ you can select others

// const ftp = require('../ftp/FTPClient');
const formidable = require('formidable');
const folder = path.join(__dirname, 'upload');

if (!fs.existsSync(folder)) {
  fs.mkdirSync(folder);
}

const _ = require('lodash');

const { User } = require('../models/user');
const { MyGroup } = require('../models/mygroup');
const { Circuit } = require('../models/circuit');
const { Booking } = require('../models/booking');
const { Operator } = require('../models/operator');
const { Where } = require('../models/where');
const { MyEvent } = require('../models/myevent');
const { Contribtype } = require('../models/contribtype');
const { PaymentType } = require('../models/paymenttype');
const { Discipline } = require('../models/discipline');
const { MyElem } = require('../models/myelem');
const { Skill } = require('../models/skill');
const { Good } = require('../models/good');
const { StatusSkill } = require('../models/statusSkill');
const { Province } = require('../models/province');
const { Sector } = require('../models/sector');
const { SectorGood } = require('../models/sectorgood');
const { CatGrp } = require('../models/catgrp');
const Site = require('../models/site');
const { Level } = require('../models/level');
const { AdType } = require('../models/adtype');
const { AdTypeGood } = require('../models/adtypegood');
const { Newstosent } = require('../models/newstosent');
const { MyPage } = require('../models/mypage');
const { CalZoom } = require('../models/calzoom');
const { Gallery } = require('../models/gallery');
const { Settings } = require('../models/settings');
const { SendMsg } = require('../models/sendmsg');
const { SendNotif } = require('../models/sendnotif');
const { Permission } = require('../models/permission');
const Producer = require('../models/producer');
const Cart = require('../models/cart');
const OrdersCart = require('../models/orderscart');
const Storehouse = require('../models/storehouse');
const Department = require('../models/department');
const { Category } = require('../models/category');
const Group = require('../models/group');

const tools = require('../tools/general');

const server_constants = require('../tools/server_constants');
const actions = require('./api/actions');

const shared_consts = require('../tools/shared_nodejs');

const globalTables = require('../tools/globalTables');

const UserCost = {
  FIELDS_UPDATE_TELEGRAM_BOT: [
    'profile.teleg_id',
    'profile.manage_telegram',
    'deleted',
    'reported',
  ],

  FIELDS_REQUISITI: [
    'verified_email',
    'profile.teleg_id',
    'profile.saw_and_accepted',
    'profile.revolut',
    'profile.payeer_id',
    'profile.advcash_id',
    'profile.link_payment',
    'profile.email_paypal',
    'profile.paymenttypes'],
};

router.post(process.env.LINKVERIF_REG, (req, res) => {
  const body = _.pick(req.body, ['idapp', 'idlink']);
  const idapp = body.idapp;
  const idlink = body.idlink;

  // Cerco l'idlink se è ancora da Verificare

  User.findByLinkreg(idapp, idlink).then((user) => {
    if (!user) {
      //console.log("NON TROVATO!");
      return res.status(404).send();
    } else {
      console.log('user', user);
      if (user.verified_email) {
        res.send({
          code: server_constants.RIS_CODE_EMAIL_ALREADY_VERIFIED,
          msg: tools.getres__('L\'Email è già stata Verificata', res),
        });
      } else {
        user.verified_email = true;
        user.lasttimeonline = new Date();
        user.save().then(() => {
          //console.log("TROVATOOOOOO!");
          res.send({
            code: server_constants.RIS_CODE_EMAIL_VERIFIED,
            msg: tools.getres__('EMAIL', res) + ' ' +
              tools.getres__('VERIF', res),
          });
        });
      }
    }
  }).catch((e) => {
    console.log(process.env.LINKVERIF_REG, e.message);
    res.status(400).send();
  });

});

// Faccio richiesta di una Nuova Password
router.post(process.env.LINK_REQUEST_NEWPASSWORD, async (req, res) => {

  try {
    const body = _.pick(req.body, ['idapp', 'email', 'codetocheck']);
    const idapp = body.idapp;
    const email = body.email.toLowerCase().trim();
    const codetocheck = body.codetocheck ? body.codetocheck.trim() : '';

    console.log('Request Reset Pwd:', email, ' idapp=', idapp);

    // Check if too many requests
    if (await User.tooManyReqPassword(idapp, email, true)) {
      console.log(process.env.LINK_REQUEST_NEWPASSWORD, 'TOO MANY REQUESTS !!! EXIT ', email);
      res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: 'TOO MANY REQUESTS' });
      return false;
    }

    console.log(
      'POST ' + process.env.LINK_REQUEST_NEWPASSWORD + ' idapp= ' + idapp +
      ' email = ' + email);

    const reqpwd = await User.createNewRequestPwd(idapp, email, codetocheck);
    if (reqpwd && reqpwd.ris) {
      res.send({ code: server_constants.RIS_CODE_OK, msg: '', link: reqpwd.link });
    } else {
      return res.status(200).
        send({ code: server_constants.RIS_CODE_EMAIL_NOT_EXIST, msg: '' });
    }
  } catch (e) {
    console.log(process.env.LINK_REQUEST_NEWPASSWORD, e.message);
    res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e });
  }

});

// Invio la Nuova Password richiesta dal reset!
// Ritorna il token per poter effettuare le chiamate...
router.post(process.env.LINK_UPDATE_PWD, async (req, res) => {
  const body = _.pick(req.body, ['idapp', 'email', 'tokenforgot', 'tokenforgot_code', 'password']);
  const idapp = body.idapp;
  const email = body.email.toLowerCase().trim();
  const tokenforgot = body.tokenforgot;
  const tokenforgot_code = body.tokenforgot_code;
  const password = body.password;
  const msg = 'Richiesta Nuova Password: idapp= ' + idapp + ' email = ' + email;
  console.log(msg);

  // telegrambot.sendMsgTelegramToTheManagers(body.idapp, msg);

  let user = null;

  user = await User.findByLinkTokenforgot(idapp, email, tokenforgot)
    .then((user) => {
      return user;
    }).catch((e) => {
      console.log(process.env.LINK_UPDATE_PWD, e.message);
      res.status(400).send();
    });

  if (!user) {
    user = await User.findByLinkTokenforgotCode(idapp, email, tokenforgot_code)
      .then((user) => {
        return user;
      }).catch((e) => {
        console.log(process.env.LINK_UPDATE_PWD, e.message);
        res.status(400).send();
      });
  }

  if (!user) {
    return res.send(
      { code: server_constants.RIS_CODE_TOKEN_RESETPASSWORD_NOT_FOUND });
  } else {
    // aggiorna la nuova password
    user.password = password;
    user.lasttimeonline = new Date();

    // Crea token
    user.generateAuthToken(req).then(token => {
      user.tokenforgot = '';  // Svuota il tokenforgot perché non ti servirà più...
      user.tokenforgot_code = '';  // Svuota il tokenforgot perché non ti servirà più...

      // Salva lo User
      user.save().then(() => {
        res.header('x-auth', token).
          send({ code: server_constants.RIS_CODE_OK });   // Ritorna il token di ritorno
      });
    });
  }
});

router.post('/testServer', authenticate_noerror, async (req, res) => {

  try {
    const test = req.body.test;
    let ris = { test };

    if (req.user) {
      await tools.sendNotificationToUser(req.user._id, 'Test Server',
        'Test Server OK',
        '/', '', 'server', []);
    }

    return res.send(ris);
  } catch (e) {
    console.error('testServer', e.message);
    return res.status(400).send(e);
  }

});

router.get('/test1', authenticate_noerror, async (req, res) => {

  try {
    const test = req.query.test;
    let ris = { test };

    if (req.user) {
      await tools.sendNotificationToUser(req.user._id, 'Test Server',
        'Test Server OK',
        '/', '', 'server', []);
    }

    return res.send(ris);
  } catch (e) {
    console.error('testServer', e.message);
    return res.status(400).send(e);
  }

});

router.post('/settable', authenticate, async (req, res) => {
  const params = req.body;
  const mytable = globalTables.getTableByTableName(params.table);
  
  let mydata = req.body.data;
  let extrarec = {};
  if (mydata && mydata.hasOwnProperty('extrarec')) {
    extrarec = mydata['extrarec'];
    delete mydata['extrarec'];
  }

  if (mydata === undefined) {
    console.error('MYDATA VUOTO !');
    return res.status(400).send('Mydata VUOTO');
  }

  const fieldsvalue = { 'ALL': 1 };

  mydata.idapp = req.user.idapp;
  const idapp = mydata.idapp;

  if (req.user && req.user.username) {
    User.setOnLine(req.user.idapp, req.user.username);
  }

  let consentito = false;

  try {
    if (User.isAdmin(req.user.perm) || User.isManager(req.user.perm) ||
      User.isEditor(req.user.perm) || User.isFacilitatore(req.user.perm)) {
      consentito = true;
    }

    if ((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) &&
      !User.isEditor(req.user.perm) && !User.isFacilitatore(req.user.perm)) &&
      !tools.ModificheConsentite(params.table, fieldsvalue)) {
      // If without permissions, exit
      return res.status(404).
        send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
    }

    if (shared_consts.TABLES_USER_ID.includes(params.table)) {
      if (!mydata.userId)
        mydata.userId = req.user._id;
    }

    if (shared_consts.TABLES_CREATEDBY.includes(params.table)) {
      if (!mydata.createdBy)
        mydata.createdBy = req.user.username;
    }

    if (shared_consts.TABLES_UPDATE_LASTMODIFIED.includes(params.table)) {
      mydata.date_updated = new Date();
    }

    if (shared_consts.TABLES_PERM_NEWREC.includes(params.table)) {
      if (!consentito) {
        mydata.verifyrec = false;
      }
    }

    if (params.table === shared_consts.TAB_MYGROUPS) {
      if (shared_consts.MYGROUPS_KEY_TO_CRYPTED in mydata) {
        if (mydata[shared_consts.MYGROUPS_KEY_TO_CRYPTED]) {
          mydata[shared_consts.MYGROUPS_KEY_TO_CRYPTED +
            shared_consts.SUFFIX_CRYPTED] = tools.cryptdata(
              mydata[shared_consts.MYGROUPS_KEY_TO_CRYPTED]);
        }
      }

    }

    if (shared_consts.TABLES_USER_INCLUDE_MY.includes(params.table)) {
      if (!mydata.admins || mydata.admins.length <= 0) {
        // Aggiungi solo se non esistono Admin:
        mydata.admins = [];
        const indfind = mydata.admins.findIndex(
          (rec) => (rec.username === req.user.username));

        if (indfind < 0) {
          mydata.admins.push({ username: req.user.username });
        }
      }
    }

    delete mydata['__v'];
    delete mydata['__proto__'];

    let mytablerec = new mytable(mydata);
    // console.log('mytablerec', mytablerec);

    const mytablestrutt = globalTables.getTableByTableName(params.table);

    if (mydata['_id'] !== undefined && mydata['_id'] !== 0 && mydata['_id'] !== '') {
      mytablerec.isNew = false;
    }

    if (shared_consts.TABLES_ID_NUMBER.includes(params.table) ||
      shared_consts.TABLES_ID_STRING.includes(params.table)) {

    } else if (params.table === 'hours') {

    } else {
      if ((mydata['_id'] === undefined || mydata['_id'] === '' || (mytablerec.isNew && mydata['_id'] === 0)) && (mytablerec._id === undefined || mytablerec._id === '0')) {
        mytablerec._id = new ObjectID();
        mydata._id = new ObjectID();
        mytablerec.isNew = true;
      }
    }

    const isnewrec = mytablerec.isNew;

    if (params.table === shared_consts.TAB_MYGROUPS && isnewrec) {
      // Controlla se esiste già con lo stesso nome
      let alreadyexist = await MyGroup.findOne({ idapp, groupname: mydata.groupname });
      if (alreadyexist) {
        return res.send({ code: server_constants.RIS_CODE_REC_ALREADY_EXIST_CODE });
      }
      alreadyexist = await MyGroup.findOne({ idapp, title: mydata.title });
      if (alreadyexist) {
        return res.send({ code: server_constants.RIS_CODE_REC_ALREADY_EXIST_NAME });
      }
    } else if (params.table === shared_consts.TAB_MYCIRCUITS && isnewrec) {
      // Controlla se esiste già con lo stesso nome
      let alreadyexist = await Circuit.findOne({ idapp, name: mydata.name });
      if (alreadyexist) {
        return res.send({ code: server_constants.RIS_CODE_REC_ALREADY_EXIST_CODE });
      }
      alreadyexist = await Circuit.findOne({ idapp, path: mydata.path });
      if (alreadyexist) {
        return res.send({ code: server_constants.RIS_CODE_REC_ALREADY_EXIST_NAME });
      }
      /*alreadyexist = await Circuit.findOne({idapp, symbol: mydata.symbol});
      if (alreadyexist) {
        return res.send({code: server_constants.RIS_CODE_REC_ALREADY_EXIST_SYMBOL});
      }

       */
    }

    if (shared_consts.TABLES_UPDATE_LASTMODIFIED.includes(params.table)) {
      mytablerec.date_updated = new Date();
      mydata.date_updated = new Date();
    }

    // console.log('mydata',mydata);
    // return await mytablerec.save().
    //  then(async (rec) => {

    const myPromise = new Promise((resolve, reject) => {
      resolve(mytablerec._id && mytable.findById(mytablerec._id))
    });

    // Controlla se esiste già questo record:
    if (shared_consts.TABLES_FIELDS_DESCR_AND_CITY_AND_USER.includes(params.table)) {
      if (mytablerec.isNew) {
        const trovatoDuplicato = await mytable.findOne({ idapp: mytablerec.idapp, descr: mytablerec.descr, idCity: mytablerec.idCity, userId: mytablerec.userId }).lean();
        if (trovatoDuplicato) {
          // trovatoDuplicato
          return res.status(200).send({ code: server_constants.RIS_CODE_REC_DUPLICATED_DESCR_CITY_USER, msg: '' });


        }
      }
    }

    return await myPromise
      .then(async (doupdate) => {

        if (doupdate)
          return mytable.updateOne({ _id: mytablerec._id }, mydata, { new: true })
        else
          return mytablerec.save()
      })
      .then(async (risult) => {
        let rec = null;
        if (risult && risult.ok === 1) {
          rec = await mytable.findById(mytablerec._id).lean();
        } else {
          rec = risult;
        }

        if (shared_consts.TABLES_GETCOMPLETEREC.includes(params.table)) {
          return await mytablestrutt.getCompleteRecord(rec.idapp, rec._id);
        } else {
          return rec;
        }

        // tools.mylog('rec', rec);
      }).then(async (myrec) => {

        let setnotif = false;
        let typedir = 0;
        let typeid = 0;
        let groupnameDest = '';
        let circuitnameDest = '';

        if (isnewrec) {
          // New Record created

          if (shared_consts.TABLES_ADV_NOTIFICATION.includes(params.table)) {
            typedir = shared_consts.TypeNotifs.TYPEDIR_BACHECA;
            if (params.table === shared_consts.TABLES_MYGOODS)
              typeid = shared_consts.TypeNotifs.ID_BACHECA_NEW_GOOD
            else if (params.table === shared_consts.TABLES_MYSKILLS)
              typeid = shared_consts.TypeNotifs.ID_BACHECA_NEW_SERVICE
            else if (params.table === shared_consts.TABLES_MYHOSPS)
              typeid = shared_consts.TypeNotifs.ID_BACHECA_NEW_HOSP
            setnotif = true;
          }

          if (shared_consts.TABLES_EVENTS_NOTIFICATION.includes(params.table)) {
            typedir = shared_consts.TypeNotifs.TYPEDIR_EVENTS;
            typeid = shared_consts.TypeNotifs.ID_EVENTS_NEW_REC;
            setnotif = true;
          }

          if (shared_consts.TABLES_GROUPS_NOTIFICATION.includes(params.table)) {
            typedir = shared_consts.TypeNotifs.TYPEDIR_GROUPS;
            typeid = shared_consts.TypeNotifs.ID_GROUP_NEW_REC;
            groupnameDest = myrec ? myrec.groupname : '';
            setnotif = true;
          }
          /*if (shared_consts.TABLES_CIRCUITS_NOTIFICATION.includes(params.table)) {
            typedir = shared_consts.TypeNotifs.TYPEDIR_CIRCUITS;
            typeid = shared_consts.TypeNotifs.ID_CIRCUIT_NEW_REC;
            circuitnameDest = myrec ? myrec.name : '';
            setnotif = (myrec.visibility === 0); // Not send a notification to others if the Circuit is HIDDEN or PRIVATE
          }*/
        }

        if (setnotif) {
          const myreq = { ...req };
          const myres = { ...res };
          SendNotif.createNewNotification(myreq, myres, { groupnameDest, circuitnameDest }, params.table, myrec, typedir, typeid);
        }

        if (params.table === 'circuits') {
          await Circuit.updateData(myrec.idapp, myrec.name);
        }

        if (params.table === shared_consts.TAB_MYGROUPS && isnewrec) {
          // nuovo Record:
          // aggiungi il creatore al gruppo stesso
          return await User.setGroupsCmd(mydata.idapp, req.user.username,
            myrec.groupname,
            shared_consts.GROUPSCMD.SETGROUP, true, req.user.username).then((ris) => {
              return res.send({ rec: myrec, ris });
            });
        } else if (params.table === shared_consts.TAB_MYCIRCUITS && isnewrec) {
          // nuovo Circuito:
          await User.setCircuitCmd(mydata.idapp, req.user.username, myrec.name,
            shared_consts.CIRCUITCMD.CREATE, true, req.user.username, extrarec).then((ris) => {
              return res.send({ rec: myrec, ris });
            });

          // aggiungi il creatore al Circuito stesso
          return await User.setCircuitCmd(mydata.idapp, req.user.username, myrec.name,
            shared_consts.CIRCUITCMD.SET, true, req.user.username, extrarec).then((ris) => {
              return res.send({ rec: myrec, ris });
            });
        }

        return res.send({ rec: myrec, ris: null });
      }).catch(async (e) => {
        console.error('settable', e.message);
        if (e.code === 11000) {
          const id = mytablerec._id;
          delete mytablerec._doc['_id'];
          const myfields = mytablerec._doc;
          if (!myfields.userId) {
            myfields.userId = req.user._id.toString();
          }
          return await mytablestrutt.findByIdAndUpdate(id, { $set: myfields }).
            then(async (rec) => {
              return res.send({ rec });
            }).
            catch((err) => {
              tools.mylog('error: ', err.message);
              return res.status(400).send(err);
            });
        } else {
          console.log(e.message);
        }
      });

  } catch (e) {
    console.error('settable', e.message);
    return res.status(400).send(e);
  }

});

router.post('/setsubrec', authenticate, (req, res) => {
  const params = req.body;
  const mytable = globalTables.getTableByTableName(params.table);
  const mydata = req.body.data;

  mydata.idapp = req.user.idapp;

  let mytablerec = new mytable(mydata);
  // console.log('mytablerec', mytablerec);

  const mytablestrutt = globalTables.getTableByTableName(params.table);

  const rec = mytablestrutt.createNewSubRecord(mydata.idapp, req).then(rec => {
    // tools.mylog('rec', rec);
    return res.send(rec);

  }).catch((e) => {

  });

  return res.send(rec);


  return mytablerec.save().then(rec => {
    // tools.mylog('rec', rec);
    return res.send(rec);


  }).catch((e) => {
    if (e.code === 11000) {
      const id = mytablerec._id;
      delete mytablerec._doc['_id'];
      const myfields = mytablerec._doc;
      if (!myfields.userId) {
        myfields.userId = req.user._id.toString();
      }
      return mytablestrutt.findByIdAndUpdate(id, { $set: myfields }).
        then(async (rec) => {
          return res.send(rec);
        }).
        catch((err) => {
          tools.mylog('error: ', err.message);
          return res.status(400).send(err);
        });
    } else {
      console.log(e.message);
    }
  });

});

router.post('/gettable', authenticate, (req, res) => {
  const params = req.body;
  let idapp = req.user ? req.user.idapp : params.idapp;
  const mytable = globalTables.getTableByTableName(params.table);
  //console.log('mytable', mytable);
  if (!mytable) {
    console.log(`Table ${params.table} not found`);
    return res.status(400).send({});
  }

  try {

    if (req.user && req.user.username) {
      User.setOnLine(req.user.idapp, req.user.username);
    }


    return mytable.executeQueryTable(idapp, params, req.user).then(ris => {
      // console.log('ris=', ris);
      return res.send(ris);

    }).catch((e) => {
      console.error('gettable: ' + e.message);
      res.status(400).send(e);
    });
  } catch (e) {
    console.error(`ERROR gettable ${params.table}: `, e.message, 'params',
      params);
    res.status(500).send(e);
  }

});

router.post('/getexp', authenticate, (req, res) => {
  const params = req.body;
  let idapp = req.user.idapp;
  const myUser = globalTables.getTableByTableName('users');
  // console.log('mytable', mytable);
  if (!myUser || params.filtersearch2 !== 'fdsgas1') {
    return res.status(400).send({});
  }

  if ((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) &&
    !User.isFacilitatore(req.user.perm))) {
    // If without permissions, exit
    return res.status(404).
      send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
  }

  try {

    if (params.table === 'exp') {
      return myUser.find({
        idapp,
        $or: [
          { deleted: { $exists: false } },
          { deleted: { $exists: true, $eq: false } }],
      },
        {
          username: 1,
          name: 1,
          surname: 1,
          email: 1,
          'reported': 1,
          date_report: 1,
          username_who_report: 1,
          'profile.teleg_id': 1,
          'verified_by_aportador': 1,
          'profile.username_telegram': 1,
          'profile.firstname_telegram': 1,
          'profile.lastname_telegram': 1,
        }).then(ris => {

          return res.send(ris);

        }).catch((e) => {
          console.error('getexp: ' + e.message);
          res.status(400).send(e);
        });
    }

  } catch (e) {
    console.error(`ERROR getexp ${params.table}: `, e.message, 'params',
      params);
    res.status(500).send(e);
  }

});

router.post('/pickup', authenticate, (req, res) => {
  const params = req.body;
  let idapp = req.user.idapp;
  let mytable = globalTables.getTableByTableName(params.table);
  // console.log('mytable', mytable);
  if (!mytable) {
    console.log(`Table ${params.table} not found`);
    return res.status(400).send({});
  }

  return mytable.executeQueryPickup(idapp, params).then(ris => {
    return res.send(ris);

  }).catch((e) => {
    console.log(e.message);
    res.status(400).send(e);
  });

});

router.post('/getpage', async (req, res) => {
  const params = req.body;
  const idapp = req.body.idapp;
  const mypath = params.path;

  let found = await MyPage.findOne({ idapp, path: mypath }).then((ris) => {
    if (ris)
      return res.send({ mypage: ris });
    else
      return null;
  }).catch((e) => {
    console.log(e.message);
    res.status(400).send(e);
  });
  if (!found) {
    // trova quelli con il :
    let regexp = new RegExp(`:`, 'ig')
    const searchpagesSpec = await MyPage.find({ idapp, path: { $regex: regexp } });

    if (searchpagesSpec) {
      let arrsubpath = mypath.split('/');
      for (let i = 0; i < searchpagesSpec.length; i++) {
        let arrsubstr = searchpagesSpec[i].path.split('/');

        if (arrsubpath.length === arrsubpath.length) {

          let mypathbuild = '';

          for (let j = 0; j < arrsubstr.length; j++) {
            if (arrsubstr[j].includes(':')) {
              mypathbuild += arrsubpath[j] + '/';
            } else {
              mypathbuild += arrsubstr[j] + '/';
            }
          }

          if (mypath + '/' === mypathbuild) {
            return res.send({ mypage: searchpagesSpec[i] });
          }
        }
      }
    }

    return await MyPage.findOne({ idapp, path: mypath }).then((ris) => {
      return res.send({ mypage: ris });
    });
  }
  return found;

});

router.patch('/setlang', authenticate, async (req, res) => {
  const username = req.body.data.username;
  const idapp = req.user.idapp;
  const mydata = req.body.data;

  const lang = mydata.lang;

  const fieldsvalue = {
    lang,
  };

  if (!!lang) {
    const rec = await User.findByUsername(idapp, username, false);
    let ris = null;
    if (!!rec)
      ris = await User.findByIdAndUpdate(rec.id, { $set: fieldsvalue });

    if (!!ris) {
      return res.send({ code: server_constants.RIS_CODE_OK, msg: '' });
    }

    res.status(400).send();
  }

});

router.patch('/chval', authenticate, async (req, res) => {
  // const idapp = req.body.idapp;
  const id = req.body.data.id;
  const idapp = req.user.idapp;
  const mydata = req.body.data;

  try {
    const mytable = globalTables.getTableByTableName(mydata.table);
    const fieldsvalue = mydata.fieldsvalue;
    const unset = mydata.unset;

    const { Account } = require('../models/account');

    // tools.mylogshow('PATCH CHVAL: ', id, fieldsvalue);

    // If I change my record...
    if (((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) &&
      !User.isEditor(req.user.perm) && !User.isFacilitatore(req.user.perm)) &&
      (req.user._id.toString() !== id) &&
      (!tools.ModificheConsentite(mydata.table, fieldsvalue)))
      && !((mydata.table === 'accounts') && await Account.canEditAccountAdmins(req.user.username, mydata.id))
    ) {
      // If without permissions, exit
      return res.status(404).
        send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
    }

    const camporequisiti = UserCost.FIELDS_REQUISITI.includes(
      Object.keys(fieldsvalue)[0]);

    let allData = {};
    let username = '';
    if (mydata.table === 'users') {
      if (camporequisiti) {
        allData = {};
        allData.myuser = await User.getUserById(idapp, id);
        username = allData.myuser.username;
        if (!!allData.myuser)
          allData.precDataUser = await User.getInfoUser(idapp,
            allData.myuser.username);
        else
          allData.precDataUser = null;
        // allData.useraportador = await ListaIngresso.getUserByInvitante_Username(idapp, allData.myuser.aportador_solidario);
        // allData.precDataAportador = await getInfoUser(idapp, allData.myuser.aportador_solidario);
      }
    }

    let index = 0;

    let recoldnave = null;

    let myuser = null;
    let mydatamsg = {};

    let flotta = null;
    let strflotta = '';

    if (shared_consts.TABLES_UPDATE_LASTMODIFIED.includes(mydata.table)) {
      fieldsvalue.date_updated = new Date();
    }

    const numobj = tools.getNumObj(fieldsvalue);
    if (numobj === 1 && fieldsvalue['_id']) {
      const myrec = await mytable.findById(id);
      const myidDel = myrec['_id'];
      myrec['_id'] = fieldsvalue['_id'];
      return await mytable.insertMany(myrec).then((ris) => {
        if (ris) {
          return mytable.deleteMany({ _id: myidDel }).then((risdel) => {
            return res.send({ code: server_constants.RIS_CODE_OK, msg: '' });
          });
        } else {
          return res.status(404).send();
        }
      });
    }

    const updatebot = UserCost.FIELDS_UPDATE_TELEGRAM_BOT.includes(Object.keys(fieldsvalue)[0]);

    tools.refreshAllTablesInMem(idapp, mydata.table, updatebot, username);

    if (mydata.table === shared_consts.TAB_SETTINGS) {
      if (shared_consts.KEY_TO_CRYPTED.includes(fieldsvalue.key)) {
        fieldsvalue.crypted = true;
        fieldsvalue.value_str = tools.cryptdata(fieldsvalue.value_str);
      }
    }

    if (mydata.table === shared_consts.TAB_SITES) {
      if (shared_consts.SITES_KEY_TO_CRYPTED in fieldsvalue) {
        fieldsvalue[shared_consts.SITES_KEY_TO_CRYPTED] = tools.cryptdata(
          fieldsvalue[shared_consts.SITES_KEY_TO_CRYPTED]);
      }

    }

    let precRec = null

    if (mydata.table === 'accounts') {
      precRec = await mytable.findById(id);
    }

    return await mytable.findByIdAndUpdate(id, { $set: fieldsvalue }).
      then(async (rec) => {
        // tools.mylogshow(' REC TO MODIFY: ', rec);
        if (!rec) {
          return res.status(404).send();
        } else {
          let addmsg = '';

          if (mydata.notifBot) {
            // Send Notification to the BOT
            await telegrambot.sendMsgTelegram(idapp, mydata.notifBot.un,
              mydata.notifBot.txt);
            if (!!addmsg)
              await telegrambot.sendMsgTelegram(idapp, mydata.notifBot.un,
                addmsg);
            let addtext = '[Msg Inviato a ' + mydata.notifBot.un + ']:' +
              '\n' +
              mydata.notifBot.txt;
            telegrambot.sendMsgTelegramToTheManagers(idapp, addtext, true);

            if (!!flotta)
              tools.writeFlottaLog(idapp, addtext, flotta.riga,
                flotta.col_prima);
          }

          if (mydata.table === 'accounts') {
            let msg = '';
            if (rec.circuitId)
              circuit = await Circuit.getCircuitByCircuitId(rec.circuitId);

            let dest = rec.groupname ? rec.groupname : rec.username;
            let valprec = 0

            if ('saldo' in fieldsvalue) {
              valprec = precRec && precRec.saldo ? precRec.saldo : 0
              msg = i18n.__('SALDO_VARIATO', circuit.name, req.user.username, dest, valprec, fieldsvalue.saldo, circuit.symbol);
            } else if ('fidoConcesso' in fieldsvalue) {
              valprec = precRec && precRec.fidoConcesso ? precRec.fidoConcesso : 0
              msg = i18n.__('FIDOCONCESSO_VARIATO', circuit.name, req.user.username, dest, valprec, fieldsvalue.fidoConcesso, circuit.symbol);
            } else if ('qta_maxConcessa' in fieldsvalue) {
              valprec = precRec && precRec.qta_maxConcessa ? precRec.qta_maxConcessa : 0
              msg = i18n.__('QTAMAX_VARIATO', circuit.name, req.user.username, dest, valprec, fieldsvalue.qta_maxConcessa, circuit.symbol);
            }

            if (msg) {
              telegrambot.sendMsgTelegramToTheManagers(idapp, msg);
              telegrambot.sendMsgTelegramToTheAdminsOfCircuit(idapp, circuit.path, msg);
            }
          }


          if (mydata.table === 'users') {

            if ('profile.resid_province' in fieldsvalue) {
              const card = fieldsvalue.hasOwnProperty('profile.resid_card') ? fieldsvalue['profile.resid_card'] : '';
              // Controlla se esiste il Circuito di questa provincia, se non esiste lo crea!
              await Circuit.createCircuitIfNotExist(req, idapp, fieldsvalue['profile.resid_province'], card);
            }

            if (camporequisiti) {
              await User.checkIfSbloccatiRequisiti(idapp, allData, id);
            }

            if ('aportador_solidario' in fieldsvalue) {
              let ind_order_ingr = mydata.ind_order_ingr;
              // SERVE SE CI METTO LE MINUSCOLE/MAIUSCOLE SBAGLIATE in invitante_username!
              const myuserfound = await User.findByUsername(idapp,
                fieldsvalue.aportador_solidario, false);
              if (!!myuserfound) {
                if (!!myuserfound._id && !myuserfound.deleted) {
                  const aportador = await User.getUsernameById(idapp,
                    myuserfound._id);
                  fieldsvalue.aportador_solidario = aportador;
                  //Aggiorna record !
                  await mytable.findByIdAndUpdate(id, { $set: fieldsvalue });

                }
              } else {
                res.send(
                  {
                    code: server_constants.RIS_CODE_ERR,
                    msg: 'Non aggiornato',
                  });
                res.status(400).send();
                return false;
              }
            } else if ('deleted' in fieldsvalue) {
              let msg = '';
              if (fieldsvalue.deleted)
                msg = 'cancellato (nascosto)';
              else
                msg = 'Ripristinato';

              await telegrambot.sendMsgTelegramToTheManagers(idapp,
                `L\'utente ` + tools.getNomeCognomeEUserNameByUser(rec) +
                ` è stato ${msg} da ` +
                tools.getNomeCognomeEUserNameByUser(req.user));
            }
          }

          if (tools.ModificheConsentite(mydata.table, fieldsvalue)) {
            let msg = '';
            if (mydata.table === 'users') {
              if ('aportador_solidario' in fieldsvalue) {
                const nomecognomenuovo = await User.getNameSurnameByUsername(
                  idapp,
                  fieldsvalue.aportador_solidario);
                const nomecognomeas = await User.getNameSurnameByUsername(
                  idapp,
                  rec.aportador_solidario);
                msg = `Variato l'invitante di ` +
                  tools.getNomeCognomeEUserNameByUser(rec) +
                  '\nmodificato da ' +
                  tools.getNomeCognomeEUserNameByUser(req.user) +
                  ' \n' +
                  'Prima: ' + nomecognomeas + ' (' +
                  rec.aportador_solidario +
                  ')\n' +
                  'Dopo: ' + nomecognomenuovo + ' (' +
                  fieldsvalue.aportador_solidario + ') ]';

                // Metti l'iniziale
                if (!await User.AportadorOrig(id)) {
                  await mytable.findByIdAndUpdate(id,
                    { $set: { aportador_iniziale: fieldsvalue.aportador_solidario } },
                    { new: false });
                }
              }

            }

            if (msg !== '')
              telegrambot.sendMsgTelegramToTheManagers(idapp, msg);
          }

          res.send({ code: server_constants.RIS_CODE_OK, msg: '' });

        }

      }).
      catch((e) => {
        tools.mylogserr('Error patch USER: ', e.message);
        res.status(400).send();
      });
  } catch (e) {
    tools.mylogserr('Error chval: ', e.message);
    res.status(400).send();
  }

});

router.patch('/askfunz', authenticate, async (req, res) => {
  // const idapp = req.body.idapp;
  const id = req.body.data.id;
  // const ind_order = req.body.data.ind_order;
  // const username = req.body.data.username;
  const idapp = req.user.idapp;
  const mydata = req.body.data;

  let entra = false;
  if (!entra) {
    // If I change my record...
    if ((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) &&
      !User.isFacilitatore(req.user.perm)) && (req.user._id.toString() !== id)) {
      // If without permissions, exit
      return res.status(404).
        send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
    }
  }

  if (mydata.myfunc === shared_consts.CallFunz.DAMMI_PRIMO_UTENTE_LIBERO) {
    const userfree = await Graduatoria.getFirstUserGradFree(idapp);

    if (!!userfree)
      return res.send({ code: server_constants.RIS_CODE_OK, out: userfree });
    /*} else if (mydata.myfunc === shared_consts.CallFunz.GET_VALBYTABLE) {
      const mytable = globalTables.getTableByTableName(mydata.table);
      const coltoshow = {
        [mydata.coltoshow]: 1
      };

      const ris = await mytable.findOne({ _id: id }, coltoshow);

      return ris;
    } else if (mydata.myfunc === shared_consts.CallFunz.SET_VALBYTABLE) {
      const mytable = globalTables.getTableByTableName(mydata.table);
      const value = mydata.value;
      const coltoset = {
        [mydata.coltoshow]: value
      };

      const ris = await mytable.findOneAndUpdate({ _id: id }, { $set: coltoset }, { new: false });
      if (!!ris)
        return res.send({ code: server_constants.RIS_CODE_OK });*/
  }

  return res.send({ code: server_constants.RIS_CODE_ERR });

});

router.patch('/callfunz', authenticate, async (req, res) => {
  // const idapp = req.body.idapp;
  const id = req.body.data.id;
  // const ind_order = req.body.data.ind_order;
  const username = req.body.data.username;
  const idapp = req.user.idapp;
  const mydata = req.body.data;

  // const telegrambot = require('../telegram/telegrambot');

  try {
    let entra = false;
    if (mydata.myfunc === shared_consts.CallFunz.AGGIUNGI_NUOVO_IMBARCO ||
      mydata.myfunc === shared_consts.CallFunz.CANCELLA_IMBARCO) {
      entra = true;
    }
    if (!entra) {
      // If I change my record...
      if ((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) &&
        !User.isFacilitatore(req.user.perm)) && (req.user._id.toString() !== id)) {
        // If without permissions, exit
        return res.status(404).
          send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
      }
    }

    let myuser = await User.findOne({ idapp, username });

    let fieldsvalue = {};

    if (mydata.myfunc === shared_consts.CallFunz.ZOOM_GIA_PARTECIPATO) {

      if (!!myuser.username) {
        let FormDaMostrare = telegrambot.getFormDaMostrare(idapp, mydata.myfunc,
          myuser);

        await telegrambot.sendMsgTelegramToTheManagers(idapp,
          `L\'utente ${myuser.name} ${myuser.surname} (${myuser.username}) ha detto di aver già visto lo Zoom di Benvenuto`,
          false, FormDaMostrare);

        const ris = await User.findByIdAndUpdate(myuser.id,
          { $set: { 'profile.ask_zoom_partecipato': true } });
        if (ris)
          return res.send({ code: server_constants.RIS_CODE_OK, msg: '' });
      }
    }

    return res.send({ code: server_constants.RIS_CODE_ERR });

  } catch (e) {
    console.log(e.message);
    res.status(400).send();
  }
});

router.get('/copyfromapptoapp/:idapporig/:idappdest', async (req, res) => {
  // const idapporig = req.params.idapporig;
  // const idappdest = req.params.idappdest;
  // if (!idapporig || !idappdest)
  //   res.status(400).send();
  //
  // const mytablesstr = ['settings', 'users', 'templemail'];
  //
  // try {
  //   let numrectot = 0;
  //   for (const table of mytablesstr) {
  //     const mytable = globalTables.getTableByTableName(table);
  //
  //     tools.mylogshow('copyfromapptoapp: ', table, mytable);
  //
  //     await mytable.DuplicateAllRecords(idapporig, idappdest).then((numrec) => {
  //       // tools.mylogshow(' REC TO MODIFY: ', rec);
  //       numrectot += numrec
  //     });
  //   }
  //
  //   res.send({ code: server_constants.RIS_CODE_OK, msg: '', numrectot });
  //
  // } catch (e) {
  //   tools.mylogserr('Error copyfromapptoapp: ', e);
  //   res.status(400).send();
  // }
});

router.delete('/delrec/:table/:id', authenticate, async (req, res) => {
  const id = req.params.id;
  // const idapp = req.user.idapp;
  const tablename = req.params.table;
  // let notifBot = false;
  // const idapp = req.body.idapp;

  console.log('id', id, 'table', tablename);

  const mytable = globalTables.getTableByTableName(tablename);

  const fields = { 'ALL': 1 };

  if ((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm)) &&
    (tablename !== 'extralist') &&
    !tools.ModificheConsentite(tablename, fields, id, req.user)) {
    // If without permissions, exit
    return res.status(404).
      send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
  }

  let cancellato = false;

  //++Tools: Notify...
  tools.NotifyIfDelRecord(tablename);

  if (!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm)) {
    if (tablename === 'users') {

      let fieldsvalue = {
        deleted: true,
        date_deleted: new Date(),
      };

      await mytable.findByIdAndUpdate(id, { $set: fieldsvalue });

      cancellato = true;
    }
  }

  let ris = null;

  if (!cancellato) {
    // ELIMINA VERAMENTE IL RECORD !!!
    ris = await mytable.findByIdAndRemove(id).then((rec) => {
      if (!rec) {
        // res.status(404).send();
        return false;
      }

      if (tablename === shared_consts.TAB_MYGROUPS) {
        // Se è un gruppo, allora cancella anche tutti i suoi riferimenti
        User.removeAllUsersFromMyGroups(rec.idapp, rec.groupname);
      } else if (tablename === shared_consts.TAB_MYCIRCUITS) {
        // Se è un gruppo, allora cancella anche tutti i suoi riferimenti
        User.removeAllUsersFromMyCircuits(rec.idapp, rec.name);
      }

      tools.refreshAllTablesInMem(rec.idapp, tablename, true, rec.username);

      cancellato = true;

      tools.mylog('DELETED ', rec._id);

      return true;

    }).catch((e) => {
      console.log(e.message);
      res.status(400).send();
    });
  }

  if (cancellato) {
    // Do extra things after deleted
    //let ris2 = await actions.doOtherlasThingsAfterDeleted(tablename, myrec, notifBot, req);
    if (!!ris) {
      return res.send({ code: server_constants.RIS_CODE_OK, msg: '' });
    }
  }

  res.send({ code: server_constants.RIS_CODE_ERR, msg: '' });
  return ris;

});

router.post('/duprec/:table/:id', authenticate, async (req, res) => {
  const id = req.params.id;
  const tablename = req.params.table;
  // const idapp = req.body.idapp;

  console.log('id', id, 'table', tablename);

  const mytable = globalTables.getTableByTableName(tablename);

  if (!req.user) {
    return res.status(404).
      send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
  }

  /* if (!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm)) {
    // If without permissions, exit
    return res.status(404).
      send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
  } */

  return await mytable.findById(id).then(async (mydata) => {

    const datadup = tools.CloneRecordToNew(mydata);
    const mynewrec = new mytable(datadup);

    return await mynewrec.save().then(async (rec) => {
      if (!rec) {
        return res.status(404).send();
      }

      tools.mylog('DUPLICATED ', rec);

      // Do extra things after deleted
      return await actions.doOtherThingsAfterDuplicated(tablename, rec).
        then(({ myrec }) => {
          // ...
          mytable.findById(myrec._id).then((record) => {
            return res.send(
              { code: server_constants.RIS_CODE_OK, record, msg: '' });
          });

        });

    }).catch((e) => {
      console.error(e.message);
      res.status(400).send();
    });
  });

});

router.get('/loadsite/:userId/:idapp', authenticate_noerror, (req, res) => {
  load(req, res, '0');
});

router.get('/loadsite/:userId/:idapp/:vers', authenticate_noerror,
  (req, res) => {
    let versionstr = req.params.vers;

    let version = tools.getVersionint(versionstr);

    load(req, res, version);

  });

function load(req, res, version) {
  const userId = req.params.userId;
  const idapp = req.params.idapp;

  if (!version) {
    version = '0';
  }

  let gestoredelSito = '0';
  if (!!req.user) {
    gestoredelSito = (User.isAdmin(req.user.perm) ||
      User.isManager(req.user.perm) ||
      User.isEditor(req.user.perm)) ? '1' : '0';
  }

  // var category = req.params.category;

  // tools.mylog('loadsite : ', req.params);

  let bookedevent = [];
  // let msgs = [];

  let socioresidente = false;

  if (!!req.user)
    socioresidente = req.user.profile.socioresidente;

  if (userId !== '0') {
    // LOGGED WITH USERID
    bookedevent = Booking.findAllByUserIdAndIdApp(userId, idapp,
      gestoredelSito);
  }

  // Extract all the todos of the userId only
  const eventlist = MyEvent.findAllIdApp(socioresidente, idapp);
  const operators = Operator.findAllIdApp(idapp);
  const internalpages = MyPage.findInternalPages(idapp);
  const wheres = Where.findAllIdApp(idapp);
  const contribtype = Contribtype.findAllIdApp(idapp);
  const paymenttype = PaymentType.findAllIdApp(idapp);
  const disciplines = Discipline.findAllIdApp(idapp);
  const myelems = MyElem.findAllIdApp(idapp);
  const settings = Settings.findAllIdApp(idapp, false, false);

  const permissions = Permission.findAllIdApp();

  // const versionstr = User....
  // let version = tools.getVersionint(versionstr);

  let newstosent = Promise.resolve([]);
  let mailinglist = Promise.resolve([]);
  let mypage;
  if (version > 91)
    mypage = MyPage.findOnlyStruttRec(idapp);
  else
    mypage = MyPage.findAllIdApp(idapp);
  let calzoom = CalZoom.findAllIdApp(idapp);

  let gallery = Promise.resolve([]);
  if (gestoredelSito) {
    gallery = Gallery.findAllIdApp(idapp);
  }

  let producers = Producer.findAllIdApp(idapp);
  let groups = Group.findAllIdApp(idapp);

  // ....
  let resps = User.getusersRespList(idapp);
  let workers = User.getusersWorkersList(idapp);
  let storehouses = Storehouse.findAllIdApp(idapp);
  let departments = Department.findAllIdApp(idapp);
  let categories = Category.findAllIdApp(idapp);

  // SKILLS:
  let levels = Level.findAllIdApp(idapp);
  let adtypes = AdType.findAllIdApp(idapp);
  let adtypegoods = AdTypeGood.findAllIdApp(idapp);
  let skills = Skill.findAllIdApp(idapp);
  let goods = Good.findAllIdApp(idapp);
  //let subSkills = SubSkill.findAllIdApp(idapp);
  let statusSkills = StatusSkill.findAllIdApp(idapp);
  let sectors = Sector.findAllIdApp(idapp);
  let sectorgoods = SectorGood.findAllIdApp(idapp);
  let catgrps = CatGrp.findAllIdApp(idapp);
  let site = Site.findAllIdApp(idapp);
  let mygroups = MyGroup.findAllGroups(idapp);
  let listcircuits = Circuit.findAllIdApp(idapp);
  // let cities = City.findAllIdApp(idapp);
  let provinces = Province.findAllIdApp(idapp);
  let cart = null;
  let orderscart = null;
  if (gestoredelSito) {
    newstosent = Newstosent.findAllIdApp(idapp);
  }

  let calcstat = null;
  if (req.user) {
    calcstat = User.calculateStat(idapp, req.user.username);
    cart = Cart.getCartByUserId(req.user.id, idapp);
    if (User.isManager(req.user.perm)) {
      // Prende Tutti gli Ordini !
      orderscart = OrdersCart.getOrdersCartByUserId('ALL', idapp, 0);
    } else {
      orderscart = OrdersCart.getOrdersCartByUserId(req.user.id, idapp, 0);
    }
  }
  let askedfriends = [];
  let myuserextra = null;
  if (req.user) {
    // askedfriends = User.getAskedFriendsByUsername(idapp, req.user.username);
    myuserextra = User.addExtraInfo(idapp, req.user._doc, req.user, version);
  }

  return Promise.all([
    bookedevent,
    eventlist,
    operators,
    wheres,
    contribtype,
    settings,
    permissions,
    disciplines,
    newstosent,
    mailinglist,
    mypage,
    gallery,
    paymenttype,
    calcstat,
    calzoom,
    producers,
    cart,
    storehouses,
    departments,
    orderscart,
    groups,
    resps,
    workers,
    internalpages,
    levels,
    skills, //25
    //subSkills,
    myuserextra, // 26
    sectors,  // 27
    statusSkills, //28
    // cities,
    provinces,
    catgrps,
    adtypes,
    adtypegoods,
    sectorgoods,
    goods,
    site,
    mygroups,
    listcircuits, // 37
    myelems, // 38
    categories, // 39
  ]).then((arrdata) => {
    // console.table(arrdata);
    let myuser = req.user;
    if (myuser) {
      try {
        myuser = arrdata[26];
        if (myuser) {
          myuser.password = '';
          myuser.calcstat = arrdata[13];
        }
      } catch (e) { }
    }
    if (version < 91) {
      res.send({
        bookedevent: arrdata[0],
        eventlist: arrdata[1],
        operators: arrdata[2],
        wheres: arrdata[3],
        contribtype: arrdata[4],
        settings: arrdata[5],
        permissions: arrdata[6],
        disciplines: arrdata[7],
        newstosent: arrdata[8],
        mailinglist: arrdata[9],
        mypage: arrdata[10],
        gallery: arrdata[11],
        paymenttypes: arrdata[12],
        calzoom: arrdata[14],
        producers: arrdata[15],
        cart: arrdata[16],
        storehouses: arrdata[17],
        departments: arrdata[18],
        orders: arrdata[19],
        groups: arrdata[20],
        resps: arrdata[21],
        workers: arrdata[22],
        myuser,
        internalpages: arrdata[23],
      });
    } else {
      res.send({
        bookedevent: arrdata[0],
        eventlist: arrdata[1],
        operators: arrdata[2],
        wheres: arrdata[3],
        contribtype: arrdata[4],
        settings: arrdata[5],
        permissions: arrdata[6],
        disciplines: arrdata[7],
        newstosent: arrdata[8],
        mailinglist: arrdata[9],
        mypage: arrdata[10],
        gallery: arrdata[11],
        paymenttypes: arrdata[12],
        calzoom: arrdata[14],
        producers: arrdata[15],
        cart: arrdata[16],
        storehouses: arrdata[17],
        departments: arrdata[18],
        orders: arrdata[19],
        groups: arrdata[20],
        resps: arrdata[21],
        workers: arrdata[22],
        myuser,
        internalpages: arrdata[23],
        levels: arrdata[24],
        skills: arrdata[25],
        // subSkills: arrdata[26],
        // myuser arrdata[26]
        sectors: arrdata[27],
        statusSkills: arrdata[28],
        provinces: arrdata[29],
        catgrps: arrdata[30],
        adtypes: arrdata[31],
        adtypegoods: arrdata[32],
        sectorgoods: arrdata[33],
        goods: arrdata[34],
        site: arrdata[35],
        mygroups: arrdata[36],
        listcircuits: arrdata[37],
        myelems: arrdata[38],
        categories: arrdata[39],
      });
    }

  }).catch((e) => {
    console.log(e.message);
    res.status(400).send(e);
  });

}

router.get(process.env.LINK_CHECK_UPDATES, authenticate, async (req, res) => {
  const userId = req.user._id;
  const idapp = req.query.idapp;

  // console.log("POST " + process.env.LINK_CHECK_UPDATES + " userId=" + userId);

  if (!ObjectID.isValid(userId)) {
    return res.status(404).send();
  }

  await CfgServer.find({ idapp }).then((arrcfgrec) => {

    if (!arrcfgrec)
      return res.status(404).send();

    // ++Add to Log Stat ....

    // const sall = '0';

    // msgs = SendMsg.findAllByUserIdAndIdApp(userId, req.user.username, req.user.idapp);
    let last_msgs = SendMsg.findLastGroupByUserIdAndIdApp(userId, req.user.username, idapp);
    let last_notifs = SendNotif.findLastNotifsByUserIdAndIdApp(req.user.username, idapp, 40);

    let usersList = null;

    if (req.user) {
      // If User is Admin, then send user Lists
      if (User.isAdmin(req.user.perm) || User.isEditor(req.user.perm) ||
        User.isManager(req.user.perm)) {

        // Send UsersList
        usersList = User.getUsersList(idapp);
        // usersList = null;
      }
    }

    return Promise.all([usersList, last_msgs, last_notifs]).then((arrdata) => {
      // console.table(arrdata);
      return res.send({
        CfgServer: arrcfgrec,
        usersList: arrdata[0],
        last_msgs: arrdata[1],
        last_notifs: arrdata[2],
      });
    });

  }).catch((e) => {
    console.log(e.message);
    res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e });
  });

});

router.post('/upload_from_other_server/:dir', authenticate, (req, res) => {
  // const dir = req.params.dir;
  // const idapp = req.user.idapp;

  /*
    const form = new formidable.IncomingForm();

    form.parse(req);

    const client = new ftp(process.env.FTPSERVER_HOST, process.env.FTPSERVER_PORT, process.env.FTPSERVER_USER + idapp + '@associazioneshen.it', process.env.FTPSERVER_PWD + idapp, false, 134217728);

    // SSL_OP_NO_TLSv1_2 = 134217728

    // console.log('client', client);

    form.uploadDir = folder + '/' + dir;
    try {

      form.on('fileBegin', async function (name, file){
        file.path = folder + '/' + file.name;
      });

      form.on('file', async function (name, file){
        try {
          // Create directory remote

          if (!!dir)
            await client.createDir(dir);

          const miofile = (dir) ? dir + ` / ` + file.name : file.name;
          console.log('Upload...');
          const ret = await client.upload(file.path, miofile, 755);
          console.log('Uploaded ' + file.name, 'status:', ret);
          if (!ret)
            res.status(400).send();
          else {
            // Delete file from local directory
            fs.unlinkSync(file.path);
            res.end();
          }
        }catch (e) {
          console.log('error', e);
          res.status(400).send();
        }
      });

      form.on('aborted', () => {
        console.error('Request aborted by the user');
        res.status(400).send();
      });

      form.on('error', (err) => {
        console.error('Error Uploading', err);
        res.status(400).send();
      });

    } catch (e) {
      console.log('Error', e)
    }
  */

});

function uploadFile(req, res, version) {
  // console.log('/upload dir:' + dir);
  const dir = tools.invertescapeslash(req.params.dir);
  console.log('inverted = ', dir);
  const idapp = req.user.idapp;

  const form = new formidable.IncomingForm();

  form.parse(req);

  let dirmain = '/statics';
  if (version > 0) {
    if (tools.sulServer()) {
      dirmain = '';
    } else {
      dirmain = '/public';
    }
  }

  const mydir2 = folder + '/' + dir;
  tools.mkdirpath(mydir2);
  form.uploadDir = mydir2;
  try {

    form.on('fileBegin', async function (name, file) {
      const mydir = folder + '/' + file.newFilename;
      // tools.mkdirpath(mydir);
      file.path = mydir
    });

    form.on('file', async function (name, file) {
      try {
        console.log('1) Uploading ' + file.originalFilename);
        const mydir = tools.getdirByIdApp(idapp) + dirmain +
          server_constants.DIR_UPLOAD + '/' + dir;

        // console.log('mydir', mydir);

        // Create Dir if doesn't exist:
        const rismk = tools.mkdirpath(mydir);

        let filename = file.originalFilename;
        let ext = path.extname(filename);

        //++Todo: Modifica del nomefile... da passare al frontend
        //if (mydir.includes('profile')) {
        //  filename = uuidv4() + ext;
        //}

        file.name = filename;
        let resized_img = mydir + '/' + server_constants.PREFIX_IMG + filename;

        oldpath = file.newFilename;

        let fromfile = '.' + server_constants.DIR_UPLOAD + '/' + dir + '/' + oldpath;
        let tofile = '.' + server_constants.DIR_UPLOAD + '/' + dir + '/' + file.originalFilename;
        let mydircurrent = process.cwd() + '/src/server/router/upload/' + dir;
        fromfile = mydircurrent + '/' + oldpath;
        tofile = mydir + '/' + file.originalFilename;
        let newname = tofile;
        file.path = newname;
        // console.log('fromfile', fromfile)
        // console.log('tofile', tofile);

        if (!tools.sulServer()) {
          res.end();
          return;
        }


        // Move in the folder application !
        tools.move(fromfile, tofile, (err) => {
          if (err) {
            console.log('err uploadDir:', err);
            res.status(400).send();
          } else {

            // Salva le immagini in formato compresso
            try {
              let resized_img_small = tools.extractFilePath(newname) + '/' +
                server_constants.PREFIX_IMG_SMALL +
                tools.extractFileName(newname);
              // SMALL

              // questa opzione 'failOnError' serve per risolvere l'errore (Error: VipsJpeg: Invalid SOS parameters for sequential JPEG
              sharp(newname, { failOnError: false }).
                resize(64, 64).
                withMetadata().
                toFile(resized_img_small);

              // MEDIUM
              let resized_img = tools.extractFilePath(newname) + '/' + server_constants.PREFIX_IMG + tools.extractFileName(newname);
              sharp(newname, { failOnError: false }).
                resize({
                  width: 512,
                  // height: 512,
                  //fit: sharp.fit.cover,
                  fit: sharp.fit.contain,
                  // position: sharp.strategy.entropy,
                }).withMetadata().toFile(resized_img, function (err) {

                  // console.log('3) Ridimensionata Immagine ' + newname, 'in', resized_img);

                  if (tools.isFileExists(resized_img)) {
                    // console.log('4) Cancella l \'immagine grande originale:', newname);
                    // DELETE THE ORIGINAL BIG
                    tools.delete(newname, false, () => { });

                    // console.log('5) Rinomina l\'immagine Media da', resized_img, 'a:', newname);
                    // RENAME THE MEDIUM IN THE ORIGINAL NAME
                    tools.move(resized_img, newname, (err) => {
                      if (err)
                        console.error('err', err);
                      else
                        console.log('move', newname);
                    });
                  }

                  if (err)
                    console.error('Error Upload: ', err);
                });
            } catch (e) {
              console.error('Error Upload(2) ', e);
            }
          }

          res.end();
          // console.log('res.end');
          // return res.send({filename: newname });

        });

      } catch (e) {
        console.log('error', e);
        res.status(400).send();
      }
    });

    form.on('end', function () {
      console.log('-> upload done');
    });

    form.on('aborted', () => {
      console.error('Request aborted by the user');
      res.status(400).send();
    });

    form.on('error', (err) => {
      console.error('Error Uploading', err);
      res.status(400).send();
    });

  } catch (e) {
    console.log('Error', e);
  }
}

router.post('/upload/:dir', authenticate, (req, res) => {
  return uploadFile(req, res, 0);

});

router.post('/uploadnew/:vers/:dir/', authenticate, (req, res) => {
  let versionstr = req.params.vers;
  let version = tools.getVersionint(versionstr);

  try {
    return uploadFile(req, res, version);

  } catch (e) {
    console.log('error', e);
    res.status(400).send();
  }

});

router.delete('/delfile/:vers', authenticate, (req, res) => {
  let versionstr = req.params.vers;
  let version = tools.getVersionint(versionstr);
  deleteFile(req, res, version);
});

router.delete('/delfile', authenticate, (req, res) => {
  deleteFile(req, res, 0);
});


function deleteFile(req, res, version) {
  const relativefile = req.query.filename;
  const idapp = req.user.idapp;

  if (!relativefile || relativefile.endsWith('/')) {
    res.send({ code: server_constants.RIS_CODE_OK, msg: '' });
  }

  try {
    let dirmain = '';
    if (version > 0) {
      if (!tools.sulServer()) {
        dirmain = '/public';
      }
    }

    try {
      console.log('Delete file ' + relativefile);
      // ++ Move in the folder application !
      let fullpathfile = tools.getdirByIdApp(idapp) + dirmain + '/' +
        relativefile;

      tools.delete(fullpathfile, true, (err) => {
        if (err) console.log('err', err);
        if (err === undefined || err.errno === -2)
          res.send({ code: server_constants.RIS_CODE_OK, msg: '' });
      });

    } catch (e) {
      console.log('error', e);
      res.status(400).send();
    }
  } catch (e) {
    console.log('Error', e);
  }

}

module.exports = router;
