import React from 'react';
import {Node, Link, Graph} from '../helpers/graph'
import {TreeNode, Tree} from '../helpers/tree'
import ViewSystem from './ViewSystem';

function log(...m) {
	console.log(...m);
}

export class RouteNode extends Node {
	constructor(routeName, uri, view = null, defaultLink = null) {
		super(uri);
		this.routeName = routeName;
		this.uri = uri;
		this.view = view;
		this.defaultLink = defaultLink; // Goes to if no view is specified
	}

	hasView() {
		return !!this.view;
	}

	getDefaultLink() {
		return this.defaultLink;
	}
}

export default class RoutingSystem {
	constructor() {
		this.topology = new Graph();
		this.currentNode = null;
		this.homeNode = null;
	}

	setHome(home) {
		this.homeNode = home;
		this.currentNode = this.homeNode;
		return this;
	}

	addRouteNode(node, parent = this.rootNode) {
		this.topology.addNode(node);
		this.topology.linkNodes(node, parent);
		return this;
	}

	addRoute(route, routeName) {
		let acc = "";
		let nodeNames = route.split('.')
		.map((item, index) => {
			acc = [...acc, item];
			return acc.join('.');
		});
		//log("nodeNames");
		//log(nodeNames);
		let i = 0;
		while (i < nodeNames.length) {
			//log("Checking ", nodeNames[i]);
			if (!this.topology.has(nodeNames[i])) {
				//log("Creating ", nodeNames[i]);
				let temp = new RouteNode(routeName, nodeNames[i]);
				this.topology.addNode(temp);
				if( i > 0 ) {
					let parent = this.topology.getNode(nodeNames[i-1]);
					let link = this.topology.linkNodes(parent, temp);
					parent.defaultLink = link;
				}
			} else {
				log(" HAS ALREADY ", nodeNames[i]);
			}
			i++;
		}
		return this;
	}

	goTo(route) {
		return this.currentNode = route;
	}

	setView(route, view) {
		let node = this.topology.getNode(route);
		//this.topology.nodes[node.id].view = view;
		node.view = view;
		return this;
	}

	setDefaultLink(route, dest) {
		let node = route;
		let dst  = dest;
		let links= this.topology.getLinks(route).out;
		let link = new Link(node, dst); 
		if(!links.has(link)) {
			throw new Error(`There is no link from ${route} to ${dest}`);
		}
		node.defaultLink = link;
		return this;
	}

	getView(route) {
		let node = this.topology.getNode(route);
		return node.view;
	}
	getCurrentView() { 
		return this.topology.getNode(this.currentNode).view;
	}

	removeRoute(route) {
		let temp = this.topology.getNode(route);
		this.topology.removeNode(temp);
		return temp;
	}

	print() {
		log("Printing Routes: ");
		for(let node in this.topology.nodes) {
			log("Node: ", node)
			let outSet = this.topology.getLinks(node).out;
			outSet.forEach( link => log("Link to : ", link.to.id) );
		}
	}


	export() {
		
		let graph = this.topology.export();

		return {
			topology: graph,
			home : this.homeNode
		}
	}

	import(data) {
		let { topology, home } = data;
		try{ 
			this.topology.import(topology, RouteNode);
			this.setHome(home);
		} catch(e) {
			console.log(e);
			throw new Error("RS Import Failed: ");
		}
		return this;
	}
}