/*jslint browser: true*/

"use strict";

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

			start_heading_first_level_tag:"<h1>",
			start_heading_second_level_tag:"<h2>",
			start_heading_third_level_tag:"<h3>",
			start_heading_fourth_level_tag:"<h4>",

			end_heading_first_level_tag:"</h1>",
			end_heading_second_level_tag:"</h2>",
			end_heading_third_level_tag:"</h3>",
			end_heading_fourth_level_tag:"</h4>",

			start_list_tag:"<ul>",
			list_item_tag:"<li>",
			end_list_tag:"</ul>",

			start_container_tag:"<div class=\"",
			middle_container_tag:"\">",
			end_container_tag:"</div>",

			start_link_tag:"<a href=\"",
			middle_link_tag:"\">",
			end_link_tag:"</a>",

			start_image_tag:"<img alt=\"",
			middle_image_tag:"\" src=\"",
			end_image_tag:"\">",

			start_table_tag:"<table>",
			end_table_tag:"</table>",
			start_table_row_tag:"<tr>",
			end_table_row_tag:"</tr>",
			start_table_data_tag:"<td>",
			end_table_data_tag:"</td>",

			end_paragraph_tag:""
		   
		};
		super(td);
		this._start_paragraph_tag = "";
	}
	
	/*
	 * Add header, iterate through text and finish with footer
	 *
	 */
	convert(text, header = "", footer = "") {
		let index = this.get_lines(text);
		
		let return_text = header;
		this._open_brackets = 0;
		this._is_converting_table = false;
		this._is_unordered_list = 0;
		this._is_paragraph = false;

		for(let i = 0; i < index.length; ++i) {
			this._has_image = false;
			this._has_block = false;
			let line = index[i];
			return_text += this.convert_line(line);
		}
		
		if(this._open_brackets > 0)
			throw "Missing '}' in document. End of file";
		if(this._is_converting_table) return_text += this._end_table_tag + "\n";
		if(this._is_paragraph) return_text += this._end_paragraph_tag + "\n";
		return_text += footer;

		return return_text;
	}
	
	/*
	 * Deletes heading tag and insert new heading tag
	 *
	 */
	convert_line_heading(line, hash_position) {

		let level = 0;
		while(this.found(hash_position) && line[hash_position + level] == '#')
			++level;

		if((hash_position + level) >= line.size())
			throw "Unexpected heading size" + line;
		else
			line = line.substring(hash_position + level, line.size());
		
		switch(level) {
			case 1: line = this._start_heading_first_level_tag + this.strip_escaping(line) + this._end_heading_first_level_tag; break;
			case 2: line = this._start_heading_second_level_tag + this.strip_escaping(line) + this._end_heading_second_level_tag; break;
			case 3: line = this._start_heading_third_level_tag + this.strip_escaping(line) + this._end_heading_third_level_tag; break;
			case 4: line = this._start_heading_fourth_level_tag + this.strip_escaping(line) + this._end_heading_fourth_level_tag; break;
			default: line = this._start_heading_fourth_level_tag + this.strip_escaping(line) + this._end_heading_fourth_level_tag; break;
		}
		
		return (this.close_paragraph(this._is_paragraph) + line + "\n");
	}
	
	// List tags

	convert_line_list_start() {

		++this._is_unordered_list;
		return this.close_paragraph(this._is_paragraph) + this._start_list_tag + "\n";
		
	}

	convert_line_list_item(li) {

		this._line = this._line.erase(li, 2);
		this._line = this._line.insert(li, this.close_paragraph(this._is_paragraph) + this._list_item_tag);
		
	}

	convert_line_list_end() {

		--this._is_unordered_list;
		if(this._is_unordered_list)
			return this.close_paragraph(this._is_paragraph) + this._end_list_tag + "\n";
		else
			return this.close_paragraph(this._is_paragraph) + this._end_list_tag + "\n";
		
	}
	
	/*
	 * 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);

			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._middle_container_tag);
				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);
					this._line = this._line.insert(end_tag, this._end_container_tag);
				} 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.close_paragraph(this._is_paragraph) + this._start_table_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;
			line = line.substr(pipe, line.size() - 1);
			pipe = line.find("|");
			if(this.found(pipe)) {
				let size = line.size() - 1;
				if(line[size] == '|') {
					while(this.found(pipe) && line[size] == '|') {
						return_text += this._start_table_data_tag + this.strip_escaping(line.substr(0, pipe)) + this._end_table_data_tag;
						++pipe;
						line = line.substr(pipe, size);
						pipe = line.find("|");
						size = line.size() - 1;
					}
					return return_text + this._end_table_row_tag;
				} 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;
	}
	/*
	 * Check line ending and convert depending ending whitespace
	 *
	 */
	convert_line_ending(line) {
		line = this.strip_escaping(line);
		if(line.size() > 1) {
			if(line[line.size() - 1] == ' ' && (this._has_image || this._has_block)) {
				return line.substring(0, line.size() - 1)  + "\n";
			} else if(line[line.size() - 1] == ' '){

				return line  + "\n";
			} else if(!this._is_converting_table && !this._has_block && !this._is_unordered_list) {
			
				return line;
			
			} else {
				
				return line;
			}
		} else 
			return line + "\n";
		
	}
	
	/*
	 * Control tags:
	 * <!, <>, <+. <
	 */
	convert_line_control_tags(line) {
		if(line[1] != '!') {
			if(line[1] == '>') {
				line = line.erase(0,2);
				return "<div class=\"embed\">" + line + "</div>" + "\n";
			} else if(line[1] == '+') {
				line = line.erase(0,2);
				return "<pre>" + line + "</pre>" + "\n";

			} else {
				line = line.erase(0,1);
				if(line.slice(-1) == "\n")
					return line + "\n";
				else
					return "<code>" + line + "</code>";
			}
		} else
			return "";
		
	}
	
	/*
	 * If there's an open paragraph, close it
	 *
	 */
	close_paragraph() {
		let p = "";
		if(this._is_paragraph) {
			p = this._end_paragraph_tag + "\n";
			this._is_paragraph = false;
		}
		return p;
	}

}
