/**
 * @file    plc_debug.js
 * @brief   PLC 调试页 — 三列布局：左(遥信输入·按钮/遥测输入·设值) | 中(信号表) | 右(遥信输出·LED/遥测输出·展示)
 * @details 所有条目从中间信号表选择添加，增量刷新
 */
var PlcDebugStIn   = [];  // 遥信输入(按钮)
var PlcDebugMxIn   = [];  // 遥测输入(设值)
var PlcDebugStOut  = [];  // 遥信输出(LED)
var PlcDebugMxOut  = [];  // 遥测输出(展示)

Router.register('#plc_debug', function(c) { PlcDebugPage.render(c); });

var PlcDebugPage = (function() {
	var outSignals = [];
	var stInChk = {}, mxInChk = {}, stOutChk = {}, mxOutChk = {}, sigChk = {};

	function getOut() {
		var out = SignalStore.get('out');
		return (Array.isArray(out) && out.length) ? out : outSignals;
	}

	function findSig(sa) {
		for (var i = 0; i < outSignals.length; i++)
			if (outSignals[i].saddr === sa) return outSignals[i];
		return null;
	}

	function refreshData() {
		var o = getOut(); if (Array.isArray(o)) outSignals = o;
		PlcDebugStIn.forEach(function(l)  { var f = findSig(l.saddr); l.val = f ? f.val : 0; });
		PlcDebugMxIn.forEach(function(m)  { var f = findSig(m.saddr); m.val = f ? f.val : 0; });
		PlcDebugStOut.forEach(function(b) { var f = findSig(b.saddr); b.val = f ? f.val : 0; });
		PlcDebugMxOut.forEach(function(m) { var f = findSig(m.saddr); m.val = f ? f.val : 0; });
	}

	function incrRefresh() {
		refreshData();
		PlcDebugStIn.forEach(function(b, i) {
			var on = parseFloat(b.val) > 0;
			var ve = document.getElementById('sti-val-' + i);
			if (ve) { ve.textContent = '(' + fmtVal(b.val) + ')'; ve.style.color = on ? 'var(--accent)' : 'var(--text-muted)'; }
		});
		PlcDebugMxIn.forEach(function(m, i) {
			var ve = document.getElementById('mxi-cur-' + i);
			if (ve) ve.textContent = '(' + fmtVal(m.val) + ')';
		});
		PlcDebugStOut.forEach(function(l, i) {
			var on = parseFloat(l.val) > 0;
			var ve = document.getElementById('sto-val-' + i), ie = document.getElementById('sto-icon-' + i);
			if (ve) { ve.textContent = '(' + fmtVal(l.val) + ')'; ve.style.color = on ? 'var(--accent)' : 'var(--text-muted)'; }
			if (ie) ie.className = 'plc-led' + (on ? ' plc-led-on' : '');
		});
		PlcDebugMxOut.forEach(function(m, i) {
			var ve = document.getElementById('mxo-val-' + i);
			if (ve) ve.textContent = fmtVal(m.val);
		});
	}

	function countChecked(obj) { var n = 0; for (var k in obj) if (obj.hasOwnProperty(k)) n++; return n; }

	function delChecked() {
		var todel = [];
		for (var k in stInChk)  if (stInChk.hasOwnProperty(k))  todel.push({ t: 'sti',  idx: parseInt(k) });
		for (var k in mxInChk)  if (mxInChk.hasOwnProperty(k))  todel.push({ t: 'mxi',  idx: parseInt(k) });
		for (var k in stOutChk) if (stOutChk.hasOwnProperty(k)) todel.push({ t: 'sto',  idx: parseInt(k) });
		for (var k in mxOutChk) if (mxOutChk.hasOwnProperty(k)) todel.push({ t: 'mxo',  idx: parseInt(k) });
		if (!todel.length) { toast(I18n.t('toast.no_selected'), 'error'); return; }
		if (!confirm(I18n.t('plc_debug.confirm_del') + ' ' + todel.length + ' ?')) return;
		todel.sort(function(a, b) { return b.idx - a.idx; }).forEach(function(t) {
			if (t.t === 'sti') PlcDebugStIn.splice(t.idx, 1);
			else if (t.t === 'mxi') PlcDebugMxIn.splice(t.idx, 1);
			else if (t.t === 'sto') PlcDebugStOut.splice(t.idx, 1);
			else PlcDebugMxOut.splice(t.idx, 1);
		});
		stInChk = {}; mxInChk = {}; stOutChk = {}; mxOutChk = {};
		renderAll();
	}

	function makeBlock(title, icon, arr, chkObj, idPrefix, blockType) {
		var html = '';
		if (!arr.length) {
			html = '<div style="color:var(--text-muted);padding:16px;text-align:center;font-size:12px">暂无</div>';
		} else {
			arr.forEach(function(item, i) {
				var on = parseFloat(item.val) > 0, chk = !!chkObj[i];
				html += '<div class="plc-item">';
				html += '<input type="checkbox" ' + (chk ? 'checked' : '') + ' onchange="PlcDebugPage._toggleChk(\'' + idPrefix + '\',' + i + ',this.checked)">';

				if (blockType === 'btn') {
					html += '<button class="plc-btn-icon" id="' + idPrefix + '-icon-' + i + '" title="点击翻转">🔘</button>';
				} else if (blockType === 'led') {
					html += '<div class="plc-led' + (on ? ' plc-led-on' : '') + '" id="' + idPrefix + '-icon-' + i + '"></div>';
				}

				html += '<div class="plc-info">';
				if (item.saddr) {
					html += '<span class="plc-saddr">' + esc(item.saddr) + '</span>';
					if (item.desc) html += '<span style="color:var(--text-muted);font-size:11px">' + esc(item.desc) + '</span>';
				} else {
					html += '<span style="color:var(--text-muted)">未绑定</span>';
				}
				html += '</div>';

				if (blockType === 'btn' || blockType === 'led') {
					html += '<span id="' + idPrefix + '-val-' + i + '" style="color:' + (on ? 'var(--accent)' : 'var(--text-muted)') + ';font-weight:600;font-family:var(--font-mono);font-size:12px">(' + fmtVal(item.val) + ')</span>';
				} else if (blockType === 'mxi') {
					html += '<span id="' + idPrefix + '-cur-' + i + '" style="color:var(--text-muted);font-weight:600;font-family:var(--font-mono);font-size:11px;margin-right:4px">(' + fmtVal(item.val) + ')</span>';
					html += '<input type="text" id="' + idPrefix + '-input-' + i + '" placeholder="输入值..." style="width:60px;padding:2px 4px;border:1px solid var(--border);border-radius:3px;background:var(--bg-input);color:var(--text-primary);font-size:11px;font-family:var(--font-mono)">';
					html += '<button class="btn btn-xs" style="font-size:10px;padding:1px 6px" id="' + idPrefix + '-setbtn-' + i + '">设置</button>';
				} else if (blockType === 'mxo') {
					html += '<span id="' + idPrefix + '-val-' + i + '" style="color:var(--accent);font-weight:700;font-family:var(--font-mono);font-size:12px">' + fmtVal(item.val) + '</span>';
				}
				html += '</div>';
			});
		}
		return '<div class="plc-block"><div class="plc-block-header"><span>' + icon + ' ' + title + '</span>'
			+ '<span style="margin-left:auto;font-size:10px;color:var(--text-muted)">' + arr.length + '</span></div>'
			+ '<div class="plc-sig-list">' + html + '</div></div>';
	}

	function renderAll() {
		var c = document.getElementById('plc-content');
		if (!c) return;
		refreshData();

		/* 信号表 (中间列) */
		var o = getOut();
		var sigHtml = '';
		if (!o.length) {
			sigHtml = '<div style="color:var(--text-muted);padding:20px;text-align:center;font-size:12px">' + I18n.t('plc_debug.no_sig') + '</div>';
		} else {
			o.forEach(function(s, i) {
				var chk = !!sigChk[i];
				sigHtml += '<div class="plc-sig-check-item" data-idx="' + i + '">'
					+ '<input type="checkbox" ' + (chk ? 'checked' : '') + ' data-sig-idx="' + i + '">'
					+ '<span style="color:var(--accent);min-width:24px;font-size:12px;font-weight:600">#' + i + '</span>'
					+ '<span class="plc-sig-saddr" title="' + esc(s.saddr) + (s.desc ? ' - ' + esc(s.desc) : '') + '" style="font-size:12px">' + esc(s.saddr) + '</span>'
					+ (s.desc ? '<span style="color:var(--text-muted);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(s.desc) + '</span>' : '')
					+ '<span style="margin-left:auto;color:var(--accent);font-weight:700;font-family:var(--font-mono);font-size:12px">' + fmtVal(s.val) + '</span>'
					+ '</div>';
			});
		}

		c.innerHTML = '<div class="plc-debug-grid">'
			/* 左列: 遥信输入(上) + 遥测输入(下) */
			+ '<div class="plc-col" style="display:flex;flex-direction:column;gap:8px">'
			+ makeBlock('遥信输入', '📤', PlcDebugStIn, stInChk, 'sti', 'btn')
			+ makeBlock('遥测输入', '📊', PlcDebugMxIn, mxInChk, 'mxi', 'mxi')
			+ '</div>'
			/* 中列: 信号表 */
			+ '<div class="plc-col plc-sig-col"><div class="card-header" style="margin-bottom:6px"><span>📋 信号表</span>'
			+ '<span style="margin-left:auto;font-size:11px;color:var(--text-muted)">' + o.length + '</span>'
			+ '</div>'
			+ '<div class="plc-arrow-row" style="justify-content:space-between">'
			+ '<button class="btn btn-xs" style="font-size:10px;padding:2px 8px" onclick="PlcDebugPage._moveSel(\'sti\')" title="→遥信输入">← 遥信输入</button>'
			+ '<button class="btn btn-xs" style="font-size:10px;padding:2px 8px" onclick="PlcDebugPage._moveSel(\'sto\')" title="→遥信输出">遥信输出 →</button>'
			+ '</div>'
			+ '<div class="plc-arrow-row" style="justify-content:space-between;margin-top:2px">'
			+ '<button class="btn btn-xs" style="font-size:10px;padding:2px 8px" onclick="PlcDebugPage._moveSel(\'mxi\')" title="→遥测输入">← 遥测输入</button>'
			+ '<button class="btn btn-xs" style="font-size:10px;padding:2px 8px" onclick="PlcDebugPage._moveSel(\'mxo\')" title="→遥测输出">遥测输出 →</button>'
			+ '</div>'
			+ '<div class="plc-sig-list">' + sigHtml + '</div></div>'
			/* 右列: 遥信输出(上) + 遥测输出(下) */
			+ '<div class="plc-col" style="display:flex;flex-direction:column;gap:8px">'
			+ makeBlock('遥信输出', '📥', PlcDebugStOut, stOutChk, 'sto', 'led')
			+ makeBlock('遥测输出', '📊', PlcDebugMxOut, mxOutChk, 'mxo', 'mxo')
			+ '</div>'
			+ '</div>';

		/* 绑定事件 */
		[].forEach.call(c.querySelectorAll('.plc-btn-icon'), function(el) {
			el.onclick = function() {
				var m = this.id.match(/^sti-icon-(\d+)$/);
				if (m) PlcDebugPage._toggleStIn(parseInt(m[1]));
			};
		});
		[].forEach.call(c.querySelectorAll('.plc-led'), function(el) {
			el.onclick = function() {
				var m = this.id.match(/^sto-icon-(\d+)$/);
				if (m) PlcDebugPage._bindStOut(parseInt(m[1]));
			};
		});
		[].forEach.call(c.querySelectorAll('[id$="-setbtn-"]'), function(el) {
			el.onclick = function() {
				var m = this.id.match(/^mxi-setbtn-(\d+)$/);
				if (m) PlcDebugPage._setMxIn(parseInt(m[1]));
			};
		});
		[].forEach.call(c.querySelectorAll('.plc-sig-check-item'), function(row) {
			row.onclick = function(e) {
				if (e.target.tagName === 'INPUT') return;
				var cb = this.querySelector('input[type="checkbox"]');
				if (cb) {
					cb.checked = !cb.checked;
					var si = parseInt(cb.getAttribute('data-sig-idx'));
					if (!isNaN(si)) { if (cb.checked) sigChk[si] = true; else delete sigChk[si]; }
				}
			};
		});
		[].forEach.call(c.querySelectorAll('.plc-sig-check-item input[type="checkbox"]'), function(cb) {
			cb.onclick = function(e) {
				e.stopPropagation();
				var si = parseInt(this.getAttribute('data-sig-idx'));
				if (!isNaN(si)) { if (this.checked) sigChk[si] = true; else delete sigChk[si]; }
			};
		});

		updateDelBtn();
	}

	function updateDelBtn() {
		var el = document.getElementById('plc-del-btn');
		if (!el) return;
		var n = countChecked(stInChk) + countChecked(mxInChk) + countChecked(stOutChk) + countChecked(mxOutChk);
		el.textContent = I18n.t('plc_debug.del_sel') + (n ? ' (' + n + ')' : '');
		el.disabled = !n;
	}

	return {
		render: function(c) {
			stInChk = {}; mxInChk = {}; stOutChk = {}; mxOutChk = {}; sigChk = {};
			refreshData();
			c.innerHTML = '<div class="card">'
				+ '<div class="card-header"><span>📟 ' + I18n.t('plc_debug.title') + '</span>'
				+ '<div class="btn-group">'
				+ '<button class="btn btn-sm" onclick="PlcDebugPage._refresh()">🔄 ' + I18n.t('plc_debug.refresh_btn') + '</button>'
				+ '<button class="btn btn-danger btn-sm" id="plc-del-btn" disabled onclick="PlcDebugPage._delChecked()">🗑 ' + I18n.t('plc_debug.del_sel') + '</button>'
				+ '</div></div>'
				+ '<div id="plc-content"></div></div>';
			renderAll();
		},
		_toggleChk: function(prefix, i, v) {
			if (prefix === 'sti')  { if (v) stInChk[i] = true;  else delete stInChk[i]; }
			if (prefix === 'mxi')  { if (v) mxInChk[i] = true;  else delete mxInChk[i]; }
			if (prefix === 'sto')  { if (v) stOutChk[i] = true; else delete stOutChk[i]; }
			if (prefix === 'mxo')  { if (v) mxOutChk[i] = true; else delete mxOutChk[i]; }
			updateDelBtn();
		},
		_toggleStIn: function(i) {
			var b = PlcDebugStIn[i];
			if (!b.saddr) {
				PlcDebugPage._showPicker(function(sa, de) {
					b.saddr = sa; b.desc = de;
					var f = findSig(sa); if (f) b.val = f.val;
					renderAll();
				});
				return;
			}
			var nv = parseFloat(b.val) > 0 ? 0 : 1;
			WsClient.send({ curd: 'set', signal_type: 'out', saddr: b.saddr, signal_data: String(nv), setting_zone: '0' });
			b.val = nv;
			var outs = SignalStore.get('out');
			for (var j = 0; j < outs.length; j++)
				if (outs[j].saddr === b.saddr) { outs[j].val = String(nv); break; }
			renderAll();
		},
		_bindStOut: function(i) {
			PlcDebugPage._showPicker(function(sa, de) {
				PlcDebugStOut[i].saddr = sa; PlcDebugStOut[i].desc = de;
				var f = findSig(sa); if (f) PlcDebugStOut[i].val = f.val;
				renderAll();
			});
		},
		_setMxIn: function(i) {
			var m = PlcDebugMxIn[i];
			if (!m || !m.saddr) {
				PlcDebugPage._showPicker(function(sa, de) {
					if (!PlcDebugMxIn[i]) return;
					PlcDebugMxIn[i].saddr = sa; PlcDebugMxIn[i].desc = de;
					var f = findSig(sa); if (f) PlcDebugMxIn[i].val = f.val;
					renderAll();
				});
				return;
			}
			var inp = document.getElementById('mxi-input-' + i);
			if (!inp) { toast('找不到输入框', 'error'); return; }
			var nv = inp.value.trim();
			if (nv === '') { toast('请输入值', 'error'); return; }
			WsClient.send({ curd: 'set', signal_type: 'out', saddr: m.saddr, signal_data: nv, setting_zone: '0' });
			m.val = parseFloat(nv) || 0;
			m.inputVal = '';
			var outs = SignalStore.get('out');
			for (var j = 0; j < outs.length; j++)
				if (outs[j].saddr === m.saddr) { outs[j].val = nv; break; }
			renderAll();
		},
		_showPicker: function(cb) {
			var sigs = getOut();
			if (!sigs.length) { toast(I18n.t('plc_debug.no_sig'), 'error'); return; }
			var rows = '';
			sigs.forEach(function(s) {
				rows += '<div class="plc-pick-row" data-saddr="' + esc(s.saddr) + '" data-desc="' + esc(s.desc || '') + '">'
					+ '<strong>' + esc(s.saddr) + '</strong>'
					+ (s.desc ? ' <span style="color:var(--text-muted)">' + esc(s.desc) + '</span>' : '')
					+ '<span style="float:right;color:var(--accent);font-weight:700">' + fmtVal(s.val) + '</span></div>';
			});
			var ov = document.createElement('div');
			ov.className = 'modal-overlay';
			ov.innerHTML = '<div class="modal-box" style="max-width:550px"><h3>' + I18n.t('plc_debug.bind_title') + '</h3>'
				+ '<div style="max-height:300px;overflow-y:auto;margin:12px 0">' + rows + '</div>'
				+ '<button class="btn btn-sm" id="plc-pick-cancel">' + I18n.t('toast.cancel') + '</button></div>';
			document.body.appendChild(ov);
			document.getElementById('plc-pick-cancel').onclick = function() { ov.remove(); };
			ov.addEventListener('click', function(e) { if (e.target === ov) ov.remove(); });
			ov.querySelectorAll('.plc-pick-row').forEach(function(r) {
				r.onclick = function() {
					var sa = this.getAttribute('data-saddr'), de = this.getAttribute('data-desc');
					ov.remove();
					if (confirm(I18n.t('plc_debug.confirm_bind') + ' ' + sa + ' ?')) cb(sa, de);
				};
			});
		},
		_moveSel: function(target) {
			var picked = [];
			for (var k in sigChk) if (sigChk.hasOwnProperty(k)) picked.push(parseInt(k));
			if (!picked.length) { toast(I18n.t('toast.no_selected'), 'error'); return; }
			picked.sort(function(a, b) { return a - b; }).forEach(function(i) {
				var s = outSignals[i];
				if (!s) return;
				var item = { saddr: s.saddr, desc: s.desc || '', val: s.val || 0 };
				if (target === 'mxi') item.inputVal = '';
				if (target === 'sti') PlcDebugStIn.push(item);
				else if (target === 'sto') PlcDebugStOut.push(item);
				else if (target === 'mxi') PlcDebugMxIn.push(item);
				else PlcDebugMxOut.push(item);
			});
			sigChk = {}; renderAll();
		},
		_refresh: function() { refreshData(); renderAll(); },
		incrRefresh: function() { refreshData(); incrRefresh(); },
		_delChecked: delChecked,
	};
})();
