// encoders.cm — nota/wota/json encode+decode benchmark
// Isolates per-type bottlenecks across all three serializers.

var nota = use('internal/nota')
var wota = use('internal/wota')
var json = use('json')

// --- Test data shapes ---

// Small integers: fast path for all encoders
var integers_small = array(100, function(i) { return i + 1 })

// Floats: stresses nota's snprintf path
var floats_array = array(100, function(i) {
  return 3.14159 * (i + 1) + 0.00001 * i
})

// Short strings in records: per-string overhead, property enumeration
var strings_short = array(50, function(i) {
  var r = {}
  r[`k${i}`] = `value_${i}`
  return r
})

// Single long string: throughput test (wota byte loop, nota kim)
var long_str = ""
var li = 0
for (li = 0; li < 100; li++) {
  long_str = `${long_str}abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMN`
}
var strings_long = long_str

// Unicode text: nota's kim encoding, wota's byte packing
var strings_unicode = "こんにちは世界 🌍🌎🌏 Ñoño café résumé naïve Ω∑∏ 你好世界"

// Nested records: cycle detection, property enumeration
function make_nested(depth, breadth) {
  var obj = {}
  var i = 0
  var k = null
  if (depth <= 0) {
    for (i = 0; i < breadth; i++) {
      k = `v${i}`
      obj[k] = i * 2.5
    }
    return obj
  }
  for (i = 0; i < breadth; i++) {
    k = `n${i}`
    obj[k] = make_nested(depth - 1, breadth)
  }
  return obj
}
var nested_records = make_nested(3, 4)

// Flat record: property enumeration cost
var flat_record = {}
var fi = 0
for (fi = 0; fi < 50; fi++) {
  flat_record[`prop_${fi}`] = fi * 1.1
}

// Mixed payload: realistic workload
var mixed_payload = array(50, function(i) {
  var r = {}
  r.id = i
  r.name = `item_${i}`
  r.active = i % 2 == 0
  r.score = i * 3.14
  r.tags = [`t${i % 5}`, `t${(i + 1) % 5}`]
  return r
})

// --- Pre-encode for decode benchmarks ---

var nota_enc_integers = nota.encode(integers_small)
var nota_enc_floats = nota.encode(floats_array)
var nota_enc_strings_short = nota.encode(strings_short)
var nota_enc_strings_long = nota.encode(strings_long)
var nota_enc_strings_unicode = nota.encode(strings_unicode)
var nota_enc_nested = nota.encode(nested_records)
var nota_enc_flat = nota.encode(flat_record)
var nota_enc_mixed = nota.encode(mixed_payload)

var wota_enc_integers = wota.encode(integers_small)
var wota_enc_floats = wota.encode(floats_array)
var wota_enc_strings_short = wota.encode(strings_short)
var wota_enc_strings_long = wota.encode(strings_long)
var wota_enc_strings_unicode = wota.encode(strings_unicode)
var wota_enc_nested = wota.encode(nested_records)
var wota_enc_flat = wota.encode(flat_record)
var wota_enc_mixed = wota.encode(mixed_payload)

var json_enc_integers = json.encode(integers_small)
var json_enc_floats = json.encode(floats_array)
var json_enc_strings_short = json.encode(strings_short)
var json_enc_strings_long = json.encode(strings_long)
var json_enc_strings_unicode = json.encode(strings_unicode)
var json_enc_nested = json.encode(nested_records)
var json_enc_flat = json.encode(flat_record)
var json_enc_mixed = json.encode(mixed_payload)

// --- Benchmark functions ---

return {
  // NOTA encode
  nota_encode_integers: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(integers_small) }
    return r
  },
  nota_encode_floats: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(floats_array) }
    return r
  },
  nota_encode_strings_short: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(strings_short) }
    return r
  },
  nota_encode_strings_long: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(strings_long) }
    return r
  },
  nota_encode_strings_unicode: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(strings_unicode) }
    return r
  },
  nota_encode_nested: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(nested_records) }
    return r
  },
  nota_encode_flat: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(flat_record) }
    return r
  },
  nota_encode_mixed: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.encode(mixed_payload) }
    return r
  },

  // NOTA decode
  nota_decode_integers: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_integers) }
    return r
  },
  nota_decode_floats: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_floats) }
    return r
  },
  nota_decode_strings_short: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_strings_short) }
    return r
  },
  nota_decode_strings_long: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_strings_long) }
    return r
  },
  nota_decode_strings_unicode: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_strings_unicode) }
    return r
  },
  nota_decode_nested: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_nested) }
    return r
  },
  nota_decode_flat: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_flat) }
    return r
  },
  nota_decode_mixed: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = nota.decode(nota_enc_mixed) }
    return r
  },

  // WOTA encode
  wota_encode_integers: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(integers_small) }
    return r
  },
  wota_encode_floats: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(floats_array) }
    return r
  },
  wota_encode_strings_short: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(strings_short) }
    return r
  },
  wota_encode_strings_long: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(strings_long) }
    return r
  },
  wota_encode_strings_unicode: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(strings_unicode) }
    return r
  },
  wota_encode_nested: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(nested_records) }
    return r
  },
  wota_encode_flat: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(flat_record) }
    return r
  },
  wota_encode_mixed: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.encode(mixed_payload) }
    return r
  },

  // WOTA decode
  wota_decode_integers: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_integers) }
    return r
  },
  wota_decode_floats: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_floats) }
    return r
  },
  wota_decode_strings_short: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_strings_short) }
    return r
  },
  wota_decode_strings_long: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_strings_long) }
    return r
  },
  wota_decode_strings_unicode: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_strings_unicode) }
    return r
  },
  wota_decode_nested: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_nested) }
    return r
  },
  wota_decode_flat: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_flat) }
    return r
  },
  wota_decode_mixed: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = wota.decode(wota_enc_mixed) }
    return r
  },

  // JSON encode
  json_encode_integers: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(integers_small) }
    return r
  },
  json_encode_floats: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(floats_array) }
    return r
  },
  json_encode_strings_short: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(strings_short) }
    return r
  },
  json_encode_strings_long: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(strings_long) }
    return r
  },
  json_encode_strings_unicode: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(strings_unicode) }
    return r
  },
  json_encode_nested: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(nested_records) }
    return r
  },
  json_encode_flat: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(flat_record) }
    return r
  },
  json_encode_mixed: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.encode(mixed_payload) }
    return r
  },

  // JSON decode
  json_decode_integers: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_integers) }
    return r
  },
  json_decode_floats: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_floats) }
    return r
  },
  json_decode_strings_short: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_strings_short) }
    return r
  },
  json_decode_strings_long: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_strings_long) }
    return r
  },
  json_decode_strings_unicode: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_strings_unicode) }
    return r
  },
  json_decode_nested: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_nested) }
    return r
  },
  json_decode_flat: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_flat) }
    return r
  },
  json_decode_mixed: function(n) {
    var i = 0
    var r = null
    for (i = 0; i < n; i++) { r = json.decode(json_enc_mixed) }
    return r
  }
}
