/*
 *  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 "globals.h"
#include "sequencemanager.h"


json_t *
SequenceManager_command(Context_t *ctx, const enum Command cmd, const char auto_colormaps, const char auto_images)
{
  SequenceManager_t *sm = ctx->sm;
  json_t *res = NULL;

  switch (cmd) {
    case CMD_SEQ_TOGGLE_LENS:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_TOGGLE_LENS\n");
#endif
      SequenceManager_toggle_lens(sm->cur);
      res = json_pack("{so}", "sequence", Sequence_to_json(ctx, sm->cur, 1, 0, (NULL == sm->cur->name) ? UNSAVED_SEQUENCE : sm->cur->name));
      break;

    case CMD_SEQ_LAYER_DEFAULT:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_LAYER_DEFAULT\n");
#endif
      SequenceManager_default_layer_mode(sm->cur);
      res = json_pack("{so}", "sequence", Sequence_to_json(ctx, sm->cur, 1, 0, (NULL == sm->cur->name) ? UNSAVED_SEQUENCE : sm->cur->name));
      break;

    case CMD_SEQ_LAYER_PREVIOUS:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_LAYER_PREVIOUS\n");
#endif
      SequenceManager_prev_layer_mode(sm->cur);
      res = json_pack("{so}", "sequence", Sequence_to_json(ctx, sm->cur, 1, 0, (NULL == sm->cur->name) ? UNSAVED_SEQUENCE : sm->cur->name));
      break;

    case CMD_SEQ_LAYER_NEXT:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_LAYER_NEXT\n");
#endif
      SequenceManager_next_layer_mode(sm->cur);
      res = json_pack("{so}", "sequence", Sequence_to_json(ctx, sm->cur, 1, 0, (NULL == sm->cur->name) ? UNSAVED_SEQUENCE : sm->cur->name));
      break;

    case CMD_SEQ_MOVE_DOWN:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_MOVE_DOWN\n");
#endif
      SequenceManager_move_selected_back(sm->cur);
      res = json_pack("{so}", "sequence", Sequence_to_json(ctx, sm->cur, 1, 0, (NULL == sm->cur->name) ? UNSAVED_SEQUENCE : sm->cur->name));
      break;

    case CMD_SEQ_MOVE_UP:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_MOVE_UP\n");
#endif
      SequenceManager_move_selected_front(sm->cur);
      res = json_pack("{so}", "sequence", Sequence_to_json(ctx, sm->cur, 1, 0, (NULL == sm->cur->name) ? UNSAVED_SEQUENCE : sm->cur->name));
      break;

    case CMD_SEQ_PARAM_DEC:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_PARAM_DEC\n");
#endif
      res = json_pack("{so}", "parameters", plugin_parameter_change(ctx, -1));
      break;

    case CMD_SEQ_PARAM_INC:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_PARAM_INC\n");
#endif
      res = json_pack("{so}", "parameters", plugin_parameter_change(ctx, +1));
      break;

    case CMD_SEQ_PARAM_DEC_FAST:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_PARAM_DEC_FAST\n");
#endif
      res = json_pack("{so}", "parameters", plugin_parameter_change(ctx, -10));
      break;

    case CMD_SEQ_PARAM_INC_FAST:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_PARAM_INC_FAST\n");
#endif
      res = json_pack("{so}", "parameters", plugin_parameter_change(ctx, +10));
      break;

    case CMD_SEQ_PARAM_PREVIOUS:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_PARAMETER_PREVIOUS\n");
#endif
      if (NULL != plugins->selected->parameters) {
        json_t *j_params = plugins->selected->parameters(ctx, NULL, 0);
        uint8_t nb_params = plugin_parameter_number(j_params);

        json_decref(j_params);

        /* authorized underflow */
        plugins->selected->selected_param = MIN((uint8_t)(plugins->selected->selected_param - 1), nb_params - 1);
        res = json_pack("{si}", "selectedParam", plugins->selected->selected_param);
      }
      break;

    case CMD_SEQ_PARAM_NEXT:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_PARAMETER_NEXT\n");
#endif
      if (NULL != plugins->selected->parameters) {
        json_t *j_params = plugins->selected->parameters(ctx, NULL, 0);
        uint8_t nb_params = plugin_parameter_number(j_params);

        json_decref(j_params);

        plugins->selected->selected_param = (plugins->selected->selected_param + 1) % nb_params;
        res = json_pack("{si}", "selectedParam", plugins->selected->selected_param);
      }
      break;

    case CMD_SEQ_RESET:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_RESET\n");
#endif
      Sequence_clear(sm->cur, 0);
      break;

    case CMD_SEQ_SAVE_BARE: {
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_SAVE_BARE\n");
#endif
#ifdef DEBUG
      printf("[i] Save bare sequence\n");
#endif
      Sequence_save(ctx, 0, FALSE, auto_colormaps, auto_images);
      sm->curseq = sequences->seqs;
      Shuffler_grow_one_left(sequences->shuffler);
      res = json_pack("{so si}",
                      "sequence", Sequence_to_json(ctx, ctx->sm->cur, 1, 0, ctx->sm->cur->name),
                      "sequences", sequences->size);
    }
      break;

    case CMD_SEQ_SAVE_FULL: {
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_SAVE_FULL\n");
#endif
#ifdef DEBUG
      printf("[i] Save full sequence\n");
#endif
      Sequence_save(ctx, 0, TRUE, auto_colormaps, auto_images);
      sm->curseq = sequences->seqs;
      Shuffler_grow_one_left(sequences->shuffler);
      res = json_pack("{so si}",
                      "sequence", Sequence_to_json(ctx, ctx->sm->cur, 1, 0, ctx->sm->cur->name),
                      "sequences", sequences->size);
    }
      break;

    case CMD_SEQ_SELECT_PREVIOUS:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_SELECT_PREVIOUS\n");
#endif
      SequenceManager_select_previous_plugin(sm->cur);
      res = json_pack("{ss ss so*}",
                      "selectedPlugin", plugins->selected->name,
                      "selectedPluginDname", plugins->selected->dname,
                      "parameters", NULL != plugins->selected->parameters ? plugins->selected->parameters(ctx, NULL, 0) : NULL);
      break;

    case CMD_SEQ_SELECT_NEXT:
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_SELECT_NEXT\n");
#endif
      SequenceManager_select_next_plugin(sm->cur);
      res = json_pack("{ss ss so*}",
                      "selectedPlugin", plugins->selected->name,
                      "selectedPluginDname", plugins->selected->dname,
                      "parameters", NULL != plugins->selected->parameters ? plugins->selected->parameters(ctx, NULL, 0) : NULL);
      break;

    case CMD_SEQ_UPDATE_BARE: {
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_UPDATE_BARE\n");
#endif
#ifdef DEBUG
      printf("[i] Update bare sequence\n");
#endif
      Sequence_save(ctx, 1, FALSE, auto_colormaps, auto_images);
      res = json_pack("{so si}",
                      "sequence", Sequence_to_json(ctx, ctx->sm->cur, 1, 0, ctx->sm->cur->name),
                      "sequences", sequences->size);
    }
      break;

    case CMD_SEQ_UPDATE_FULL: {
#ifdef DEBUG_COMMANDS
      printf(">>> CMD_SEQ_UPDATE_FULL\n");
#endif
#ifdef DEBUG
      printf("[i] Update full sequence\n");
#endif
      Sequence_save(ctx, 1, TRUE, auto_colormaps, auto_images);
      res = json_pack("{so si}",
                      "sequence", Sequence_to_json(ctx, ctx->sm->cur, 1, 0, ctx->sm->cur->name),
                      "sequences", sequences->size);
    }
      break;

    default:
      xerror("Unhandled sequence command %d\n", cmd);
  }

  return res;
}
