<%
local api = require "luci.passwall.api"
local fs = api.fs
local has_old_geoip = fs.access("/tmp/bak_v2ray/geoip.dat")
local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
-%>
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js?v=26.1.9"></script>

<style>
	table .cbi-button-up,
	table .cbi-button-down {
		display: none !important;
	}

	div.cbi-value[id$="-gfwlist_update"],
	div.cbi-value[id$="-chnroute_update"],
	div.cbi-value[id$="-chnroute6_update"],
	div.cbi-value[id$="-chnlist_update"],
	div.cbi-value[id$="-geoip_update"],
	div.cbi-value[id$="-geosite_update"] {
		display: none !important;
	}

	.drag-handle {
		vertical-align: middle;
		cursor: grab !important;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		font-size: 20px;
		font-weight: 100;
		padding: 0 !important;
		line-height: inherit;
		user-select: none;
		align-self: stretch;
		background-color: transparent;
	}

	.drag-handle:hover {
		background: transparent;
	}

	.dragging-row {
		background-color: rgba(131, 191, 255, 0.7) !important;
		box-shadow: 0 4px 6px rgba(0,0,0,0.1);
	}
</style>

<div class="cbi-value" id="_rule_div">
	<label class="cbi-value-title">
		<%:Update Options%>
	</label>
	<div class="cbi-value-field">
		<div>
			<label>
				<input class="cbi-input-checkbox" type="checkbox" name="gfwlist" value="1" />
				gfwlist
			</label>
			<label>
				<input class="cbi-input-checkbox" type="checkbox" name="chnroute" value="1" />
				chnroute
			</label>
			<label>
				<input class="cbi-input-checkbox" type="checkbox" name="chnroute6" value="1" />
				chnroute6
			</label>
			<label>
				<input class="cbi-input-checkbox" type="checkbox" name="chnlist" value="1" />
				chnlist
			</label>
			<label>
				<input class="cbi-input-checkbox" type="checkbox" name="geoip" value="1" />
				geoip
			</label>
			<label>
				<input class="cbi-input-checkbox" type="checkbox" name="geosite" value="1" />
				geosite
			</label>
			<br><br>
			<input class="btn cbi-button cbi-button-apply" type="button" id="update_rules_btn" onclick="update_rules(this)" value="<%:Manually update%>" />
			<% if has_old_geoip then %>
			<input class="btn cbi-button cbi-button-reset" type="button" onclick="rollback_rules(this, 'geoip')" value="<%:Rollback%> GeoIP" />
			<% end %>
			<% if has_old_geosite then %>
			<input class="btn cbi-button cbi-button-reset" type="button" onclick="rollback_rules(this, 'geosite')" value="<%:Rollback%> Geosite" />
			<% end %>
		</div>
	</div>
</div>

<script type="text/javascript">
	//<![CDATA[
	document.addEventListener('DOMContentLoaded', function () {
		const flags = [
			"gfwlist_update","chnroute_update","chnroute6_update",
			"chnlist_update","geoip_update","geosite_update"
		];
		const bindFlags = () => {
			let allBound = true;
			flags.forEach(flag => {
				const orig = Array.from(document.querySelectorAll(`input[name$=".${flag}"]`)).find(i => i.type === 'checkbox');
				if (!orig) { allBound = false; return; }
				// 隐藏最外层 div
				const wrapper = orig.closest('.cbi-value');
				if (wrapper && wrapper.style.display !== 'none') {
					wrapper.style.display = 'none';
				}
				const custom = document.querySelector(`.cbi-input-checkbox[name="${flag.replace('_update','')}"]`);
				if (!custom) { allBound = false; return; }
				custom.checked = orig.checked;
				// 自定义选择框与原生Flag双向绑定
				if (!custom._binded) {
					custom._binded = true;
					orig.addEventListener('change', () => {
						custom.checked = orig.checked;
					});
					custom.addEventListener('change', () => {
						orig.checked = custom.checked;
						orig.dispatchEvent(new Event('change', { bubbles: true }));
					});
				}
			});
			return allBound;
		};

		const geo2ruleFlag = () => {
			const geoEl = document.querySelector('input[type="checkbox"][name*="passwall"][name*="geo2rule"]');
			if (!geoEl) return;
			const updateCheckboxes = (disabled) => {
				flags.filter(flag => !flag.includes('geo')).forEach(flag => {
					const custom = document.querySelector(`.cbi-input-checkbox[name="${flag.replace('_update','')}"]`);
					if (custom) {
						//if (disabled) custom.checked = true;
						custom.parentElement.style.display = disabled ? 'none' : '';
					}
				});
			};
			updateCheckboxes(geoEl.checked);
			geoEl.addEventListener("change", () => {
				geoEl.blur();
				updateCheckboxes(geoEl.checked);
			});
		};

		const bindAll = () => {
			bindFlags();
			geo2ruleFlag();
		};

		const target = document.querySelector('form') || document.body;
		const observer = new MutationObserver(() => bindAll() ? observer.disconnect() : 0);
		observer.observe(target, { childList: true, subtree: true });
		const timer = setInterval(() => bindAll() ? (clearInterval(timer), observer.disconnect()) : 0, 300);
		setTimeout(() => { clearInterval(timer); observer.disconnect(); }, 5000);
	});

	function update_rules(btn) {
		btn.disabled = true;
		btn.value = '<%:Updating...%>';
		var div = document.getElementById('_rule_div');
		var domList = div.getElementsByTagName('input');
		var checkBoxList = [];
		var len = domList.length;
		while(len--) {
			var dom = domList[len];　　
			if(dom.type == 'checkbox' && dom.checked) {
				checkBoxList.push(dom.name);
			}
		}
		XHR.get('<%=api.url("update_rules")%>', {
				update: checkBoxList.join(",")
			},
			function(x, data) {
				if(x && x.status == 200) {
					window.location.href = '<%=api.url("log")%>';
				} else {
					alert("<%:Error%>");
					btn.disabled = false;
					btn.value = '<%:Manually update%>';
				}
			}
		);
	}

	function rollback_rules(btn, type) {
		let ori_val = btn.value;
		btn.disabled = true;
		btn.value = '<%:Rollbacking...%>';
		var div = document.getElementById('_rule_div');
		var domList = div.getElementsByTagName('input');
		var checkBoxList = [];
		var len = domList.length;
		while(len--) {
			var dom = domList[len];　　
			if(dom.type == 'checkbox' && dom.checked) {
				if(type == 'geoip' && (dom.name === 'chnroute' || dom.name === 'chnroute6')) {
					checkBoxList.push(dom.name);
				}
				if(type == 'geosite' && (dom.name === 'gfwlist' || dom.name === 'chnlist')) {
					checkBoxList.push(dom.name);
				}
			}
		}
		XHR.get('<%=api.url("rollback_rules")%>', {
			type: type,
			rules: checkBoxList.join(",")
			},
			function(x, data) {
				if(x && x.status == 200 && data.code == 1) {
					alert("<%:Success%>");
					btn.style.display = "none";
				} else {
					alert("<%:Error%>");
					btn.disabled = false;
					btn.value = ori_val;
				}
			}
		);
	}

	//分流规则添加拖拽排序
	document.addEventListener("DOMContentLoaded", function () {
		function initSortableForTable() {
			var section = document.getElementById("cbi-<%=api.appname%>-shunt_rules");
			if (!section) return;

			hideSortColumn(section);

			// === 插入 drag handle ===
			var rows = section.querySelectorAll("tr");
			rows.forEach(function(row) {
				var btn = row.querySelector(".cbi-button-remove:last-of-type");
				if (!btn) return;
				if (btn.nextElementSibling && btn.nextElementSibling.classList.contains("drag-handle")) return;
				var handle = document.createElement("span");
				handle.className = "drag-handle center";
				handle.title = "<%:Drag to reorder%>";
				handle.innerHTML = "⠿";
				btn.after(handle);
			});

			// === 初始化 Sortable ===
			var table = section.getElementsByTagName("table")[0];
			if (!table) return;
			var root = table.tBodies[0] || table;
			if (root._sortable_initialized) return root._sortable_instance;
			root._sortable_initialized = true;

			// 保存原始顺序
			root._origOrder = getCurrentOrder(root);

			try {
				root._sortable_instance = Sortable.create(root, {
					handle: ".drag-handle",
					draggable: "tr.cbi-section-table-row",
					animation: 150,
					ghostClass: "dragging-row",
					fallbackOnBody: true,
					forceFallback: false,
					swapThreshold: 0.65,
					onEnd: function (evt) {
						updateHiddenInput(root, section);
					}
				});
				return root._sortable_instance;
			} catch (e) {
				root._sortable_initialized = false;
				console.error("Sortable init failed:", e);
			}
		}

		// 获取 table 当前行顺序
		function getCurrentOrder(root) {
			var order = [];
			var rows = root.querySelectorAll("tr.cbi-section-table-row");
			rows.forEach(function (tr) {
				var id = tr.id || "";
				if (id.startsWith("cbi-<%=api.appname%>-"))
					id = id.replace("cbi-<%=api.appname%>-", "");
				order.push(id);
			});
			return order;
		}

		// 拖拽完成后更新 hidden input
		function updateHiddenInput(root, section) {
			var newOrder = getCurrentOrder(root);
			var changed = newOrder.join(" ") !== root._origOrder.join(" ");
			var hiddenInput = section.querySelector('input[type="hidden"][id^="cbi.sts."]');
			if (hiddenInput) {
				hiddenInput.value = changed ? newOrder.join(" ") : "";
			}
		}

		// 隐藏18.06 up/down 列
		function hideSortColumn(section) {
			var table = section.getElementsByTagName("table")[0];
			if(!table) return;
			var rows = table.querySelectorAll("tr.cbi-section-table-row");
			if(!rows.length) return;
			var colCount = rows[0].children.length, sortCol = -1;
			for(var col=0; col<colCount; col++){
				var hasSort=false, invalid=false;
				rows.forEach(function(tr){
					var td=tr.children[col]; if(!td) return;
					if(td.querySelector(".cbi-button-edit, .cbi-button-remove")) invalid=true;
					if(td.querySelector(".cbi-button-up, .cbi-button-down")) hasSort=true;
				});
				if(!invalid && hasSort){ sortCol=col; break; }
			}
			if(sortCol===-1) return;
			table.querySelectorAll("tr").forEach(function(tr){
				var c=tr.children[sortCol]; if(c) c.style.display="none";
			});
		}

		// === 等待 TypedSection 行稳定 ===
		(function waitStable() {
			var last = 0, stable = 0;
			var THRESHOLD = 5;
			function tick() {
				var count = document.querySelectorAll("tr.cbi-section-table-row").length;
				if (count && count === last) stable++;
				else stable = 0;

				last = count;
				if (stable >= THRESHOLD)
					setTimeout(initSortableForTable, 200);
				else
					requestAnimationFrame(tick);
			}
			tick();
		})();
	});
	//]]>
</script>
