let _seListEl = document.getElementById('sets-editor-list'); let _seDetailEl = document.getElementById('sets-editor-detail'); let _seSelectedIdx = 0; let _seEditingIdx = -1; let _seFrets = []; let _seNameInput = null; let _seAutoLabel = null; function _seDbg() { if (window.dbg) window.dbg.apply(null, ['[sets-editor]'].concat(Array.prototype.slice.call(arguments))); } function _seData() { return window.getScoreSetsData(); } function _seDensity(set) { return set && set.type === 'density'; } document.getElementById('btn-back-explorer').addEventListener('click', function() { _seEditingIdx = -1; window.setScoreSetsData(_seData()); window.switchToView('shapes'); }); window.initSetsEditor = function() { _seDbg('init'); var data = _seData(); _seSelectedIdx = data.selected; _seEditingIdx = -1; seRenderList(); seRenderDetail(); }; function seSelectSet(i) { _seDbg('selectSet', i); _seSelectedIdx = i; _seEditingIdx = -1; seRenderList(); seRenderDetail(); } function seNewSet() { _seDbg('newSet'); var name = prompt('New score set name:'); if (!name || !name.trim()) return; var data = _seData(); data.sets.push({ name: name.trim(), type: '', shapes: [] }); _seSelectedIdx = data.sets.length - 1; _seEditingIdx = -1; window.persistSets(); seRenderList(); seRenderDetail(); } function seRenderList() { _seListEl.innerHTML = ''; var data = _seData(); data.sets.forEach(function(set, i) { var item = document.createElement('div'); item.className = 'se-set-item' + (i === _seSelectedIdx ? ' selected' : ''); var nm = document.createElement('span'); nm.className = 'se-set-name'; nm.textContent = set.name; var badges = document.createElement('span'); badges.className = 'se-set-badges'; var ct = document.createElement('span'); ct.className = 'se-badge'; ct.textContent = set.shapes.length; badges.appendChild(ct); if (_seDensity(set)) { var db = document.createElement('span'); db.className = 'se-badge se-badge-density'; db.textContent = 'density'; badges.appendChild(db); } item.appendChild(nm); item.appendChild(badges); item.setAttribute('onclick', 'seSelectSet(' + i + ')'); _seListEl.appendChild(item); }); var btn = document.createElement('button'); btn.className = 'btn-small se-btn-new-set'; btn.textContent = 'New Set'; btn.setAttribute('onclick', 'seNewSet()'); _seListEl.appendChild(btn); } function seRenameSet() { _seDbg('rename'); var set = _seData().sets[_seSelectedIdx]; if (!set) return; var name = prompt('Rename set:', set.name); if (!name || !name.trim()) return; set.name = name.trim(); window.persistSets(); seRenderList(); seRenderDetail(); } function seDeleteSet() { _seDbg('deleteSet'); var data = _seData(); var set = data.sets[_seSelectedIdx]; if (!set || !confirm('Delete "' + set.name + '"?')) return; data.sets.splice(_seSelectedIdx, 1); if (_seSelectedIdx >= data.sets.length) _seSelectedIdx = data.sets.length - 1; data.selected = _seSelectedIdx; window.persistSets(); seRenderList(); seRenderDetail(); } function seMoveShape(i, dir) { _seDbg('move', i, dir); var set = _seData().sets[_seSelectedIdx]; if (!set) return; var j = i + dir; if (j < 0 || j >= set.shapes.length) return; var tmp = set.shapes[i]; set.shapes[i] = set.shapes[j]; set.shapes[j] = tmp; window.persistSets(); seRenderDetail(); } function seEditShape(i) { _seDbg('edit', i); _seEditingIdx = i; seRenderDetail(); } function seDupShape(i) { _seDbg('dup', i); var set = _seData().sets[_seSelectedIdx]; if (!set) return; var orig = set.shapes[i]; set.shapes.splice(i + 1, 0, { name: '', frets: orig.frets.slice() }); window.persistSets(); seRenderDetail(); } function seDelShape(i) { _seDbg('del', i); var set = _seData().sets[_seSelectedIdx]; if (!set) return; set.shapes.splice(i, 1); window.persistSets(); seRenderDetail(); } function seAddShape() { _seDbg('add'); var set = _seData().sets[_seSelectedIdx]; if (!set) return; set.shapes.push({ name: '', frets: [0, 0, 0, 0, 0, 0] }); _seEditingIdx = set.shapes.length - 1; window.persistSets(); seRenderDetail(); } function seRenderDetail() { _seDetailEl.innerHTML = ''; var data = _seData(); var set = data.sets[_seSelectedIdx]; if (!set) return; if (_seEditingIdx >= 0) { seRenderShapeEditor(set); return; } var density = _seDensity(set); var header = document.createElement('div'); header.className = 'se-detail-header'; var h3 = document.createElement('h3'); h3.textContent = set.name; header.appendChild(h3); if (!density) { var btnR = document.createElement('button'); btnR.className = 'btn-small'; btnR.textContent = 'Rename'; btnR.setAttribute('onclick', 'seRenameSet()'); header.appendChild(btnR); if (data.sets.length > 1) { var btnD = document.createElement('button'); btnD.className = 'btn-small se-btn-danger'; btnD.textContent = 'Delete Set'; btnD.setAttribute('onclick', 'seDeleteSet()'); header.appendChild(btnD); } } _seDetailEl.appendChild(header); var listEl = document.createElement('div'); listEl.className = 'se-shape-list'; set.shapes.forEach(function(shape, i) { var row = document.createElement('div'); row.className = 'se-shape-row'; var fb = document.createElement('div'); fb.className = 'fretboard alternative-fretboard se-mini-fb'; var fingering = shape.frets.map(function(f) { return f === -1 ? 'x' : String(f); }); var mx = Math.max.apply(null, shape.frets.filter(function(f) { return f >= 0; }).concat([1])); window.renderSingleFretboard(fb, fingering, Math.max(mx, 4)); row.appendChild(fb); var info = document.createElement('div'); info.className = 'se-shape-info'; var nameEl = document.createElement('span'); nameEl.className = 'se-shape-name'; if (shape.name) { nameEl.textContent = shape.name; } else { nameEl.classList.add('se-auto-name'); nameEl.textContent = 'detecting...'; _seAutoDetect(shape.frets).then(function(n) { nameEl.textContent = n || '(unknown)'; }); } info.appendChild(nameEl); var fretsEl = document.createElement('span'); fretsEl.className = 'se-shape-frets'; fretsEl.textContent = shape.frets.map(function(f) { return f === -1 ? 'x' : f; }).join(' '); info.appendChild(fretsEl); row.appendChild(info); if (!density) { var acts = document.createElement('div'); acts.className = 'se-shape-actions'; if (i > 0) { var up = document.createElement('button'); up.className = 'btn-small'; up.textContent = '\u25B2'; up.title = 'Move up'; up.setAttribute('onclick', 'seMoveShape(' + i + ',-1)'); acts.appendChild(up); } if (i < set.shapes.length - 1) { var dn = document.createElement('button'); dn.className = 'btn-small'; dn.textContent = '\u25BC'; dn.title = 'Move down'; dn.setAttribute('onclick', 'seMoveShape(' + i + ',1)'); acts.appendChild(dn); } var ed = document.createElement('button'); ed.className = 'btn-small'; ed.textContent = 'edit'; ed.setAttribute('onclick', 'seEditShape(' + i + ')'); acts.appendChild(ed); var dp = document.createElement('button'); dp.className = 'btn-small'; dp.textContent = 'dup'; dp.title = 'Duplicate'; dp.setAttribute('onclick', 'seDupShape(' + i + ')'); acts.appendChild(dp); var dl = document.createElement('button'); dl.className = 'btn-small se-btn-danger'; dl.textContent = 'del'; dl.setAttribute('onclick', 'seDelShape(' + i + ')'); acts.appendChild(dl); row.appendChild(acts); } listEl.appendChild(row); }); _seDetailEl.appendChild(listEl); if (!density) { var btnA = document.createElement('button'); btnA.className = 'btn-small se-btn-add-shape'; btnA.textContent = 'Add Shape'; btnA.setAttribute('onclick', 'seAddShape()'); _seDetailEl.appendChild(btnA); } } function seShapeDone() { _seDbg('done'); var set = _seData().sets[_seSelectedIdx]; if (!set) return; var shape = set.shapes[_seEditingIdx]; if (!shape) return; shape.frets = _seFrets.slice(); shape.name = _seNameInput ? _seNameInput.value.trim() : ''; _seEditingIdx = -1; window.persistSets(); seRenderList(); seRenderDetail(); } function seFbCell(s, f) { var cur = _seFrets[s]; if (f === 0) { _seFrets[s] = (cur === -1) ? 0 : -1; } else { _seFrets[s] = (cur === f) ? 0 : f; } _seBuildGrid(); _seUpdateAutoName(); } function _seBuildGrid() { var wrap = document.getElementById('se-fb-wrap'); if (!wrap) return; wrap.innerHTML = ''; var nf = 12; var table = document.createElement('div'); table.className = 'se-fb-grid'; var hdr = document.createElement('div'); hdr.className = 'se-fb-header-row'; var lbl = document.createElement('div'); lbl.className = 'se-fb-label'; hdr.appendChild(lbl); for (var f = 0; f <= nf; f++) { var c = document.createElement('div'); c.className = 'se-fb-fret-num'; c.textContent = f === 0 ? 'nut' : f; hdr.appendChild(c); } table.appendChild(hdr); var labels = ['1 (low)', '2', '3', '4', '5', '6 (high)']; for (var s = 0; s < 6; s++) { var row = document.createElement('div'); row.className = 'se-fb-row'; var sl = document.createElement('div'); sl.className = 'se-fb-label'; sl.textContent = labels[s]; row.appendChild(sl); for (var f = 0; f <= nf; f++) { var cell = document.createElement('div'); cell.className = 'se-fb-cell'; if (f === 0) cell.classList.add('se-fb-nut'); var cur = _seFrets[s]; if (f === 0) { if (cur === -1) { cell.classList.add('se-muted'); cell.textContent = 'x'; } else if (cur === 0) { cell.classList.add('se-open'); cell.textContent = 'o'; } } else if (cur === f) { cell.classList.add('se-dot-active'); } cell.setAttribute('onclick', 'seFbCell(' + s + ',' + f + ')'); row.appendChild(cell); } table.appendChild(row); } wrap.appendChild(table); } function _seUpdateAutoName() { _seAutoDetect(_seFrets).then(function(n) { if (_seAutoLabel) _seAutoLabel.textContent = n ? 'Detected: ' + n : ''; }); } function seRenderShapeEditor(set) { var shape = set.shapes[_seEditingIdx]; if (!shape) { _seEditingIdx = -1; seRenderDetail(); return; } _seFrets = shape.frets.slice(); _seDetailEl.innerHTML = ''; var header = document.createElement('div'); header.className = 'se-editor-header'; var btnDone = document.createElement('button'); btnDone.className = 'btn-small btn-apply'; btnDone.textContent = 'Done'; btnDone.setAttribute('onclick', 'seShapeDone()'); header.appendChild(btnDone); var title = document.createElement('h3'); title.textContent = 'Edit Shape'; header.appendChild(title); _seDetailEl.appendChild(header); var nameRow = document.createElement('div'); nameRow.className = 'se-editor-name-row'; var nl = document.createElement('label'); nl.textContent = 'Name'; _seNameInput = document.createElement('input'); _seNameInput.type = 'text'; _seNameInput.className = 'se-editor-name-input'; _seNameInput.placeholder = 'Auto-detect name'; _seNameInput.value = shape.name; _seAutoLabel = document.createElement('span'); _seAutoLabel.className = 'se-auto-label'; nameRow.appendChild(nl); nameRow.appendChild(_seNameInput); nameRow.appendChild(_seAutoLabel); _seDetailEl.appendChild(nameRow); var fbWrap = document.createElement('div'); fbWrap.id = 'se-fb-wrap'; fbWrap.className = 'se-clickable-fb'; _seDetailEl.appendChild(fbWrap); _seBuildGrid(); _seUpdateAutoName(); } function _seAutoDetect(frets) { if (!window.go || !window.go.main || !window.go.main.App) return Promise.resolve(''); return window.go.main.App.IdentifyShape(frets).then(function(n) { return n || ''; }).catch(function() { return ''; }); }