/*jslint browser: true*/

"use strict";

/*jshint esversion: 6 */
class tedi2tex extends tedi2lang {
	constructor() {
		const td = {

			start_heading_first_level_tag:"\\section{",
			start_heading_second_level_tag:"\\subsection{",
			start_heading_third_level_tag:"\\subsubsection{",
			start_heading_fourth_level_tag:"\\subsubsection{",

			end_heading_first_level_tag:"}",
			end_heading_second_level_tag:"}",
			end_heading_third_level_tag:"}",
			end_heading_fourth_level_tag:"}",

			start_list_tag:"\\begin{itemize}",
			list_item_tag:"\\item ",
			end_list_tag:"\\end{itemize}",

			start_container_tag:"",
			middle_container_tag:"",
			end_container_tag:"",

			start_link_tag:"\\href{",
			middle_link_tag:"}{",
			end_link_tag:"}",

			start_image_tag:"\\begin{figure}[h!]\n\\centering\n\\includegraphics[width=1\\textwidth]{",
			middle_image_tag:"",
			end_image_tag:"",

			start_table_tag:"",
			end_table_tag:"\\hline\n\\end{longtable}",
			start_table_row_tag:"\\hline",
			end_table_row_tag:"\\tabularnewline",
			start_table_data_tag:" & ",
			end_table_data_tag:"",

			end_paragraph_tag:"\n"
		   
		};
		super(td);
	}
	/*
	 * Underscores are subscripts in LaTeX
	 *
	 */
	escape_underscores(line) {
		let underscore = line.find('_');
		while(this.found(underscore)) {
			let start_list_tag = line.find("__");
			if(!this.found(start_list_tag))
				line = line.insert(underscore, 1, '\\');
			underscore = line.find('_', underscore + 2);
		}
		return line;
	}
	
	/*
	 * Main logic converting line. 
	 *
	 */
	convert_line(line) {
		if(line[0] != '<') {
		
			line = this.escape_underscores(line);
			
			let end_table = this.convert_end_table(line);
			let hash = line.find('#');

			if(this.found(hash) && this.is_first_tag(line, hash))
				return end_table + this.convert_line_heading(line, hash);
			else {
				let ul = line.find("__");
				if(this.found(ul))
					return end_table + this.convert_line_list_start(line);
				else {
					this._line = line;
					let li = this._line.find("--");
					if(this.found(li) && this._is_unordered_list)
						this.convert_line_list_item(li);
					
					let ul_end = this._line.find(",,");
					if(this.found(ul_end) && this._is_unordered_list)
						return end_table + this.convert_line_list_end(line);
					else {
						if(this._line[0] == '"')
							this.convert_line_quote();
						else
							this.convert_unquoted_tags();
						
						let first_pipe = this._line.find("|");
						if(this.found(first_pipe))
							return this.convert_line_table(first_pipe);
						else
							return end_table + this.convert_line_ending(this._line);
						
					}
				}
			}
		} else
			return this.convert_end_table_control_tags(line) + this.convert_line_control_tags(line);
		
	}
	
	/*
	 * Deletes image tag and insert image tag
	 *
	 */
	convert_line_image() {

		let start_tag = this.get_not_escaped_tag("([");
		if(this.found(start_tag) && !this.is_tag_escaped(start_tag)) {

			this._line = this._line.erase(start_tag, 2);

			let square_bracket = this.get_not_escaped_tag("] ");
			if(this.found(square_bracket) && !this.is_tag_escaped(square_bracket)) {
			
				let caption = this._line.substr(start_tag, square_bracket - start_tag);

				this._line = this._line.erase(start_tag, square_bracket + 2 - start_tag);
				this._line = this._line.insert(start_tag, this._start_image_tag);

				let last_parenthesis = this.correct_position(start_tag + this._middle_image_tag.size(), '(', ')');
				if(this.found(last_parenthesis)) {
					this._line = this._line.erase(last_parenthesis, 1);
					this._line = this._line.insert(last_parenthesis, "}\n\\caption{" + caption + "}\n\\end{figure}");
				} else
					throw "Missing ')' in images tag." + this._line;
			} else
				throw "Missing ']' in images tag." + this._line;
		} else
			throw "Missing images tag." + this._line;

	}
	
	/*
	 * Deletes block tag and insert block tag
	 *
	 */
	convert_line_block() {
		
		let start_tag = this.get_not_escaped_tag("{(");
		if(this.found(start_tag) && !this.is_tag_escaped(start_tag)) {

			this._line = this._line.erase(start_tag, 2);
			this._line = this._line.insert(start_tag, this._start_container_tag);

			let parenthesis = this.get_not_escaped_tag(") ");
			if(this.found(parenthesis) && !this.is_tag_escaped(parenthesis)) {
				this._line = this._line.erase(start_tag, parenthesis - start_tag + 2);

				let end_tag = this.correct_position(start_tag + this._middle_container_tag.size(), '{', '}');
				if(this.found(end_tag)) {
					this._line = this._line.erase(end_tag, 1);

				} else
					++this._open_brackets;
				
			} else
				throw "Missing ')' in block tag." + this._line;
		} else
			throw "Missing block tag." + this._line;

		this._has_block = true;
	}
	
	/*
	 * Start or continue table conversion
	 *
	 */
	convert_line_table(first_pipe) {
		let return_text = "";
		if(!this._is_converting_table) {
			if(first_pipe != -1 && first_pipe != this._line.lastIndexOf("\|")) {
				return_text = this.get_table_start_tag();
				this._is_converting_table = true;
				return return_text + this.convert_line_table_row(this._line);
			} else
				return this.convert_line_ending(this._line);
		}else
			return this.convert_line_table_row(this._line);

	}
	
	/*
	 * Convert every cell of one table row
	 *
	 */
	convert_line_table_row(line) {

		let pipe = line.find("|");
		if(this.found(pipe)) {
			++pipe;
			let return_text = this._start_table_row_tag + "\n";
			line = line.substr(pipe, line.size() - 1);
			pipe = line.find("|");
			if(this.found(pipe)) {
				let size = line.size() - 1;
				if(line[size] == '|') {
					let start = true;
					while(this.found(pipe) && line[size] == '|') {
						if(!start) {
							return_text += this._start_table_data_tag;
						} else
							start = false;
						return_text += line.substr(0, pipe);
						++pipe;
						line = line.substr(pipe, size);
						pipe = line.find("|");
						size = line.size() - 1;
					}
					return return_text + this._end_table_row_tag + "\n";
				} else
					throw "Table not correctly written\n" +
						"Maybe there's a whitespace at end of line" + line;
			} else
				throw "Expected '|' in table" + this._line;
		} else
			throw "Expected '|' in table" + this._line;
	}
	
		/*
	 * Control tags:
	 * <!, <>, <+. <
	 */
	convert_line_control_tags(line) {
		if(line[1] != '!') {
			if(line[1] == '>') {
				line = line.erase(0,2);
				return line + "\n";
			} else if(line[1] == '+') {
				line = line.erase(0,2);
				return "\\begin{verbatim}\n" + line + "\n\\end{verbatim}\n\n";

			} else if(!this.found(line.find("!")) && !this.found(line.find("¡"))) {
				line = line.erase(0,1);
				return "\\verb!" + line + "!\n";
			} else if(!this.found(line.find("}")) && !this.found(line.find("{"))) {
				line = line.erase(0,1);
				return "\\verb{" + line + "}\n";
			} else {
				line = line.erase(0, 1);
				return "\\begin{verbatim}\n" + line + "\n\\end{verbatim}\n\n";
			}
		} else
			return "";
		
	}
	
		
	/*
	 * Check line ending and convert depending ending whitespace
	 *
	 */
	convert_line_ending(line) {
		line = this.strip_escaping(line);
		if(line[line.size() - 1] == ' ' && !this._is_unordered_list)
			return line + this._end_paragraph_tag + "\n";
		else
			return line + "\n";
	}
	
	get_table_start_tag() {

		let columns = this.get_table_columns(this._line);
		let start_table_tag = "\\begin{longtable}{";
		let size_per_column = 0.9 / columns;
		for(let i = 0; i < columns; ++i)
			start_table_tag += "|p{" + size_per_column + "\\linewidth}";
		start_table_tag += "|}\n";
		return start_table_tag;
	}
	
	get_table_columns(line) {
		let data = 0;
		let pipe = line.find("|");
		let size = line.size() - 1;
		while(this.found(pipe) && (line[size] == '|' || line[size - 1] == '|')) {
			++pipe;
			line = line.substr(pipe);
			pipe = line.find("|");
			size = line.size() - 1;
			++data;
		}
		return data - 1;
	}
	
}
