

import * as POLYTOPES from './polytopes.js';

// face detection for the 600-cell


export function nodes_links(links, nodeid) {
	return links.filter((l) => l.source === nodeid || l.target === nodeid);
}


export function linked(links, n1, n2) {
	const ls = nodes_links(nodes_links(links, n1), n2);
	if( ls.length ) {
		return ls[0]
	} else {
		return false;
	}
}


function fingerprint(ids) {
	const sids = [...ids];
	sids.sort();
	return sids.join(',');
}


export function make_600cell() {
	const nodes = POLYTOPES.make_600cell_vertices();
	const links = POLYTOPES.auto_detect_edges(nodes, 12);
	return {
		nodes: nodes,
		links: links
	}
}

export function link_to_tetras(nodes, links, link) {
	const n1 = link.source;
	const n2 = link.target;
	const nl1 = nodes_links(links, n1).filter((l) => l.id !== link.id);
	const nl2 = nodes_links(links, n2).filter((l) => l.id !== link.id);
	const p1 = new Set();
	const p = new Set();
	for( const nl of nl1 ) {
		if( nl.source !== n1 ) {
			p1.add(nl.source);
		}
		if( nl.target !== n1 ) {
			p1.add(nl.target);
		}
	}
	for( const nl of nl2 ) {
		if( nl.source !== n2 && p1.has(nl.source) ) {
			p.add(nl.source);
		}
		if( nl.target !== n2 && p1.has(nl.target) ) {
			p.add(nl.target);
		}
	}
	const lp = Array.from(p);
	const seen = {};
	const tetras = [];
	for( const p1 of lp ) {
		for( const p2 of lp ) {
			if( p1 != p2 ) {
				if( linked(links, p1, p2) ) {
					const fp = fingerprint([n1, n2, p1, p2]);
					if( !seen[fp] ) {
						seen[fp] = true;
						tetras.push({fingerprint: fp, nodes: [n1, n2, p1, p2]})
					}
				}
			}
		}
	}
	return tetras;
}


export function auto_600cell_cells(nodes, links) {
	const seen = {};
	const tetras = [];
	links.map((link) => {
		link_to_tetras(nodes, links, link).map((lt) => {
			if( !seen[lt.fingerprint] ) {
				seen[lt.fingerprint] = true;
				tetras.push(lt.nodes);
			}
		})
	});

	return tetras;
}


function node_by_id(nodes, nid) {
	const ns = nodes.filter((n) => n.id === nid);
	return ns[0];
}


export function tetra_w(nodes, tetra) {
	let w = 0;
	for( const nid of tetra ) {
		const node = node_by_id(nodes, nid);
		w += node.w;
	}
	return w / 4;
}

export function sorted_600cells() {
	const cell600 = make_600cell();
	const tetras = auto_600cell_cells(cell600.nodes, cell600.links);
	const layers = tetras.map((t) => { return { "nodes": t, w: tetra_w(cell600.nodes, t) } });
	layers.sort((a, b) => b.w - a.w);
	return layers;
}

// const cell600 = make_600cell();

// const layers = sorted_600cells(cell600.nodes, cell600.links);
// for( const cell of layers ) {
// //	const fp = fingerprint(cell.nodes);
// 	console.log(`${cell.w} ${cell.nodes}`);
// }

export function make_layered_600cell() {
	const tetras = sorted_600cells()

	const LAYERS = [
		[ "00", 20 ],
		[ "01", 20 ], 
		[ "02", 30 ], 
		[ "03", 60 ], 
		[ "04", 60 ], 
		[ "05", 60 ], 
		[ "06", 20 ],
		[ "07", 60 ], 
		[ "08", 20 ],
		[ "09", 60 ], 
		[ "10", 60 ], 
		[ "11", 60 ], 
		[ "12", 30 ], 
		[ "13", 20 ], 
		[ "14", 20 ]
	];

	const vertices = {};
	const seen = {};
	let i = 0;

	for( const layer of LAYERS ) {
		const label = layer[0];
		const n = layer[1];
		vertices[label] = [];
		console.log(`Layer ${label} starting at ${i}`);
		for( const t of tetras.slice(i, i + n) ) {
			console.log(t);
			for( const n of t.nodes ) {
				if( !seen[n] ) {
					vertices[label].push(n);
					seen[n] = true;
				}
			}
		}
		i += n;
	}
	return JSON.stringify(vertices);
}


