#pragma once

#include "encoder_base.h"
#include "util.h"
#include "../enum/te.h"
#include "../protobuf/util.h"
#include "../protobuf/validate.h"

// ==========================================================================
// ==========================================================================
// Teenage Engineering Representations

class TeTrackDensityEncoder : public ENCODER {
public:
  TeTrackDensityEncoder() {    
    rep = new REPRESENTATION({
      {PIECE_START, TOKEN_DOMAIN(2)}, // 1 is bar infill
      {BAR, TOKEN_DOMAIN(1)},
      {BAR_END, TOKEN_DOMAIN(1)},
      {TRACK, TOKEN_DOMAIN({
        OPZ_KICK_TRACK,
        OPZ_SNARE_TRACK,
        OPZ_HIHAT_TRACK,
        OPZ_SAMPLE_TRACK,
        OPZ_BASS_TRACK,
        OPZ_LEAD_TRACK,
        OPZ_ARP_TRACK,
        OPZ_CHORD_TRACK   
      })},
      {TRACK_END, TOKEN_DOMAIN(1)},
      {INSTRUMENT, TOKEN_DOMAIN(128)},
      {NOTE_OFFSET, TOKEN_DOMAIN(128)},
      {NOTE_ONSET, TOKEN_DOMAIN(128)},
      {TIME_DELTA, TOKEN_DOMAIN(48)},
      {FILL_IN, TOKEN_DOMAIN(3)},
      {DENSITY_LEVEL, TOKEN_DOMAIN(10)}
      });
    config = get_encoder_config();
  }
  ~TeTrackDensityEncoder() {
    delete rep;
    delete config;
  }
  EncoderConfig *get_encoder_config() {
    EncoderConfig *e = new EncoderConfig();
    e->both_in_one = true;
    e->force_instrument = true;
    e->mark_density = true;
    e->min_tracks = 1;
    e->use_drum_offsets = false;
    e->te = true;
    e->resolution = 12;
    return e;
  }
  vector<int> encode(midi::Piece *p) {
    // add validate function here ...
    update_note_density(p);
    return to_performance_w_tracks_dev(p, rep, config);
  }
  void decode(vector<int> &tokens, midi::Piece *p) {
    if (config->do_multi_fill == true) {
      tokens = resolve_bar_infill_tokens(tokens, rep);
    }
    return decode_track_dev(tokens, p, rep, config);
  }
};
