/*
 *  Copyright 1994-2022 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "bulfius.h"
#include "context.h"
#include "plugins.h"


int
callback_post_parameters(const struct _u_request *request, struct _u_response *response, void *user_data)
{
  Context_t *ctx = user_data;
  const char *plugin = u_map_get(request->map_url, "plugin");

  assert(NULL != ctx);

  if (NULL != plugin) {
    Plugin_t *p = Plugins_find(plugin);
#ifdef DEBUG_BULFIUS_POST
    printf("%s: %s Plugin %s: %p\n", __FILE__, __func__, plugin, p);
#endif

    if (NULL != p) {
      if (NULL != p->parameters) {
#ifdef DEBUG_BULFIUS_POST
        printf("%s: %s Plugin %s has parameters\n", __FILE__, __func__, plugin);
#endif
        // plugin exists and has parameters, get them
        json_t *params = p->parameters(ctx, NULL, 0);
        json_error_t jerror;
        // parse request body
        json_t *body = ulfius_get_json_body_request(request, &jerror);

        if (NULL == body) {
          // error
          fprintf(stderr, "[!] %s: JSON error: %s\n", __FILE__, jerror.text);
          ulfius_set_string_body_response(response, 400, NULL);
        } else {
          // iterate over json post body
          const char *key;
          json_t *value;
          json_object_foreach(body, key, value) {
            json_t *p = json_object_get(params, key);
#ifdef DEBUG_BULFIUS_POST
            printf("%s: %d key= %s\n", __func__, __LINE__, key);
#endif
            if (NULL != p) {
              // get old value, will be used for type checking
              const json_t *old_value = json_object_get(p, "value");
              assert(NULL != old_value);
              json_t *new_value = NULL;

#ifdef DEBUG_BULFIUS_POST
              printf("%s: %s Plugin %s: change parameter %s\n", __FILE__, __func__, plugin, key);
#endif
              // convert new value to the right type
              if (json_is_integer(old_value)) {
                if (json_is_integer(value)) {
                  new_value = value;
                } else {
                  new_value = json_integer(xstrtol(json_string_value(value)));
                }
              } else if (json_is_real(old_value)) {
                if (json_is_real(value)) {
                  new_value = value;
                } else if (json_is_integer(value)) {
                  new_value = json_real(json_integer_value(value));
                } else {
                  new_value = json_real(xatof(json_string_value(value)));
                }
              } else if (json_is_boolean(old_value)) {
                if (json_is_boolean(value)) {
                  new_value = value;
                } else {
                  new_value = (!strcmp("true", json_string_value(value))) ? json_true() : json_false();
                }
              } else {
                assert(json_is_string(old_value));
                new_value = value;
              }

              assert(NULL != new_value);
              // update new parameter and parameters object
              json_object_set_new(p, "value", new_value);
            }
          }
          json_decref(body);
          json_t *new_params = p->parameters(ctx, params, 0);
          ulfius_set_json_body_response(response, 200, new_params);
          json_decref(new_params);
          json_decref(params);
        }
      } else {
#ifdef DEBUG_BULFIUS_POST
        printf("%s: %s Plugin %s doesn't have parameters\n", __FILE__, __func__, plugin);
#endif
        ulfius_set_string_body_response(response, 204, NULL);
      }
    } else {
#ifdef DEBUG_BULFIUS_POST
      printf("%s: %s Plugin %s not found\n", __FILE__, __func__, plugin);
#endif
      ulfius_set_string_body_response(response, 404, "Plugin not found");
    }
  } else {
#ifdef DEBUG_BULFIUS_POST
    printf("%s: %s Bad request, plugin %s\n", __FILE__, __func__, plugin);
#endif
    ulfius_set_string_body_response(response, 400, "Bad request");
  }

  return U_CALLBACK_COMPLETE;
}
