'use babel';

// Novation LaunchControl XL factory-template CC layout.
// Source of truth: reference_controller_map.md.
//
//   Lane:          1    2    3    4    5    6    7    8
//   Top knobs:    13   14   15   16   17   18   19   20    (row A)
//   Mid knobs:    29   30   31   32   33   34   35   36    (row B)
//   Bot knobs:    49   50   51   52   53   54   55   56    (row C)
//   Faders:       77   78   79   80   81   82   83   84    (row D)
//   State btns:   41   42   43   44   57   58   59   60    (row E)
//   Push btns:    73   74   75   76   89   90   91   92    (row F)

const TABLE = [
  { row: 'A', start: 13, lanes: [1, 2, 3, 4, 5, 6, 7, 8] },
  { row: 'B', start: 29, lanes: [1, 2, 3, 4, 5, 6, 7, 8] },
  { row: 'C', start: 49, lanes: [1, 2, 3, 4, 5, 6, 7, 8] },
  { row: 'D', start: 77, lanes: [1, 2, 3, 4, 5, 6, 7, 8] },
  // E and F have gaps — split into two contiguous segments each.
  { row: 'E', start: 41, lanes: [1, 2, 3, 4] },
  { row: 'E', start: 57, lanes: [5, 6, 7, 8] },
  { row: 'F', start: 73, lanes: [1, 2, 3, 4] },
  { row: 'F', start: 89, lanes: [5, 6, 7, 8] }
];

export function decodeCC(cc) {
  const n = Number(cc);
  for (const seg of TABLE) {
    const idx = n - seg.start;
    if (idx >= 0 && idx < seg.lanes.length) {
      const lane = seg.lanes[idx];
      return { row: seg.row, lane, label: `${seg.row}${lane}`, cc: n };
    }
  }
  return { row: '?', lane: null, label: `cc${n}`, cc: n };
}

// Reverse: given a (row, lane), return the matching CC. Used by the
// convention map in render so we can show an orbit's expected physical
// control even when the .tidal file has no explicit "^NN" reference.
export function encodeCC(row, lane) {
  for (const seg of TABLE) {
    if (seg.row !== row) continue;
    const idx = seg.lanes.indexOf(lane);
    if (idx >= 0) return seg.start + idx;
  }
  return null;
}
