'use strict';
'require form';
'require fs';
'require ui';
'require tools.widgets as widgets';
'require dockerman.common as dm2';

/*
Copyright 2026
Docker manager JS for Luci by Paul Donald <newtwen+github@gmail.com> 
Based on Docker Lua by lisaac <https://github.com/lisaac/luci-app-dockerman>
LICENSE: GPLv2.0
*/


return dm2.dv.extend({
	load() {
		return Promise.all([

		]);
	},

	render() {

		// stuff JSONMap with {network: {}} to prime it with a new empty entry
		const m = new form.JSONMap({network: {}}, _('Docker - New Network'));
		m.submit = true;
		m.reset = true;

		let s = m.section(form.NamedSection, 'network', _('Create new docker network'));
		s.anonymous = true;
		s.nodescriptions = true;
		s.addremove = false;

		let o;

		o = s.option(form.Value, 'name', _('Network Name'),
			_('Name of the network that can be selected during container creation'));
		o.rmempty = true;

		o = s.option(form.ListValue, 'driver', _('Driver'));
		o.rmempty = true;
		o.value('bridge', _('Bridge device'));
		o.value('macvlan', _('MAC VLAN'));
		o.value('ipvlan',  _('IP VLAN'));
		o.value('overlay', _('Overlay network'));

		o = s.option(widgets.DeviceSelect, 'parent', _('Base device'));
		o.rmempty = true;
		o.create = false
		o.noaliases = true;
		o.nocreate = true;
		o.depends('driver', 'macvlan');

		o = s.option(form.ListValue, 'macvlan_mode', _('Mode'));
		o.rmempty = true;
		o.depends('driver', 'macvlan');
		o.default = 'bridge';
		o.value('bridge', _('Bridge (Support direct communication between MAC VLANs)'));
		o.value('private', _('Private (Prevent communication between MAC VLANs)'));
		o.value('vepa', _('VEPA (Virtual Ethernet Port Aggregator)'));
		o.value('passthru', _('Pass-through (Mirror physical device to single MAC VLAN)'));

		o = s.option(form.ListValue, 'ipvlan_mode', _('Ipvlan Mode'));
		o.rmempty = true;
		o.depends('driver', 'ipvlan');
		o.default='l3';
		o.value('l2', _('L2 bridge'));
		o.value('l3', _('L3 bridge'));

		o = s.option(form.Flag, 'ingress',
			_('Ingress'),
			_('Ingress network is the network which provides the routing-mesh in swarm mode'));
		o.rmempty = true;
		o.disabled = 0;
		o.enabled = 1;
		o.default = 0;
		o.depends('driver', 'overlay');

		o = s.option(form.DynamicList, 'options', _('Options'));
		o.rmempty = true;
		o.placeholder='com.docker.network.driver.mtu=1500';

		o = s.option(form.DynamicList, 'labels', _('Labels'));
		o.rmempty = true;
		o.placeholder='foo=bar';

		o = s.option(form.Flag, 'internal', _('Internal'), _('Restrict external access to the network'));
		o.rmempty = true;
		o.depends('driver', 'overlay');
		o.disabled = 0;
		o.enabled = 1;
		o.default = o.disabled;

		// if nixio.fs.access('/etc/config/network') and nixio.fs.access('/etc/config/firewall')then
		// 	o = s.option(form.Flag, 'op_macvlan', _('Create macvlan interface'), _('Auto create macvlan interface in Openwrt'))
		// 	o.depends('driver', 'macvlan')
		// 	o.disabled = 0
		// 	o.enabled = 1
		// 	o.default = 1
		// end

		o = s.option(form.Value, 'subnet', _('Subnet'));
		o.rmempty = true;
		o.placeholder = '10.1.0.0/16';
		o.datatype = 'ip4addr';

		o = s.option(form.Value, 'gateway', _('Gateway'));
		o.rmempty = true;
		o.placeholder = '10.1.1.1';
		o.datatype = 'ip4addr';

		o = s.option(form.Value, 'ip_range', _('IP range'));
		o.rmempty = true;
		o.placeholder='10.1.1.0/24';
		o.datatype = 'ip4addr';

		o = s.option(form.DynamicList, 'aux_address', _('Exclude IPs'));
		o.rmempty = true;
		o.placeholder = 'my-route=10.1.1.1';

		o = s.option(form.Flag, 'ipv6', _('Enable IPv6'));
		o.rmempty = true;
		o.disabled = 0;
		o.enabled = 1;
		o.default = o.disabled;

		o = s.option(form.Value, 'subnet6', _('IPv6 Subnet'));
		o.rmempty = true;
		o.placeholder='fe80::/10'
		o.datatype = 'ip6addr';
		o.depends('ipv6', 1);

		o = s.option(form.Value, 'gateway6', _('IPv6 Gateway'));
		o.rmempty = true;
		o.placeholder='fe80::1';
		o.datatype = 'ip6addr';
		o.depends('ipv6', 1);

		this.map = m;

		return m.render();

	},

	handleSave(ev) {
		ev?.preventDefault();

		const view = this;

		const map = this.map;
		if (!map)
			return Promise.reject(new Error(_('Form is not ready yet.')));

		const listToKv = view.listToKv;

		const toBool = (val) => (val === 1 || val === '1' || val === true);

		return map.parse()
			.then(() => {
				const get = (opt) => map.data.get('json', 'network', opt);
				const name = get('name');
				const driver = get('driver');
				const internal = toBool(get('internal'));
				const ingress = toBool(get('ingress'));
				const ipv6 = toBool(get('ipv6'));
				const subnet = get('subnet');
				const gateway = get('gateway');
				const ipRange = get('ip_range');
				const auxAddress = listToKv(get('aux_address'));
				const optionsList = listToKv(get('options'));
				const labelsList = listToKv(get('labels'));
				const subnet6 = get('subnet6');
				const gateway6 = get('gateway6');

				const createBody = {
					Name: name,
					Driver: driver,
					EnableIPv6: ipv6,
					IPAM: {
						Driver: 'default'
					},
					Internal: internal,
					Labels: labelsList,
				};

				if (subnet || gateway || ipRange
					|| (auxAddress && typeof auxAddress === 'object' && Object.keys(auxAddress).length)) {
					createBody.IPAM.Config = [{
						Subnet: subnet,
						Gateway: gateway,
						IPRange: ipRange,
						AuxAddress: auxAddress,
						AuxiliaryAddresses: auxAddress,
					}];
				}

				if (driver === 'macvlan') {
					createBody.Options = {
						macvlan_mode: get('macvlan_mode'),
						parent: get('parent'),
					};
				}
				else if (driver === 'ipvlan') {
					createBody.Options = {
						ipvlan_mode: get('ipvlan_mode'),
					};
				}
				else if (driver === 'overlay') {
					createBody.Ingress = ingress;
				}

				if (ipv6 && (subnet6 || gateway6)) {
					createBody.IPAM.Config = createBody.IPAM.Config || [];
					createBody.IPAM.Config.push({
						Subnet: subnet6,
						Gateway: gateway6,
					});
				}

				if (optionsList && typeof optionsList === 'object' && Object.keys(optionsList).length) {
					createBody.Options = Object.assign(createBody.Options || {}, optionsList);
				}

				if (labelsList && typeof labelsList === 'object' && Object.keys(labelsList).length) {
					createBody.Labels = Object.assign(createBody.Labels || {}, labelsList);
				}

				return createBody;
			})
			.then((createBody) => view.executeDockerAction(
				dm2.network_create,
				{ body: createBody },
				_('Create network'),
				{
					showOutput: false,
					showSuccess: false,
					onSuccess: (response) => {
						if (response?.body?.Warning) {
							view.showNotification(_('Network created with warning'), response.body.Warning, 5000, 'warning');
						} else {
							view.showNotification(_('Network created'), _('OK'), 4000, 'success');
						}
						window.location.href = `${this.dockerman_url}/networks`;
					}
				}
			))
			.catch((err) => {
				view.showNotification(_('Create network failed'), err?.message || String(err), 7000, 'error');
				return false;
			});
	},

	handleSaveApply: null,
	handleReset: null,

});
