var libFS = require("fs");

fcf.module({
  name: "fcf:NServer/NControllers/Receive.js",
  dependencies: ["fcf:NServer/NControllers/Controller.js"],
  module: function(Controller) {
    fcf.prepareObject(fcf, "NServer.NControllers");

    fcf.NServer.NControllers.Receive = class Receive extends Controller{

      constructor(a_options) {
        super(a_options);
        this.userImportance = true;
      }

      action(a_request) {
        let self = this;
        let context = fcf.getContext();
        var template = a_request.getRouteData().args.template;
        if (!template){
          a_request.sendErrorPage(new fcf.Exception("ERROR_REQUEST_PARAMETER_NOT_SET", ["template"]));
          return;
        }

        var part     = template.split("+")[1];
            template = template.split("+")[0];
        var extPos = template.indexOf(".tmpl");
        if (extPos == -1){
          a_request.sendErrorPage(new fcf.Exception("ERROR_REQUEST_PARAMETER_NOT_VALID", [template]));
          return;
        }
        var handlerFile = template.substr(0, extPos);
        if (part)
          handlerFile += "+" + part + ".receive.js";
        else
          handlerFile += ".receive.js";
        var realHandlerFile = fcf.getPath(handlerFile);

        libFS.access(realHandlerFile, libFS.F_OK, (err) => {
          fcf.setContext(context);
          if (err) {
            a_request.sendError(new fcf.Exception("ERROR_READ_NOT_FILE", [handlerFile]));
            return
          }
          fcf.requireEx([realHandlerFile], function(a_error, Handler){
            if (a_error){
              a_request.sendError(a_error);
              return;
            }

            let handler = new Handler();

            if (typeof handler !== "object" || typeof handler.receive !== "function"){
              a_request.sendError(new fcf.Exception("ERROR_INCORRECT_FORMAT_HANDLER", {file: handlerFile}));
              return;
            }

            fcf.actions()
            .then(()=>{
              //check access
              return fcf.application.getRender().getLoader().load(template);
            })
            .then((a_res)=>{
              let formData = a_request.getFormData();
              let fileAttributes = formData.fileAttributes;
              let files = [];
              let fields = {};
              let formFiles = a_request.getFiles();
              for(var i = 0; true; ++i){
                if (!formFiles || !formFiles["files[" + i + "]"])
                  break;
                let file = formFiles["files[" + i + "]"];
                files.push({
                  size:       file.size,
                  path:       file.path,
                  name:       file.name,
                  type:       file.type,
                  mtime:      file.mtime,
                  attributes: file.attributes
                });
              }
              try {
                fields = !fcf.empty(formData.data) ? JSON.parse(formData.data) : {};
              } catch (a_error) {
                a_request.sendError(a_error);
                return;
              }
              var attributes = [];
              if (formData.filesAttributes){
                try {
                  attributes = JSON.parse(formData.filesAttributes);
                } catch (a_error) {
                  a_request.sendError(a_error);
                  return;
                }
                for(var i = 0; i < files.length; ++i)
                  files[i].attributes = attributes[i] ? attributes[i] : {};
              }

              for(var i = 0; i < files.length; ++i){
                if (files[i].attributes && files[i].attributes.objectPath){
                  let ptr = fcf.resolveEx(fields, files[i].attributes.objectPath, true);
                  ptr.object[ptr.key] = files[i];
                }
              }

              for(var i = 0; i < files.length; ++i)
                if (files[i].attributes.filename)
                  files[i].name = files[i].attributes.filename;

              try {
                fcf.setContext(context);
                let error = undefined;
                let res   = undefined;
                try {
                  res = handler.receive(fields, files, a_request);
                } catch(e){
                  error = e;
                }
                if (error){
                  a_request.sendError(error);
                } else if (res instanceof Promise || res instanceof fcf.Actions){
                  res.then((a_result)=>{
                    a_request.send(a_result);
                  })
                  .catch((a_error)=>{
                    a_request.sendError(a_error);
                  });
                } else {
                  a_request.send(res);
                }
              } catch (a_error) {
                a_request.sendError(a_error);
                return;
              }
            })
            .catch((a_error)=>{
              a_request.sendError(a_error);
            })
          });
        })
      }
    }

    return fcf.NServer.NControllers.Receive;
  }
});

