"use strict";

/**
 * @name Loader
 *
 * @description
 * Implements actions with loading and rendering content
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
export default class loader {
	/**
	 * @name Type of the program
	 */
	static type = "module";

	/**
	 * @name Load
	 *
	 * @param {string} uri
	 * @param {string} body
	 *
	 * @return {Promise}
	 */
	static async load(uri = "/", body) {
		if (typeof uri === "string") {
			// Received and validated uri

			return await core
				.request(
					uri,
					body,
					"GET",
					{
						"Content-Type": "application/x-www-form-urlencoded",
						Accept: "application/json",
					},
					"json",
				)
				.then((json) => {
					if (json) {
						// Received a JSON-response

						if (
							json.errors !== null &&
							typeof json.errors === "object" &&
							json.errors.length > 0
						) {
							// Fail (received errors)

							// Exit (fail)
							reject(json);
						} else {
							// Success (not received errors)

							// Writing to the browser history
							history.pushState({}, json.title ?? uri, uri);

							/**
							 * The <title>
							 *
							 * The title of the page
							 */
							if (
								typeof json.title === "string" &&
								json.title.length > 0
							) {
								// Received text for the <title> of the page

								// Search for the <title> element (document.title)
								const title = document.getElementsByTagName("title")[0];

								if (title instanceof HTMLElement) {
									// Found the <title> element

									// Writing into the <title> element
									title.innerText = json.title;
								} else {
									// Not found the <title> element

									// Initialize the <title> element
									const title = document.createElement("title");

									// Inititalize the <head> element (document.head)
									const head = document.getElementsByTagName("head")[0];

									if (head instanceof HTMLElement) {
										// Found the <head> element

										// Writing the <title> element into the <head> element
										head.appendChild(title);
									}

									// Writing title into the <title> element
									title.innerText = json.title;
								}
							}

							/**
							 * The <header> element
							 */
							if (
								typeof json.header === "string" &&
								json.header.length > 0
							) {
								// Received and validated the header HTML-code

								if (core.header instanceof HTMLElement) {
									// Found the <header> element

									// Writing into the <header> element
									core.header.outerHTML = json.header;

									// Reinitializing the parameter with the <header> element
									core.header = document.getElementsByTagName("header")[0];
								} else {
									// Not found the <header> element

									// Initialize the <header> element
									core.header = document.createElement("header");

									// Inititalize the <body> element (document.body)
									const body = document.getElementsByTagName("body")[0];

									if (body instanceof HTMLElement) {
										// Found the <body> element

										if (core.main instanceof HTMLElement) {
											// Found the <main> element

											// Writing the <header> element before the <main> element
											body.insertBefore(core.header, core.main);
										} else if (core.footer instanceof HTMLElement) {
											// Fount the <footer> element

											// Writing the <header> element before the <footer> element
											body.insertBefore(core.header, core.footer);
										} else {
											// Not found the <main> element and the <footer> element

											// Search for the last <section> element inside the <body> element
											const section = document.body.querySelector(
												"body > section:last-of-type",
											);

											if (section instanceof HTMLElement) {
												// Found the last <section> element inside the <body> element

												// Writing the <header> element after the last <section> element inside the <body> element
												body.insertBefore(
													core.header,
													section.nextElementSibling,
												);
											} else {
												// Not found section elements <section> inside the <body> element

												// Writing the <header> element into the <body> element
												body.appendChild(core.header);
											}
										}

										// Writing into the <header> element
										core.header.outerHTML = json.header;

										// Reinitializing the parameter with the <header> element
										core.header = document.getElementsByTagName("header")[0];
									}
								}
							}

							/**
							 * The <main> element
							 *
							 * The main content of the page
							 */
							if (typeof json.main === "string" && json.main.length > 0) {
								// Received and validated the <main> HTML-code

								if (core.main instanceof HTMLElement) {
									// Found the <main> element

									// Writing into the <main> element
									core.main.outerHTML = json.main;

									// Reinitializing the parameter with the <main> element
									core.main = document.getElementsByTagName("main")[0];
								} else {
									// Not found the <main> element

									// Initialize the <main> element
									core.main = document.createElement("main");

									// Inititalize the <body> element (document.body)
									const body = document.getElementsByTagName("body")[0];

									if (body instanceof HTMLElement) {
										// Found the <body> element

										if (core.header instanceof HTMLElement) {
											// Found the <header> element

											// Writing the <main> element after the <header> element
											body.insertBefore(
												core.main,
												core.header.nextElementSibling,
											);
										} else if (core.footer instanceof HTMLElement) {
											// Fount the <footer> element

											// Writing the <main> element before the <footer> element
											body.insertBefore(core.main, core.footer);
										} else {
											// Not found the <header> element and the <footer> element

											// Search for the last <section> element inside the <body> element
											const section = document.body.querySelector(
												"body > section:last-of-type",
											);

											if (section instanceof HTMLElement) {
												// Found the last <section> element inside the <body> element

												// Writing the <main> element after the last <section> element inside the <body> element
												body.insertBefore(core.main, section.nextElementSibling);
											} else {
												// Not found section elements <section> inside the <body> element

												// Writing the <main> element into the <body> element
												body.appendChild(core.main);
											}
										}

										// Writing into the <main> element
										core.main.outerHTML = json.main;

										// Reinitializing the parameter with the <main> element
										core.main = document.getElementsByTagName("main")[0];
									}
								}
							}

							// Exit (success)
							return json;
						}
					}
				});
		}
	}
}

// Connecting to the core
if (!core.loader) core.loader = loader;
