const express = require("express");
const glob = require("glob");
const fs = require("fs-extra");
const path = require("path");
const conf = require(`${process.env.dirtown}/conf.json`);
const Odmdb = require("../models/Odmdb.js");
// Middlewares
const checkHeaders = require("../middlewares/checkHeaders");
const isAuthenticated = require("../middlewares/isAuthenticated");
const router = express.Router();


/** 
 * @api{get}/odmdb/idx/:objectname/:indexname - index Get
 * @apiGroup Odmdb
 * @apiName getIndex
 * @apiDescription Get index file for an object
 *
 * @apiParam {string} objectname  If in conf.nationObjects then object is into nationchains/ else in tribes/xtribe/objectname/idx/indexname indexname
 * @apiParam {String} indexname  name of index file in /idx/indexnamme.json 
 *
 * 
 * @apiError {json} objectNotfound the file does not exist 
 * @apiErrorExample {json}
 * HTTP/1.1 404 Not Found
   {"status":404,"ref":"Odmdb","msg":"pathnamedoesnotexist","data":{indexpath}}
 *
 * @apiSuccess {object}  indexfile content
 * @apiSuccessExample {json} Success-Response:
 * HTTP/1.1 200 OK
 * {"status":200, "ref":"Odmdb", "msg":"indexexist", "data":{indexname,content:{index file}}
 * 
 *
 */
   router.get(
    "/idx/:objectname/:indexname",
    checkHeaders,
    isAuthenticated,
    (req, res) => {
      console.log("passe");
      // indexname = objectname_key_value.json
      let objectLocation = "../../nationchains/";
      if (!conf.api.nationObjects.includes(req.params.objectname)) {
        objectLocation += `tribes/${req.session.headers.xtribe}/`;
        // check if accessright
      }
      const indexpath = `${objectLocation}/${req.params.objectname}/idx/${req.params.indexname}`;
      if (fs.existsSync(indexpath)) {
        res
          .status(200)
          .json({
            ref: "Odmdb",
            msg: "indexexist",
            data: {
              indexname: req.params.indexname,
              content: fs.readJsonSync(indexpath),
            },
          });
      } else {
        res.status(404).json({
          ref: "Odmdb",
          msg: "pathnamedoesnotexist",
          data: { indexpath },
        });
      }
    }
  );

/**
 * @api {get} /odmdb/rebuildidx/:objectname  - index refresh all
 * @apiGroup Odmdb
 * @apiName refreshAllIndex
 * @apiDescription Rebuild all index for an object, this can be usefull in case crash or any data conflict. 
 *
 * @apiParam {string} objectname Mandatory 
 *
 * @apiSuccess {object}  indexfile content
 * @apiSuccessExample {json} Success-Response:
 * HTTP/1.1 200 OK
 * {"status":200, "ref":"Odmdb", "msg":"successreindex", "data":{"indexlist":[]}}
 *
 * @apiError {json} objectNotfound the file does not exist 
 * @apiErrorExample {json}
 * HTTP/1.1 404 Not Found
   {"status":404,"ref":"Odmdb","msg":"see nationchains/model/lg/Odmdb_xx.json","data":"object to render with msg"}
 *
 */
   router.get(
    "/rebuildidx/:objectname",
    checkHeaders,
    isAuthenticated,
    (req, res) => {
      console.log("reindex");
      // check validity and accessright
      const objectPathname = conf.api.nationObjects.includes(
        req.params.objectname
      )
        ? `${conf.dirapi}/nationchains/${req.params.objectname}`
        : `${conf.dirtown}/tribes/${req.session.header.xtribe}/${req.params.objectname}`;
      //console.log(objectPathname);
      if (!fs.existsSync(objectPathname)) {
        res.status(404).json({
          status: 404,
          ref: "Odmdb",
          msg: "pathnamedoesnotexist",
          data: { indexpath: objectPathname },
        });
        return false;
      }
      if (
        conf.api.nationObjects.includes(req.params.objectname) &&
        !req.session.header.xprofils.includes("mayor")
      ) {
        res.status(403).json({
          status: 403,
          ref: "Odmdb",
          msg: "profilnotallow",
          data: { profils: "mayor" },
        });
        return false;
      }
      if (
        !conf.api.nationObjects.includes(req.params.objectname) &&
        !req.session.header.xprofils.includes("druid")
      ) {
        res.status(403).json({
          status: 403,
          ref: "Odmdb",
          msg: "profilnotallow",
          data: { profils: "druid" },
        });
        return false;
      }
      const reindex = Odmdb.idxfromitm(objectPathname, "I", {}, {}, [], {});
      res.status(reindex.status).json(reindex);
    }
  );
  


/**
 * @api {post} /odmdb/itm/:objectname - item Create
 * @apiGroup Odmdb
 * @apiName postItm
 * @apiPermission none
 * @apiDescription Add an new item (data) into a collection of objectname items. Before Check data integrity with the relevant schema.
 * Then create a new primarykey. For multilanguage return see nationchains/model/lg/Odmdb_xx.json. 
 * 
 * @apiParam {string} objectname Place where to create new item, schema and version are available in /objectname/conf.json
 * 
 * @apiBody {Object} data must pass Checkjson.js with schema
 * 
 * @apiSuccess {json}  data idxprimary Value of idxprimary into objectname collection
 * @apiSuccessExample {json} Success-Response:
 * HTTP/1.1 200 OK
 * {"status":200, "ref":"Odmdb", "msg":"cudsuccessfull", "data":{"itm":{}}}
 * 
 * @apiError {json} schemanotfound The objectname schema is not found
 * @apiError {json} pathnamedoesnotexist The objectname does not exist for the tribe
 * @apiError {json} missingprimarykey Body data must have primarykey to be created
 * @apiError {json} unconsistencyapxidx some Body data get unique key that already exist 
 * @apiError {json} checkjsonfalse The body data are not consistent with the schema 
 * @apiErrorExample {json}
 * HTTP/1.1 404 Not Found
 * {"status":404,"ref":"Odmdb","msg":"see nationchains/model/lg/Odmdb_xx.json","data":"object to render with msg"}
 *
 */
router.post("/itm/:objectname", checkHeaders, isAuthenticated, (req, res) => {
  // Create an item of an object with no specificities
  // if specificities then create a route / model that import odmdb
});
router.get(
  "/searchitems/:objectname/:question",
  checkHeaders,
  isAuthenticated,
  (req, res) => {
    /**
     *
     *
     */
    console.log(
      "route referentials get all language" +
        req.params.objectname +
        "-" +
        req.params.question
    );
    const getref = Referentials.getref(
      true,
      req.params.source,
      req.params.idref,
      req.session.header.xworkon,
      req.session.header.xlang
    );
    // Return any status the data if any erreur return empty object
    res.jsonp(getref.payload.data);
  }
);

/**
 * @api {get} /odmdb/itm/:objectname/:primaryindex - item Get
 * @apiGroup Odmdb
 * @apiName getItemFromId
 * @apiDescription Get itm for a primaryid of an object
 *
 * @apiParam {String} objectname name Mandatory if in conf.nationObjects then file is into nationchains/ else in /nationchains/tribes/xtribe/objectname
 * @apiParam {String} primaryindex the unique id where item is store
 *
 * @apiError {json} objectNotfound the file item does not exist
 * @apiErrorExample {json}
 * HTTP/1.1 404 Not Found
 *  {"status":404,"ref":"Odmdb","msg":"doesnotexist","data":{"objectname":"objectname","key":"apxid","val":"primaryindex"}}
 *
 * @apiSuccess {object}  indexfile content
 * @apiSuccessExample {json} Success-Response:
 * HTTP/1.1 200 OK
 * {"status":200, "ref":"Odmdb", "msg":"indexexist", "data":{"indexname","content":{itm file}}
 *
 *
 */
// indexname = objectname_key_value.json
router.get(
  "/itm/:objectname/:primaryindex",
  checkHeaders,

  isAuthenticated,
  (req, res) => {
    const objectName = req.params.objectname;
    const objectId = req.params.primaryindex;
    let objectLocation = "../../nationchains/";
    if (!conf.api.nationObjects.includes(objectName)) {
      objectLocation += `tribes/${req.session.headers.xtribe}/${objectName}`;
      // check if accessright on object on item
      // in case not res.status(403)
    }
    const objectpath = `${objectLocation}/${objectName}/itm/${objectId}`;

    if (fs.existsSync(objectpath)) {
      res.status(200).json({ data: fs.readJsonSync(objectpath) });
    } else {
      res.status(404).json({
        ref: "Odmdb",
        msg: "objectfiledoesnotexist",
        data: { objectpath },
      });
    }
  }
);
/**
 * @api {get} https://wall-ants.ndda.fr/Checkjson.js  - schema check data lib
 * @apiGroup Odmdb
 * @apiName checkjsonjs
 * @apiDescription Public js lib to import in a browser by :<br>
 * ```<script src="wall-ants.ndda.fr/nationchains/contracts/Checkjson.js"></script>```
 * to import in a node.js:<br>
 * ```const Checkjson = require(`Checkjson.js`);```
 * 
 *  with functions:<br>
 *  <strong>Checkjson.schema.validation(schema)</strong> that return<br>
 *     - {status:200, ref:"Checkjson", msg:"validcheck"} => all rules are correct<br>
 *     - {status:406, multimsg:[{ref:"Checkjson",msg:"errorkey",data:{}}]}<br>
 *
 *  <strong>Checkjson.schema.data(schema{json},data{json},withschemacheck{boolean})</strong> that return<br>
 *     - {status:200, ref:"Checkjson", msg:"validcheck"} => all data keys respect schema rules <br>
 *     - {status:417, multimsg:[{ref:"Checkjson",msg:"errorkey",data:{}}]}<br>
 * 
 * To identify issues, get the language errorkey list with a get
 *   https://wall-ants.ndda.fr/nationchains/models/Checkjson_lg.json  
 * 
 */



/**
 * @api {get} https://wall-ants.ndda.fr/nationchains/schema/:objectname - schema Get public 
 * @apiGroup Odmdb
 * @apiName getPublicSchema
 * @apiDescription Get a Schema model from public apxtrib (nations, pagans,persons,towns, tribes,wwws)
 * @apiSuccess {json} contain json file
 * @apiSuccessExample {json} Fichier direct
 * HTTP/1.1 200 Success-response:
  {
  "$id": "https://smatchit.io/schema/pagan",
  "$comment": "To create account bin apxtrib",
  "title": "Pagans identity",
  "description": "A numeric id in the nationchains world",
  "type": "object",
  "properties": {
    "publickey": {
      "title": "Alias's publickey",
      "description": "Public key generate with openpgp.js",
      "type": "string",
      "format": "pgppublickey"
    },
    "alias": {
      "title": "Alias",
      "description": "text to remember easily a public key",
      "type": "string",
      "minLength": 4,
      "pattern": "^[a-z0-9]*$"
    },
    "dt_delete": {
      "title": "Date of death",
      "description": "Date of alias delete request, your will will be apply",
      "type": "string",
      "format": "date-time"
    },
    "will": {
      "title": "Will script after death",
      "description": "This will script will be apply on your data 30 days after your death",
      "type": "string"
    }
  },
  "required": ["publickey", "alias"],
  "apxid": "alias",
  "apxuniquekey": ["publickey"],
  "apxidx": [
    { "name": "lst_alias", "keyval": "alias" },
    { "name": "alias", "keyval": "alias" }
  ],
  "apxaccessrights": {
    "owner": { "R": [], "D": [] },
    "anonymous": { "C": [], "R": ["alias"] },
    "pagan": { "R": ["alias", "publickey"] }
  }
}

 * @apiError {json} contain json file
 * @apiErrorExample {string} nginx html not found message
 * HTTP/1.1 404 Not Found
 * <html>...</html>
**/

/**
 * @api {get} /odmdb/schema/:objectname  - schema Get private
 * @apiGroup Odmdb
 * @apiName getPrivateSchema
 * @apiDescription Get a private (profil must have accessright R on object) to a Schema model 
 *
 * @apiParam {String} objectname Mandatory
 *
 * @apiError {object} ref objectmodel to get in the right language
 * @apiErrorExample {json} Error-response:
 * HTTP/1.1 404 Not Found
 * {"status":404,"ref":"Odmdb","msg":"schemanotfound","data":{"fullpath"}}
 *
 * @apiSuccess {object} data contains schema requested
 * @apiSuccessExample {json} Success-Response: 
 * HTTP/1.1 200 Success-response:
 * {"status":200,"data":{schema}}
 */
router.get("schema/:objectname", checkHeaders, isAuthenticated, (req, res) => {
  const fullpath = path.resolve(
    `${__dirname}/tribes/${req.session.header.xworkon}/schema/${req.params.pathobjectname}.json`
  );
  if (fs.existsSync(fullpath)) {
    res.status(200).json({ data: fs.readJsonSync(fullpath) });
  } else {
    res
      .status(404)
      .json({ status:404, msg: "schemanotfound", ref: "odmdb", data: { fullpath } });
  }
});

/**
 * @api {put} /odmdb/schema/:objectname - schema Put
 * @apiGroup Odmdb
 * @apiName putSchema
 * @apiDescription Replace a schema by another one need druid profil for a tribe
 *
 * @apiParam {String} objectname Mandatory
 *
 * @apiBody {string} schemapath where to store schema .../schema
 * @apiBody {string} objectpath where to store object ...objectname/idx/conf.json
 * @apiBody {json} schema content
 * @apiBody {json} schemalang content in lg
 * @apiBody {string} lang define which schemalg is (2 letters)
 *
 * @apiError {object} ref objectmodel to get in the right language
 * @apiErrorExample {json} Error-response:
 * HTTP/1.1 404 Not Found
 * {"status":404,"ref":"Odmdb","msg":"schemanotfound","data":{"fullpath"}}
 *
 * @apiSuccess {object} data contains schema requested
 * HTTP/1.1 200 Success-response:
 * {"status":200,"data":{schema}}
 *
 *
 */
router.put("schema/:objectname", checkHeaders, isAuthenticated, (req, res) => {
  const fullpath = path.resolve(
    `${__dirname}/tribes/${req.session.header.xworkon}/schema/${req.params.pathobjectname}.json`
  );
  const set = Odmdb.setObject(
    path.resolve(`${__dirname}/tribes/${req.session.header.xworkon}`)
  );

  if (fs.existsSync(fullpath)) {
    res.status(200).json({ data: fs.readJsonSync(fullpath) });
  } else {
    res
      .status(404)
      .json({ msg: "schemanotfound", ref: "odmdb", data: { fullpath } });
  }
});


/**
 * @api {get} https://wall-ants.ndda.fr/nationchains/models/:modelname_lg.json - translation notif Get public 
 * @apiGroup Odmdb
 * @apiName getPublicModelmessagekey 
 * @apiDescription Get a public json object for the ref: modelname in language lg, to get a template description with key msg
 * @apiParam {string} modelname Mandatory
 * @apiSuccess {json} contain json file
 * @apiSuccessExample {json} Fichier direct
 * HTTP/1.1 200 Success-response:
 *  {
  "alreadyexist": "Un object {{objectname}} avec la clé {{key}} existe déjà avec {{val}}",
  "doesnotexist": "L'object {{objectname}} avec la clé {{key}} ,'existe pas avec {{val}}",
  "getschema": "Schema {{{conf.name}}}",
  "schemanotfound": "Schema introuvable dans {{{schemaPath}}}",
  "pathnamedoesnotexist": "Le repertoire n'existe pas {{{indexpath}}}",
  "objectfiledoesnotexist": "Le fichier n'existe pas {{{objectpath}}}",
  "cudsuccessfull": "Mise à jour effectuée avec succés",
  "missingprimarykey": "Il manque une clé primaire apxid pour stocker et identifier les objects",
  "unconsistencyapxidx": "L'index {{name}} doit contenir en objkey au moins {{apxid}} car keyval n'est pas unique",
  "profilnotallow": "Vous n'avez pas le profil de {{profils}}, cette action n'est pas authorisée",
  "successreindex": "Objet reindexé à partir des items, vos index sont à jour",
  "indexexist":"L'indexe existe"
}

 * @apiError {json} contain json file
 * @apiErrorExample {string} nginx html not found message
 * HTTP/1.1 404 Not Found
 * <html>...</html>
**/

module.exports = router;
