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{

      getRequestInfo(){
        return {
          userRequest: true,
          redirect:    false,
        };
      }

      action(a_request) {
        let self = this;
        let state = fcf.getState();
        var template = a_request.getRoute().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.setState(state);
          if (err) {
            a_request.sendError(new fcf.Exception("ERROR_READ_NOT_FILE", [handlerFile]));
            return
          }
          fcf.requireEx([realHandlerFile], function(a_error, Handler){
            if (a_error){
              fcf.log.err("FCF", "Failed load module '" + realHandlerFile + "': ", 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().loadInfo(template);
            })
            .then((a_res)=>{
              let formData = a_request.getFormData();
              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,
                  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;

              fcf.setState(state);
              return handler.receive(fields, files, a_request);
            })
            .then((a_result)=>{
              a_request.send(a_result);
            })
            .catch((a_error)=>{
              fcf.log.err("FCF", "Error in the Receive controller: ", a_error);
              a_request.sendError(a_error);
            })
          });
        })
      }
    }

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