/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the Source EULA. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import * as nls from 'vscode-nls';
import { IJupyterBookSection, IJupyterBookToc } from '../contracts/content';
const localize = nls.loadMessageBundle();

export enum BookTreeItemType {
	Book = 'Book',
	Notebook = 'Notebook',
	Markdown = 'Markdown',
	ExternalLink = 'ExternalLink'
}

export interface BookTreeItemFormat {
	title: string;
	root: string;
	tableOfContents: IJupyterBookToc;
	page: any;
	type: BookTreeItemType;
	treeItemCollapsibleState: number;
	isUntitled: boolean;
}

export class BookTreeItem extends vscode.TreeItem {
	private _sections: IJupyterBookSection[];
	private _uri: string;
	private _previousUri: string;
	private _nextUri: string;
	public command: vscode.Command;

	constructor(public book: BookTreeItemFormat, icons: any) {
		super(book.title, book.treeItemCollapsibleState);

		if (book.type === BookTreeItemType.Book) {
			this.collapsibleState = book.treeItemCollapsibleState;
			this._sections = book.page;
			if (book.isUntitled) {
				this.contextValue = 'untitledBook';
			} else {
				this.contextValue = 'savedBook';
			}
		} else {
			this.setPageVariables();
			this.setCommand();
		}
		this.iconPath = icons;
	}

	private setPageVariables() {
		this.collapsibleState = (this.book.page.sections || this.book.page.subsections) && this.book.page.expand_sections ?
			vscode.TreeItemCollapsibleState.Expanded :
			this.book.page.sections || this.book.page.subsections ?
				vscode.TreeItemCollapsibleState.Collapsed :
				vscode.TreeItemCollapsibleState.None;
		this._sections = this.book.page.sections || this.book.page.subsections;
		this._uri = this.book.page.url;

		let index = (this.book.tableOfContents.sections.indexOf(this.book.page));
		this.setPreviousUri(index);
		this.setNextUri(index);
	}

	private setCommand() {
		if (this.book.type === BookTreeItemType.Notebook) {
			let pathToNotebook = path.join(this.book.root, 'content', this._uri.concat('.ipynb'));
			this.command = { command: this.book.isUntitled ? 'bookTreeView.openUntitledNotebook' : 'bookTreeView.openNotebook', title: localize('openNotebookCommand', "Open Notebook"), arguments: [pathToNotebook], };
		} else if (this.book.type === BookTreeItemType.Markdown) {
			let pathToMarkdown = path.join(this.book.root, 'content', this._uri.concat('.md'));
			this.command = { command: 'bookTreeView.openMarkdown', title: localize('openMarkdownCommand', "Open Markdown"), arguments: [pathToMarkdown], };
		} else if (this.book.type === BookTreeItemType.ExternalLink) {
			this.command = { command: 'bookTreeView.openExternalLink', title: localize('openExternalLinkCommand', "Open External Link"), arguments: [this._uri], };
		}
	}

	private setPreviousUri(index: number): void {
		let i = --index;
		while (i > -1) {
			if (this.book.tableOfContents.sections[i].url) {
				// TODO: Currently only navigating to notebooks. Need to add logic for markdown.
				let pathToNotebook = path.join(this.book.root, 'content', this.book.tableOfContents.sections[i].url.concat('.ipynb'));
				// tslint:disable-next-line:no-sync
				if (fs.existsSync(pathToNotebook)) {
					this._previousUri = pathToNotebook;
					return;
				}
			}
			i--;
		}
	}

	private setNextUri(index: number): void {
		let i = ++index;
		while (i < this.book.tableOfContents.sections.length) {
			if (this.book.tableOfContents.sections[i].url) {
				// TODO: Currently only navigating to notebooks. Need to add logic for markdown.
				let pathToNotebook = path.join(this.book.root, 'content', this.book.tableOfContents.sections[i].url.concat('.ipynb'));
				// tslint:disable-next-line:no-sync
				if (fs.existsSync(pathToNotebook)) {
					this._nextUri = pathToNotebook;
					return;
				}
			}
			i++;
		}
	}

	public get title(): string {
		return this.book.title;
	}

	public get uri(): string {
		return this._uri;
	}

	public get root(): string {
		return this.book.root;
	}

	public get tableOfContents(): IJupyterBookToc {
		return this.book.tableOfContents;
	}

	public get sections(): any[] {
		return this._sections;
	}

	public get previousUri(): string {
		return this._previousUri;
	}

	public get nextUri(): string {
		return this._nextUri;
	}

	get tooltip(): string {
		if (this.book.type === BookTreeItemType.ExternalLink) {
			return `${this._uri}`;
		}
		else {
			return undefined;
		}
	}

	/**
	 * Helper method to find a child section with a specified URL
	 * @param url The url of the section we're searching for
	 */
	public findChildSection(url?: string): IJupyterBookSection | undefined {
		if (!url) {
			return undefined;
		}
		return this.findChildSectionRecur(this, url);
	}

	private findChildSectionRecur(section: IJupyterBookSection, url: string): IJupyterBookSection | undefined {
		if (section.url && section.url === url) {
			return section;
		} else if (section.sections) {
			for (const childSection of section.sections) {
				const foundSection = this.findChildSectionRecur(childSection, url);
				if (foundSection) {
					return foundSection;
				}
			}
		}
		return undefined;
	}
}
