#include <stdint.h>
#include <stdlib.h>
#include "el_runtime.h"

el_val_t el_escape(el_val_t s);
el_val_t el_text(el_val_t s);
el_val_t el_attr(el_val_t name, el_val_t value);
el_val_t el_div(el_val_t attrs, el_val_t children);
el_val_t el_section(el_val_t attrs, el_val_t children);
el_val_t el_article(el_val_t attrs, el_val_t children);
el_val_t el_header(el_val_t attrs, el_val_t children);
el_val_t el_footer(el_val_t attrs, el_val_t children);
el_val_t el_main(el_val_t attrs, el_val_t children);
el_val_t el_nav(el_val_t attrs, el_val_t children);
el_val_t el_aside(el_val_t attrs, el_val_t children);
el_val_t el_ul(el_val_t attrs, el_val_t children);
el_val_t el_ol(el_val_t attrs, el_val_t children);
el_val_t el_li(el_val_t attrs, el_val_t children);
el_val_t el_p(el_val_t attrs, el_val_t children);
el_val_t el_span(el_val_t attrs, el_val_t children);
el_val_t el_form(el_val_t attrs, el_val_t children);
el_val_t el_h1(el_val_t attrs, el_val_t text);
el_val_t el_h2(el_val_t attrs, el_val_t text);
el_val_t el_h3(el_val_t attrs, el_val_t text);
el_val_t el_h4(el_val_t attrs, el_val_t text);
el_val_t el_button(el_val_t attrs, el_val_t label);
el_val_t el_a(el_val_t href, el_val_t attrs, el_val_t children);
el_val_t el_input(el_val_t type_attr, el_val_t attrs);
el_val_t el_textarea(el_val_t attrs, el_val_t value);
el_val_t el_label(el_val_t for_id, el_val_t attrs, el_val_t children);
el_val_t el_img(el_val_t src, el_val_t alt, el_val_t attrs);
el_val_t el_video(el_val_t attrs, el_val_t children);
el_val_t el_strong(el_val_t children);
el_val_t el_em(el_val_t children);
el_val_t el_code(el_val_t children);
el_val_t el_pre(el_val_t attrs, el_val_t children);
el_val_t el_hr(void);
el_val_t el_br(void);
el_val_t el_html_doc(el_val_t lang, el_val_t head_html, el_val_t body_html);
el_val_t el_meta(el_val_t name, el_val_t content);
el_val_t el_meta_charset(el_val_t charset);
el_val_t el_link_stylesheet(el_val_t href);
el_val_t el_script_src(el_val_t src, el_val_t defer_load);
el_val_t el_script_inline(el_val_t js);
el_val_t el_title(el_val_t text);


el_val_t el_escape(el_val_t s) {
  s = str_replace(s, EL_STR("&"), EL_STR("&amp;"));
  s = str_replace(s, EL_STR("<"), EL_STR("&lt;"));
  s = str_replace(s, EL_STR(">"), EL_STR("&gt;"));
  s = str_replace(s, EL_STR("\""), EL_STR("&quot;"));
  return str_replace(s, EL_STR("'"), EL_STR("&#39;"));
  return 0;
}

el_val_t el_text(el_val_t s) {
  return el_escape(s);
  return 0;
}

el_val_t el_attr(el_val_t name, el_val_t value) {
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR(" "), name), EL_STR("=\"")), el_escape(value)), EL_STR("\""));
  return 0;
}

el_val_t el_div(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<div>"), children), EL_STR("</div>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<div "), attrs), EL_STR(">")), children), EL_STR("</div>"));
  return 0;
}

el_val_t el_section(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<section>"), children), EL_STR("</section>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<section "), attrs), EL_STR(">")), children), EL_STR("</section>"));
  return 0;
}

el_val_t el_article(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<article>"), children), EL_STR("</article>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<article "), attrs), EL_STR(">")), children), EL_STR("</article>"));
  return 0;
}

el_val_t el_header(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<header>"), children), EL_STR("</header>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<header "), attrs), EL_STR(">")), children), EL_STR("</header>"));
  return 0;
}

el_val_t el_footer(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<footer>"), children), EL_STR("</footer>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<footer "), attrs), EL_STR(">")), children), EL_STR("</footer>"));
  return 0;
}

el_val_t el_main(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<main>"), children), EL_STR("</main>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<main "), attrs), EL_STR(">")), children), EL_STR("</main>"));
  return 0;
}

el_val_t el_nav(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<nav>"), children), EL_STR("</nav>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<nav "), attrs), EL_STR(">")), children), EL_STR("</nav>"));
  return 0;
}

el_val_t el_aside(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<aside>"), children), EL_STR("</aside>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<aside "), attrs), EL_STR(">")), children), EL_STR("</aside>"));
  return 0;
}

el_val_t el_ul(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<ul>"), children), EL_STR("</ul>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<ul "), attrs), EL_STR(">")), children), EL_STR("</ul>"));
  return 0;
}

el_val_t el_ol(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<ol>"), children), EL_STR("</ol>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<ol "), attrs), EL_STR(">")), children), EL_STR("</ol>"));
  return 0;
}

el_val_t el_li(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<li>"), children), EL_STR("</li>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<li "), attrs), EL_STR(">")), children), EL_STR("</li>"));
  return 0;
}

el_val_t el_p(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<p>"), children), EL_STR("</p>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<p "), attrs), EL_STR(">")), children), EL_STR("</p>"));
  return 0;
}

el_val_t el_span(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<span>"), children), EL_STR("</span>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<span "), attrs), EL_STR(">")), children), EL_STR("</span>"));
  return 0;
}

el_val_t el_form(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<form>"), children), EL_STR("</form>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<form "), attrs), EL_STR(">")), children), EL_STR("</form>"));
  return 0;
}

el_val_t el_h1(el_val_t attrs, el_val_t text) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<h1>"), el_escape(text)), EL_STR("</h1>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<h1 "), attrs), EL_STR(">")), el_escape(text)), EL_STR("</h1>"));
  return 0;
}

el_val_t el_h2(el_val_t attrs, el_val_t text) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<h2>"), el_escape(text)), EL_STR("</h2>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<h2 "), attrs), EL_STR(">")), el_escape(text)), EL_STR("</h2>"));
  return 0;
}

el_val_t el_h3(el_val_t attrs, el_val_t text) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<h3>"), el_escape(text)), EL_STR("</h3>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<h3 "), attrs), EL_STR(">")), el_escape(text)), EL_STR("</h3>"));
  return 0;
}

el_val_t el_h4(el_val_t attrs, el_val_t text) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<h4>"), el_escape(text)), EL_STR("</h4>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<h4 "), attrs), EL_STR(">")), el_escape(text)), EL_STR("</h4>"));
  return 0;
}

el_val_t el_button(el_val_t attrs, el_val_t label) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<button type=\"button\">"), el_escape(label)), EL_STR("</button>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<button type=\"button\" "), attrs), EL_STR(">")), el_escape(label)), EL_STR("</button>"));
  return 0;
}

el_val_t el_a(el_val_t href, el_val_t attrs, el_val_t children) {
  el_val_t h = el_str_concat(el_str_concat(EL_STR("href=\""), el_escape(href)), EL_STR("\""));
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<a "), h), EL_STR(">")), children), EL_STR("</a>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<a "), h), EL_STR(" ")), attrs), EL_STR(">")), children), EL_STR("</a>"));
  return 0;
}

el_val_t el_input(el_val_t type_attr, el_val_t attrs) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<input type=\""), type_attr), EL_STR("\" />"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<input type=\""), type_attr), EL_STR("\" ")), attrs), EL_STR(" />"));
  return 0;
}

el_val_t el_textarea(el_val_t attrs, el_val_t value) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<textarea>"), el_escape(value)), EL_STR("</textarea>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<textarea "), attrs), EL_STR(">")), el_escape(value)), EL_STR("</textarea>"));
  return 0;
}

el_val_t el_label(el_val_t for_id, el_val_t attrs, el_val_t children) {
  el_val_t f = el_str_concat(el_str_concat(EL_STR("for=\""), el_escape(for_id)), EL_STR("\""));
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<label "), f), EL_STR(">")), children), EL_STR("</label>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<label "), f), EL_STR(" ")), attrs), EL_STR(">")), children), EL_STR("</label>"));
  return 0;
}

el_val_t el_img(el_val_t src, el_val_t alt, el_val_t attrs) {
  el_val_t base = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("src=\""), el_escape(src)), EL_STR("\" alt=\"")), el_escape(alt)), EL_STR("\""));
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<img "), base), EL_STR(" />"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<img "), base), EL_STR(" ")), attrs), EL_STR(" />"));
  return 0;
}

el_val_t el_video(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<video>"), children), EL_STR("</video>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<video "), attrs), EL_STR(">")), children), EL_STR("</video>"));
  return 0;
}

el_val_t el_strong(el_val_t children) {
  return el_str_concat(el_str_concat(EL_STR("<strong>"), children), EL_STR("</strong>"));
  return 0;
}

el_val_t el_em(el_val_t children) {
  return el_str_concat(el_str_concat(EL_STR("<em>"), children), EL_STR("</em>"));
  return 0;
}

el_val_t el_code(el_val_t children) {
  return el_str_concat(el_str_concat(EL_STR("<code>"), children), EL_STR("</code>"));
  return 0;
}

el_val_t el_pre(el_val_t attrs, el_val_t children) {
  if (str_eq(attrs, EL_STR(""))) {
    return el_str_concat(el_str_concat(EL_STR("<pre>"), children), EL_STR("</pre>"));
  }
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<pre "), attrs), EL_STR(">")), children), EL_STR("</pre>"));
  return 0;
}

el_val_t el_hr(void) {
  return EL_STR("<hr />");
  return 0;
}

el_val_t el_br(void) {
  return EL_STR("<br />");
  return 0;
}

el_val_t el_html_doc(el_val_t lang, el_val_t head_html, el_val_t body_html) {
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<!doctype html><html lang=\""), el_escape(lang)), EL_STR("\"><head>")), head_html), EL_STR("</head><body>")), body_html), EL_STR("</body></html>"));
  return 0;
}

el_val_t el_meta(el_val_t name, el_val_t content) {
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("<meta name=\""), el_escape(name)), EL_STR("\" content=\"")), el_escape(content)), EL_STR("\" />"));
  return 0;
}

el_val_t el_meta_charset(el_val_t charset) {
  return el_str_concat(el_str_concat(EL_STR("<meta charset=\""), el_escape(charset)), EL_STR("\" />"));
  return 0;
}

el_val_t el_link_stylesheet(el_val_t href) {
  return el_str_concat(el_str_concat(EL_STR("<link rel=\"stylesheet\" href=\""), el_escape(href)), EL_STR("\" />"));
  return 0;
}

el_val_t el_script_src(el_val_t src, el_val_t defer_load) {
  if (defer_load) {
    return el_str_concat(el_str_concat(EL_STR("<script src=\""), el_escape(src)), EL_STR("\" defer></script>"));
  }
  return el_str_concat(el_str_concat(EL_STR("<script src=\""), el_escape(src)), EL_STR("\"></script>"));
  return 0;
}

el_val_t el_script_inline(el_val_t js) {
  return el_str_concat(el_str_concat(EL_STR("<script>"), js), EL_STR("</script>"));
  return 0;
}

el_val_t el_title(el_val_t text) {
  return el_str_concat(el_str_concat(EL_STR("<title>"), el_escape(text)), EL_STR("</title>"));
  return 0;
}


