/*
 *  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 "context.h"
#include "biniou.h"
#include "defaults.h"


extern uint64_t frames;
extern uint8_t  encoding;


json_t *
Context_get_state(const Context_t *ctx)
{
  json_t *res = json_object();
  json_t *seq;
  int colormaps_min, colormaps_max;
  int images_min, images_max;
  int sequences_min, sequences_max;
#ifdef WITH_WEBCAM
  int webcams_min, webcams_max;
#endif

  json_object_set_new(res, "version", json_string(LEBINIOU_VERSION));
#ifdef ULFIUS_VERSION_STR
  json_object_set_new(res, "ulfius", json_string(ULFIUS_VERSION_STR));
#endif
  seq = Sequence_to_json(ctx, ctx->sm->cur, 1, 0, (NULL == ctx->sm->cur->name) ? UNSAVED_SEQUENCE : ctx->sm->cur->name);

  biniou_get_delay(BD_COLORMAPS, &colormaps_min, &colormaps_max);
  biniou_get_delay(BD_IMAGES, &images_min, &images_max);
  biniou_get_delay(BD_SEQUENCES, &sequences_min, &sequences_max);
#ifdef WITH_WEBCAM
  biniou_get_delay(BD_WEBCAMS, &webcams_min, &webcams_max);
#endif

  json_object_set_new(res, "selectedPlugin", json_string(plugins->selected->name));
  json_object_set_new(res, "selectedPluginDname", json_string(plugins->selected->dname));
  json_object_set_new(res, "sequence", seq);
  json_object_set_new(res, "randomSchemes", json_boolean((ctx->random_mode == BR_SCHEMES) || (ctx->random_mode == BR_BOTH)));
  json_object_set_new(res, "randomSequences", json_boolean((ctx->random_mode == BR_SEQUENCES) || (ctx->random_mode == BR_BOTH)));
  json_object_set_new(res, "autoColormaps", json_boolean(ctx->auto_colormaps));
  json_object_set_new(res, "autoColormapsMode", json_string(Shuffler_mode2str(ctx->cf->shf->mode)));
  json_object_set_new(res, "autoImages", json_boolean(ctx->auto_images));
  if (NULL != ctx->imgf) {
    json_object_set_new(res, "autoImagesMode", json_string(Shuffler_mode2str(ctx->imgf->shf->mode)));
  }
  json_object_set_new(res, "colormapsMin", json_integer(colormaps_min));
  json_object_set_new(res, "colormapsMax", json_integer(colormaps_max));
  json_object_set_new(res, "imagesMin", json_integer(images_min));
  json_object_set_new(res, "imagesMax", json_integer(images_max));
  json_object_set_new(res, "autoSequencesMode", json_string(Shuffler_mode2str(sequences->shuffler->mode)));
  json_object_set_new(res, "sequencesMin", json_integer(sequences_min));
  json_object_set_new(res, "sequencesMax", json_integer(sequences_max));
#ifdef WITH_WEBCAM
  json_object_set_new(res, "autoWebcams", json_boolean(ctx->auto_webcams));
  json_object_set_new(res, "webcamsMin", json_integer(webcams_min));
  json_object_set_new(res, "webcamsMax", json_integer(webcams_max));
  json_object_set_new(res, "webcams", json_integer(ctx->webcams));
  if (ctx->webcams > 1) {
    json_object_set_new(res, "autoWebcamsMode", json_string(Shuffler_mode2str(ctx->webcams_shuffler->mode)));
  }
#endif
  json_object_set_new(res, "width", json_integer(WIDTH));
  json_object_set_new(res, "height", json_integer(HEIGHT));
  json_object_set_new(res, "maxFps", json_integer(ctx->max_fps));
  if (NULL != ctx->locked) {
    json_object_set_new(res, "lockedPlugin", json_string(ctx->locked->name));
  } else {
    json_object_set_new(res, "lockedPlugin", json_null());
  }

  json_object_set_new(res, "bankSet", json_integer(ctx->bank_set));
  json_object_set_new(res, "bank", json_integer(ctx->bank));
  json_object_set_new(res, "banks", Context_get_bank_set(ctx, ctx->bank_set));

  json_object_set_new(res, "volumeScale", json_real(Context_get_volume_scale(ctx)));
  json_object_set_new(res, "fadeDelay", json_real(fade_delay));
  json_object_set_new(res, "params3d", Params3d_to_json(&ctx->params3d));
  if (NULL != ctx->input_plugin) {
    json_object_set_new(res, "inputPlugin", json_string(ctx->input_plugin->name));
    json_object_set_new(res, "mute", json_boolean(ctx->input->mute));
  } else {
    json_object_set_new(res, "inputPlugin", json_null());
  }
  json_object_set_new(res, "outputPlugins", Context_output_plugins(ctx));
  json_object_set_new(res, "fullscreen", json_boolean(ctx->fullscreen));
  json_object_set_new(res, "encoding", json_boolean(encoding));
  json_object_set_new(res, "allInputPlugins", json_strtok(INPUT_PLUGINS, ","));
  json_object_set_new(res, "allOutputPlugins", json_strtok(OUTPUT_PLUGINS, ","));
  json_object_set_new(res, "rotationFactor", json_integer(ctx->params3d.rotation_factor));
  json_object_set_new(res, "layerModes", layer_modes());
  json_object_set_new(res, "shortcuts", Context_get_shortcuts(ctx));

  json_object_set_new(res, "bandpassMin", json_integer(ctx->bandpass_min));
  json_object_set_new(res, "bandpassMax", json_integer(ctx->bandpass_max));

  return res;
}


void
Context_websocket_send_colormap(Context_t *ctx)
{
  json_t *colormap = CmapFader_command_result(ctx->cf);

  bulfius_websocket_broadcast_json_message(ctx, colormap, NULL);
  json_decref(colormap);
}


void
Context_websocket_send_image(Context_t *ctx)
{
  json_t *image = ImageFader_command_result(ctx->imgf);

  bulfius_websocket_broadcast_json_message(ctx, image, NULL);
  json_decref(image);
}


void
Context_websocket_send_sequence(Context_t *ctx)
{
  Sequence_t *current = ctx->sm->cur;

  json_t *seq = Sequence_to_json(ctx, current, 1, 0, (NULL == current->name) ? UNSAVED_SEQUENCE : current->name);
  // Need to send the 3D parameters from the engine, not the sequence
  json_object_del(seq, "params3d");
  json_object_set_new(seq, "params3d", Params3d_to_json(&ctx->params3d));
  json_t *json = json_pack("{so}", "sequence", seq);
  bulfius_websocket_broadcast_json_message(ctx, json, NULL);
  json_decref(json);
}
