import React from 'react';
import {TreeNode, Tree} from '../helpers/tree'
import Row from '../../modules/Row';
import Col from '../../modules/Col';
import BaseHolder from '../../modules/BaseHolder';
import {View as Div, StyleSheet} from 'react-native';

function log(...m) {
	console.log(...m);
}
export class ViewNode extends TreeNode {
	constructor(id,value, props, namespace = "default"){
		super(id);
		this.value = value; // constructor Component
		this.namespace = namespace;
		this.props = props || {};
	}
}

export class Node extends TreeNode {
	constructor(id, props, content) {
		super(id);
		this.ctor = BaseHolder;
		this.props = props || {};
		if(content){
			this.content = content; // this is a viewNode
		}
	}
}

export default class ViewSystem {
	constructor(MS, ES) {
		this.views = {};
		this.ModuleSystem = MS;
		this.EventSystem = ES;
	}

	getNode(ViewId, NodeId) {
		return this.views[ViewId].getNode(NodeId);
	}

	getView(name) {
		return this.views[name];
	}
	addView(name, view) {
		this.views[name] = view;
		return view;
	}

	removeView(name) {
		let view = this.views[name];
		delete this.views[name];
		return view;
	}

	render(name) {
		return this.views[name].render(this.ModuleSystem, this.EventSystem);
	}

	export() {
		let views = {};

		for(var i in this.views) {
			views[i] = this.views[i].export();
		}

		return {
			views
		}
	}

	import(data) {
		let { views } = data;

		for(var i in views) {
			this.views[i] = new View().import(views[i]);
		}

		return this;
	}

	ray(viewId, x, y, id) {
		let tree = this.views[viewId].ViewTree;

	}
}

export class View {
	constructor(){
		this.ViewTree = new Tree();
		let rootNode = new Node(Math.random(), {stretchContainer: true, selected: true}); // row
		this.addViewNode(rootNode);
		// this.setColumns(rootNode, 1);
		this.defaultContainer = rootNode;
	}

	getDefaultContainer() {
		return this.defaultContainer;
	}

	getRoot() {
		return this.ViewTree.root;
	}
	getNode(id) {
		return this.ViewTree.getNode(id);
	}

	has(node) {
		if (typeof node !== "object") return this.getNode(node);
		return this.getNode(node.id);
	}

	render(MS, ES) {
		let node = this.ViewTree.root;
		return (<Renderer ModuleSystem={MS} EventSystem={ES} node={node} tree={this.ViewTree}/>);	
	}

	addViewNode(node,parentNode = null){
		this.ViewTree.insert(node,parentNode);
		return this;
	}

	setContent(content, container) {
		container.content = content;
		return this;
	}

	getParent(node) {
		return this.getNode(this.ViewTree.getParent(node));
	}

	getRows(column) {
		log("Deprecated for now")
		return true;
		if(!column.isCol) {
			throw new Error("You must pass a ColNode to this function");
		}
		return this.getChildren(column);
	}
	setRows(column, rows = 1) {
		log("Deprecated for now")
		return true;
		if(!column.isCol) 	throw new Error("You must pass a ColNode to this function");
		if(rows < 1) 	throw new Error("Only positive rows");

		let colChildren = this.getChildren(column);
		if (colChildren.length > rows) {
			for(var i = rows; i < colChildren.length; i++) {
				let row = colChildren[i];
				if(row.content) {
					if(confirm("Are you sure you want to remove this row it has content?"))
						this.remove(row);
				} else {
					this.remove(row);				}
			}
		} else {
			for(var i = colChildren.length; i < rows; i++)
				this.addViewNode(new Node(Math.random(), true), column); // row
		}
		return this.getRows(column);
	}

	getColumns(row) {
		log("Deprecated for now")
		return true;
		if(!row.isRow) {
			throw new Error("You must pass a RowNode to this function");
		}
		return this.getChildren(row);
	}
	setColumns(row, columns = 1) {
		log("Deprecated for now")
		return true;
		if(!row.isRow) 	throw new Error("You must pass a RowNode to this function");
		if(columns < 1) throw new Error("Only positive cols");

		let rowChildren = this.getChildren(row);
		if (rowChildren.length > columns) {
			for(var i = columns; i < rowChildren.length; i++) {
				let col = rowChildren[i];
				if(col.content) {
					if(confirm("Are you sure you want to remove this col it has content?"))
						this.remove(col);
				} else {
					this.remove(col);
				}
			}
		} else {
			for(var i = rowChildren.length; i < columns; i++) {
				this.addViewNode(new Node(Math.random()), row);
			}
		}
		return this.getColumns(row);
	}
	addGrid(column, rowSize, columnSize) {
		log("Deprecated for now")
		return true;
		this.setRows(column, rowSize)
		.forEach(row => this.setColumns(row, columnSize)
		.forEach(col => col.content = new ViewNode(
			Math.random(),
			"BaseContainer",
			{}
		)));
	}
	remove(node) {
		if(node === root) {
			console.log("Cannot remove Root node", node);
			return this;
		}
		this.ViewTree.remove(node);
		return this;
	}

	replace(oldNode,newNode){
		this.ViewTree.replaceNode(oldNode,newNode);
		return this;
	}

	getChildren(node) {
		return this.ViewTree.getChildren(node);
	}

	import(data) {
		let { tree } = data;
		this.ViewTree = new Tree();
		try {
			this.ViewTree.import(tree, Node);
			this.defaultContainer = this.ViewTree.root;
		} catch(e) {
			log(e);
			throw new Error("ViewSystem import error : ", e);
		}
		return this;
	}

	export() {
		let tree = this.ViewTree.export();
		return {
			tree
		};
	}
}
/// Node = Container -> Everywhere Containers
//  Content is Node.content Container property.
//  When Content is present, Container for Containers is stretchedToContent
//  IF NOT -> just be placed there.
//  


let Renderer = (props) => {
	let { node , tree, ModuleSystem, EventSystem } = props;
	let childrens = tree.getChildren(node);
	let childrenReact = childrens.map(child => {
		return(
		<Renderer node = {child}
				tree={tree}
				key={child.id} 
				ModuleSystem={ModuleSystem}
				EventSystem={EventSystem} />)
	});
		
	let viewNode = node.content;
	let ViewNodeReact;
	// IF CONTENT
	if(viewNode) {
		// Create ref
		ModuleSystem.createRef(viewNode.id);
		// Crete element
		ViewNodeReact = ModuleSystem.createElement(
			viewNode.value,
			{ 
				...viewNode.props,
				ModuleID: viewNode.id,
				EventSystem: EventSystem
			},
			[], // children
			viewNode.namespace,
			viewNode.id
		);
	}
	ModuleSystem.createRef(node.id);
	return ModuleSystem.createElementCtor(
		node.ctor, 
		{
			...node.props,
			depth: node.depth,
			content: ViewNodeReact,
			ID: node.id
		},
		childrenReact,
		node.id
	);
}

const styles = StyleSheet.create({
	colWrapper: {
		"position": "absolute",
		"left": 0,
		"bottom": 0,
		"right": 0,
		"top": 0
	}
})