import { ExtensionContext, TreeDataProvider, EventEmitter, TreeItem, Event, window, TreeItemCollapsibleState, Uri, commands, workspace, TextDocumentContentProvider, CancellationToken, ProviderResult } from 'vscode';
import * as os from 'os';
import * as path from 'path';

interface IEntry {
	name: string;
	type: string;
}

type TreeNode = ConnectionNode | FolderNode

export class FolderNode {
	constructor(public name:string, public children : TreeNode[]) {
	}
}

export class ConnectionNode {

	constructor(public name:string, public host:string, public port:Number, public schema:String, public username:String, public password:String) {
	}
}

export class ConnectionModel {

	constructor(public data:any) {
	}

	private traverse(data) : TreeNode[] {
		return data['items'].map( (x) => {
			if (x['type'] == 'connection') {
				return new ConnectionNode(x['name'], x['host'], x['port'], x['sid'], x['username'], x['password'])
			} else {
				return new FolderNode(x['name'], this.traverse(x))
			}
		});
	}

	public get roots(): Thenable<TreeNode[]> {
		let list : TreeNode[] = this.traverse(this.data);
        return new Promise((c, e) => c(list));
	}

	public getChildren(node: TreeNode): Thenable<TreeNode[]> {
		if (node instanceof FolderNode) {
			return new Promise((c, e) => c(node.children)); 
		} else {
			return new Promise((c, e) => c([])); 
		}
	}
}

export class ConnectionProvider implements TreeDataProvider<TreeNode>, TextDocumentContentProvider {

	private _onDidChangeTreeData: EventEmitter<any> = new EventEmitter<any>();
	readonly onDidChangeTreeData: Event<any> = this._onDidChangeTreeData.event;

	private model: ConnectionModel;

	public getTreeItem(element: TreeNode): TreeItem {
		if (element instanceof FolderNode) {
			return {
				label: element.name,
				collapsibleState: TreeItemCollapsibleState.Collapsed,
				command: void 0				
			}
		} else {
			return {
				label: element.name,
				collapsibleState: void 0,
				command: {
					command: 'selectConnection',
					arguments: [element],
					title: 'Open Connection'
				}
			}
		}
	}

	public getChildren(element?: TreeNode): TreeNode[] | Thenable<TreeNode[]> {
		if (!element) {
			if (!this.model) {
				let data = require(os.homedir() + '/.frog.json');
				this.model = new ConnectionModel(data);
			}

			return this.model.roots;
		}

		if (element instanceof FolderNode) {
			return element.children;
		} else {
			return [];
		}
    }
    
    public provideTextDocumentContent(uri: Uri, token: CancellationToken): ProviderResult<string> {
		return "nix";
	}
}