#!/usr/bin/lua

local sysconfig = require 'gluon.sysconfig'


if sysconfig.primary_mac then
	os.exit(0)
end


local json = require 'jsonc'
local platform = require 'gluon.platform'
local util = require 'gluon.util'

local board_data = json.load('/etc/board.json')
local network_data = (board_data or {}).network

local function read(...)
	local addr = util.readfile(string.format(...))
	if addr then
		return util.trim(addr)
	end
end

local function get_netdev_addr(ifname)
	return read('/sys/class/net/%s/address', ifname)
end

local function strip_vlan(ifname)
	return (ifname:gsub('%..*', ''))
end


local function netdev(ifname)
	return function()
		return get_netdev_addr(ifname)
	end
end

local function phy(index)
	return function()
		return read('/sys/class/ieee80211/phy%d/macaddress', index)
	end
end

local function interface(name)
	return function()
		local ifdata = network_data[name] or {}
		if ifdata.macaddr then
			return ifdata.macaddr
		elseif ifdata.ifname then
			return get_netdev_addr(strip_vlan(ifdata.ifname))
		end
	end
end

local function label_mac()
	return function()
		local mac = util.exec('/lib/gluon/label_mac.sh')

		if mac == nil then return nil end

		mac = util.trim(mac)
		if string.len(mac) ~= 17 then return nil end

		return mac
	end
end


-- Entries are matched in the order they are listed
local primary_addrs = {
	{interface('lan'), {
		{'ath79', 'generic', {
			'glinet,gl-ar750s-nor',
			'ocedo,raccoon',
			'tplink,archer-a7-v5',
			'tplink,archer-c2-v3',
			'tplink,archer-d50-v1',
		}},
		{'brcm2708'},
		{'ipq40xx', 'generic', {
			'avm,fritzbox-4040',
			'meraki,mr33',
			'plasmacloud,pa1200',
			'plasmacloud,pa2200',
		}},
		{'ipq806x', 'generic', {
			'netgear,r7800',
		}},
		{'lantiq', 'xrx200', {
			'arcadyan,vgv7510kw22-nor',
		}},
		{'lantiq', 'xway', {
			'netgear,dgn3500b',
		}},
		{'mediatek', 'filogic', {
			'asus,tuf-ax4200',
			'asus,tuf-ax6000',
		}},
		{'ramips', 'mt7620', {
			'netgear,ex3700',
			'tplink,archer-c2-v1',
			'tplink,archer-c20-v1',
			'tplink,archer-c20i',
			'tplink,archer-c50-v1',
		}},
		{'ramips', 'mt76x8', {
			'xiaomi,mi-router-4a-100m',
		}},
		{'rockchip', 'armv8', {
			'friendlyarm,nanopi-r2s',
			'friendlyarm,nanopi-r3s',
			'friendlyarm,nanopi-r4s',
		}},
		{'x86'},
	}},
	{interface('wan'), {
		{'ipq40xx', 'generic', {
			'linksys,ea6350v3',
			'openmesh,a42',
			'openmesh,a62',
		}},
		{'kirkwood', 'generic', {
			'linksys,e4200-v2',
			'linksys,ea4500',
		}},
		{'mpc85xx', 'p1020', {
			'aerohive,hiveap-330',
			'ocedo,panda',
		}},
		{'mpc85xx', 'p1010', {
			'enterasys,ws-ap3715i',
		}},
		{'ramips', 'mt7620', {
			'xiaomi,miwifi-mini',
			'asus,rt-ac51u',
		}},
	}},
	{phy(1), {
		{'ramips', 'mt7621', {
			'dlink,dir-860l-b1',
		}},
	}},
	-- label-mac-device default
	{label_mac(), {
		{}, -- matches everything
	}},
	-- phy0 default
	{phy(0), {
		{}, -- matches everything
	}},
	-- eth0 fallback when phy0 does not exist
	{netdev('eth0'), {
		{}, -- matches everything
	}},
}


for _, matcher in ipairs(primary_addrs) do
	local f, matches = unpack(matcher)

	for _, match in ipairs(matches) do
		if platform.match(unpack(match)) then
			local addr = f()
			if addr then
				sysconfig.primary_mac = addr:lower()
				return
			end
		end
	end
end

error('no primary MAC address found')
