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

el_val_t strip_query(el_val_t path);
el_val_t root_dir(void);
el_val_t parse_port(void);
el_val_t content_type_for(el_val_t path);
el_val_t route_health(void);
el_val_t route_founding_count(void);
el_val_t route_index(void);
el_val_t route_static(el_val_t path);
el_val_t route_brand(el_val_t path);
el_val_t err_404(el_val_t path);
el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body);

el_val_t strip_query(el_val_t path) {
  el_val_t q = str_index_of(path, EL_STR("?"));
  if (q < 0) {
    return path;
  }
  return str_slice(path, 0, q);
  return 0;
}

el_val_t root_dir(void) {
  el_val_t r = env(EL_STR("LANDING_ROOT"));
  if (str_eq(r, EL_STR(""))) {
    r = EL_STR("./src");
  }
  return r;
  return 0;
}

el_val_t parse_port(void) {
  el_val_t p = env(EL_STR("PORT"));
  if (str_eq(p, EL_STR(""))) {
    p = EL_STR("8080");
  }
  return str_to_int(p);
  return 0;
}

el_val_t content_type_for(el_val_t path) {
  if (str_ends_with(path, EL_STR(".html"))) {
    return EL_STR("text/html; charset=utf-8");
  }
  if (str_ends_with(path, EL_STR(".css"))) {
    return EL_STR("text/css; charset=utf-8");
  }
  if (str_ends_with(path, EL_STR(".js"))) {
    return EL_STR("application/javascript; charset=utf-8");
  }
  if (str_ends_with(path, EL_STR(".json"))) {
    return EL_STR("application/json; charset=utf-8");
  }
  if (str_ends_with(path, EL_STR(".png"))) {
    return EL_STR("image/png");
  }
  if (str_ends_with(path, EL_STR(".jpg"))) {
    return EL_STR("image/jpeg");
  }
  if (str_ends_with(path, EL_STR(".jpeg"))) {
    return EL_STR("image/jpeg");
  }
  if (str_ends_with(path, EL_STR(".svg"))) {
    return EL_STR("image/svg+xml");
  }
  if (str_ends_with(path, EL_STR(".ico"))) {
    return EL_STR("image/x-icon");
  }
  if (str_ends_with(path, EL_STR(".webp"))) {
    return EL_STR("image/webp");
  }
  if (str_ends_with(path, EL_STR(".woff2"))) {
    return EL_STR("font/woff2");
  }
  if (str_ends_with(path, EL_STR(".woff"))) {
    return EL_STR("font/woff");
  }
  return EL_STR("application/octet-stream");
  return 0;
}

el_val_t route_health(void) {
  return EL_STR("{\"status\":\"ok\",\"engine\":\"el-landing\"}");
  return 0;
}

el_val_t route_founding_count(void) {
  el_val_t sold = 47;
  el_val_t total = 1000;
  el_val_t remaining = (total - sold);
  return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"sold\":"), int_to_str(sold)), EL_STR(",\"total\":")), int_to_str(total)), EL_STR(",\"remaining\":")), int_to_str(remaining)), EL_STR("}"));
  return 0;
}

el_val_t route_index(void) {
  return fs_read(el_str_concat(root_dir(), EL_STR("/index.html")));
  return 0;
}

el_val_t route_static(el_val_t path) {
  return fs_read(el_str_concat(root_dir(), path));
  return 0;
}

el_val_t route_brand(el_val_t path) {
  el_val_t after = str_slice(path, 6, str_len(path));
  return fs_read(el_str_concat(el_str_concat(root_dir(), EL_STR("/assets/brand")), after));
  return 0;
}

el_val_t err_404(el_val_t path) {
  return el_str_concat(el_str_concat(EL_STR("{\"error\":\"not found\",\"path\":\""), path), EL_STR("\"}"));
  return 0;
}

el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) {
  el_val_t clean = strip_query(path);
  if (!str_eq(method, EL_STR("GET"))) {
    return EL_STR("{\"error\":\"method not allowed\"}");
  }
  if (str_eq(clean, EL_STR("/"))) {
    return route_index();
  }
  if (str_eq(clean, EL_STR("/health"))) {
    return route_health();
  }
  if (str_eq(clean, EL_STR("/api/founding-count"))) {
    return route_founding_count();
  }
  if (str_starts_with(clean, EL_STR("/assets/"))) {
    return route_static(clean);
  }
  if (str_starts_with(clean, EL_STR("/brand/"))) {
    return route_brand(clean);
  }
  return err_404(clean);
  return 0;
}

int main(int argc, char** argv) {
  el_runtime_init_args(argc, argv);
  el_val_t port = parse_port();
  println(el_str_concat(EL_STR("[landing] root="), root_dir()));
  println(el_str_concat(EL_STR("[landing] listening on "), int_to_str(port)));
  http_set_handler(EL_STR("handle_request"));
  http_serve(port, EL_STR("handle_request"));
  return 0;
}

