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


extern uint64_t frames;
extern uint8_t  encoding;
char *randomModes[BR_NB] = { "Off", "Sequences", "Schemes", "Mixed" };


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

  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_t *auto_modes = json_pack("{s{sb ss s[ii]} s{ss ss s[ii]}}",
                                 "colormaps",
                                 "value", ctx->auto_colormaps,
                                 "mode", Shuffler_mode2str(ctx->cf->shf->mode),
                                 "range", colormaps_min, colormaps_max,
                                 "sequences",
                                 "value", randomModes[ctx->random_mode],
                                 "mode", Shuffler_mode2str(sequences->shuffler->mode),
                                 "range", sequences_min, sequences_max
                                 );
  if (NULL != ctx->imgf) {
    json_object_set_new(auto_modes, "images", json_pack("{sb ss s[ii]}",
                                                        "value", ctx->auto_images,
                                                        "mode", Shuffler_mode2str(ctx->imgf->shf->mode),
                                                        "range", images_min, images_max));
  } else {
    json_object_set_new(auto_modes, "images", json_pack("{sb ss s[ii]}", "value", 0, "mode", "shuffle", "range", DELAY_MIN, DELAY_MAX));
  }
#ifdef WITH_WEBCAM
  json_object_set_new(auto_modes, "webcams", json_pack("{sb ss? s[ii]}",
                                                       "value", ctx->auto_webcams,
                                                       "mode", (ctx->webcams > 1) ? Shuffler_mode2str(ctx->webcams_shuffler->mode) : NULL,
                                                       "range", webcams_min, webcams_max));
#endif

  json_t *versions = json_pack("{ss ss?}",
                               "lebiniou", LEBINIOU_VERSION,
                               "ulfius",
#ifdef ULFIUS_VERSION_STR
                               ULFIUS_VERSION_STR
#else
                               NULL
#endif
                               );

  json_t *engine = json_pack("{sb sb sf so, ss? sb sb si s{ss ss so} si}",
                             "allowAutoColormaps", ctx->allow_auto_colormaps,
                             "allowAutoImages", ctx->allow_auto_images,
                             "fadeDelay", fade_delay * 1000,
                             "layerModes", layer_modes(),
                             "lockedPlugin", (NULL != ctx->locked) ? ctx->locked->name : NULL,
                             "lockColormap", ctx->lock_colormap,
                             "lockImage", ctx->lock_image,
                             "maxFps", ctx->max_fps,
                             "selectedPlugin",
                             "name", plugins->selected->name,
                             "displayName", plugins->selected->dname,
                             "parameters", (NULL != plugins->selected->parameters) ? plugins->selected->parameters(ctx, NULL, 0) : json_array(),
                             "webcams", ctx->webcams);
#ifdef WITH_WEBCAM
  json_object_set_new(engine, "lockWebcam", json_boolean(ctx->lock_webcam));
#endif

  json_t *data = json_pack("{si si si}",
                           "colormaps", colormaps->size,
                           "images", (NULL != ctx->imgf) ? images->size : 0,
                           "sequences", sequences->size);

  json_t *screen = json_pack("{sb si si sb}",
                             "fixed", FIXED_AS_BOOLEAN,
                             "width", WIDTH,
                             "height", HEIGHT,
                             "fullscreen", ctx->fullscreen);

  json_t *input = json_pack("{ss? sb sf}",
                            "name", (NULL != ctx->input_plugin) ? ctx->input_plugin->name : NULL,
                            "mute", (NULL != ctx->input) ? ctx->input->mute : 0,
                            "volumeScale", Context_get_volume_scale(ctx));

  json_t *all_sequences = json_array();
  if (NULL != sequences) {
    for (GList *seq = sequences->seqs; NULL != seq; seq = g_list_next(seq)) {
      Sequence_t *s = (Sequence_t *)seq->data;
      json_array_append_new(all_sequences, json_pack("{sI ss}", "id", s->id, "name", s->name));
    }
  }

  res = json_pack("{so so so so so so so sI si si so so so sb so so si so so}",
                  "versions", versions,
                  "engine", engine,
                  "data", data,
                  "screen", screen,
                  "input", input,
                  "sequence", Sequence_to_json(ctx, ctx->sm->cur, 1, 0, (NULL == ctx->sm->cur->name) ? UNSAVED_SEQUENCE : ctx->sm->cur->name),
                  "allSequences", all_sequences,
                  "frames", frames,
                  "bankSet", ctx->bank_set,
                  "bank", ctx->bank,
                  "banks", Context_get_bank_set(ctx, ctx->bank_set),
                  "params3d", Params3d_to_json(&ctx->params3d),
                  "outputPlugins", Context_output_plugins(ctx),
                  "encoding", encoding,
                  "allInputPlugins", json_strtok(INPUT_PLUGINS, ","),
                  "allOutputPlugins", json_strtok(OUTPUT_PLUGINS, ","),
                  "rotationFactor", ctx->params3d.rotation_factor,
                  "shortcuts", Context_get_shortcuts(ctx),
                  "auto", auto_modes);

  if (NULL != ctx->input) {
    json_object_set_new(res, "mute", json_boolean(ctx->input->mute));
  }

  return res;
}
