const codesByIcon = Object.assign(Object.create(null), {
	cancel: 'cancelled',
	himWarn: 'disturbance',
});

const linkTypesByCode = Object.assign(Object.create(null), {
	BB: 'stop-website',
	// IFOPT-based DHID
	// https://wiki.openstreetmap.org/wiki/DE:Key:ref:IFOPT
	// https://trid.trb.org/view/1435440
	IF: 'stop-dhid',
	OZ: 'transit-authority',
	// todo: `{type: 'I',code: 'TD',icoX: 1,txtN: '8010224'}`
	// todo: `{type: 'I',code: 'TE',icoX: 1,txtN: '8024001'}`
});

// todo: pass in tag list from hint reference, e.g.:
// "tagL": [
// 	"RES_JNY_H3" // H3 = level 3 heading? shown on overview
// ]
// "tagL": [
// 	"RES_JNY_DTL" // only shown in journey detail
// ]
// todo: https://github.com/public-transport/hafas-client/issues/5
// todo: expose h.type somehow
// todo: https://github.com/KDE/kpublictransport/blob/39ac8f9586b9300fa8a9ba0dec010e96fab9ab08/src/lib/backends/hafasmgateparser.cpp#L56-L72
// todo: h.sty

// SNCB:
// {
// 	"type": "A",
// 	"code": "60",
// 	"prio": 10,
// 	"icoX": 2,
// 	"txtN": "Reservierungspflicht"
// }
// {
// 	"type": "A",
// 	"code": "64",
// 	"prio": 110,
// 	"icoX": 2,
// 	"txtN": "Zuschlag"
// }
// {
// 	"type": "I",
// 	"code": "CON_OVERVIEW_TARIF_HINT",
// 	"icoX": 2,
// 	"txtN": "Für diese Strecke ist ein internationales Ticket notwendig."
// }

// DB:
// {
// 	"type": "C",
// 	"code": "",
// 	"icoX": 2,
// 	"txtN": "Current information available."
// }
// {
// 	"type": "H",
// 	"code": "text.connection.section.arrival.date.deviation",
// 	"icoX": 4,
// 	"txtN": "Arrival Wednesday, 2023-05-10"
// }
// {
// 	"type": "H",
// 	"code": "text.connection.section.departure.date.deviation",
// 	"icoX": 4,
// 	"txtN": "Departure Wednesday, 2023-05-10"
// }
// {
// 	"type": "C",
// 	"code": "",
// 	"icoX": 8,
// 	"txtN": "Includes trains requiring a reservation"
// }

// DB:
// {
// 	"type": "A",
// 	"code": "RP",
// 	"icoX": 7,
// 	"txtN": "RP"
// }
// on this `jny`:
// {
// 	"jid": "1|327365|0|80|-1",
// 	"prodX": 27,
// 	"status": "P",
// 	"isRchbl": true,
// 	"pos": {
// 		"x": 9837336,
// 		"y": 52241377
// 	},
// 	"ctxRecon": "T$A=1@O=Hamburg Hbf@L=8002549@a=0@$A=1@O=Freiburg(Breisgau) Hbf@L=8000107@a=0@$202305092207$202305100721$NJ   471$$1$$$$$$",
// 	"msgL": [
// 		{
// 			"type": "REM",
// 			"remX": 3,
// 			"sty": "I",
// 			"tagL": [
// 				"RES_JNY_DTL_L"
// 			],
// 			"sort": 818413568
// 		}
// 	],
// 	"approxDelay": true,
// 	"subscr": "F",
// 	"sumLDrawStyleX": 4,
// 	"resLDrawStyleX": 1,
// 	"durS": "091400"
// }

// todo bvg:
// {"type": "R", "code": "text.realtime.journey.cancelled", "icoX": 7, "txtN": ": S41"} with icon {"res": "rt_cancel"}

const parseHint = (ctx, h) => {
	// todo: C

	if (h.type === 'I' && h.code && h.txtN) {
		if (h.code in linkTypesByCode) {
			const text = h.txtN === 'NULL'
				? null
				: h.txtN;
			return {type: linkTypesByCode[h.code], text};
		}
		if (h.code === 'TW' && h.txtN[0] === '$') {
			return {type: 'local-fare-zone', text: h.txtN.slice(1)};
		}
		if (h.code === 'TW' && h.txtN[0] === '#') {
			return {type: 'foreign-id', text: h.txtN.slice(1)};
		}
	}

	const text = h.txtN && h.txtN.trim() || '';
	const icon = h.icon || null;
	const code = h.code || icon && icon.type && codesByIcon[icon.type] || null;

	if (h.type === 'M') {
		return {
			type: 'status',
			summary: h.txtS && h.txtS.trim() || '',
			code,
			text,
		};
	}

	if (h.type === 'L') {
		return {
			type: 'status',
			code: 'alternative-trip',
			text,
			tripId: h.jid,
		};
	}
	if (h.type === 'A' || h.type === 'I') {
		return {
			type: 'hint',
			code,
			text,
		};
	}

	if (
		h.type === 'D' || h.type === 'U' || h.type === 'R' || h.type === 'N'
		|| h.type === 'Y' || h.type === 'Q' || h.type === 'P'
	) {
		// todo: how can we identify the individual types?
		// todo: does `D` mean "disturbance"?
		return {
			type: 'status',
			code,
			text,
		};
	}

	return null;
};

export {
	parseHint,
};
