<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="author" content="@ajotanc" />

    <title>Pixel Magic Tool (Inline) - @ajotanc</title>

    <link
      rel="shortcut icon"
      href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAK9JREFUeNqUUssNwyAMJZWVUw4dhRHakZA6RqWMFEbwKDnk1FNBekEWxOBYQggL/D68yXXq+M7PtHkcefn89vrOw/UrP96w/NUFGiDLRz71GyY0QJa1Yn+nFa0ShqUNYCAF0QvoceOB4naEZif6UTNRapYaTyauRi4DEspr4Hbs5YKsbmtMyeJ0LxeESV4gB+hlSy4oO2txWysyus0a0+lO6vBjxcTMlG4mt2H6F2AAhU5NWu4dorQAAAAASUVORK5CYII=
    " />

    <style>
      body {
        display: flex;
        min-height: 100vh;
        margin: 0;
        font-size: 14px;
        font-family: monospace !important;
      }

      #code {
        width: calc(100% - 40px);
        height: 100%;
        padding: 20px;
        margin: 0;
        white-space: pre-wrap;
        word-wrap: break-word;
      }

      #toast-container {
        position: fixed;
        bottom: 20px;
        right: 20px;
        z-index: 9999;
      }

      .toast {
        display: flex;
        align-items: center;
        width: max-content;
        padding: 6px 12px;
        margin: 10px 0 0;
        border-radius: 8px;
        color: #fff;
        font-size: 12px;
        transform: translateY(30px);
        opacity: 0;
        visibility: hidden;
      }

      .toast .toast-body {
        padding: 8px 0;
        color: #fdfdfd;
      }

      .toast.success {
        background-color: #8ac926;
      }

      .toast.error {
        background-color: #ff595e;
      }

      .toast.warning {
        background-color: #f48c06;
      }

      .toast-progress {
        position: absolute;
        left: 4px;
        bottom: 4px;
        width: calc(100% - 8px);
        height: 3px;
        transform: scaleX(0);
        transform-origin: left;
        border-radius: inherit;
      }

      .toast.success .toast-progress {
        background: linear-gradient(to right, #8ac926, #548c2f);
      }

      .toast.error .toast-progress {
        background: linear-gradient(to right, #ff595e, #c9262b);
      }

      .toast.warning .toast-progress {
        background: linear-gradient(to right, #f48c06, #e85d04);
      }

      @keyframes progress {
        to {
          transform: scaleX(1);
        }
      }

      @keyframes fadeIn {
        5% {
          opacity: 1;
          visibility: visible;
          transform: translateY(0);
        }

        95% {
          opacity: 1;
          transform: translateY(0);
        }
      }
    </style>
  </head>
  <body>
    <pre id="code"></pre>
    <div id="toast-container"></div>
  </body>
  <script>
    const protocol =
      window.location.protocol === "file:" ? "http:" : window.location.protocol;
    const query = window.location.search;
    const params = new URLSearchParams(query);

    const hostname = params.get("hostname")
      ? params.get("hostname")
      : params.get("hn")
      ? params.get("hn")
      : "0.0.0.0";

    async function execute() {
      const image = params.get("image");

      if (!image) {
        toast("Image parameter is required!", "error");
        return;
      }

      if (!hostname) {
        toast("Hostname parameter is required!", "error");
        return;
      }

      const path = image.match(/^https?:\/\//)
        ? image
        : `${protocol}//${hostname}/${image}`;

      const response = await fetch(path);
      const blob = await response.blob();

      const body = new FormData();

      const file = new File([blob], "image", { type: blob.type });
      body.append("image", file);

      await convertImage(body, query);
    }

    async function convertImage(body, query) {
      const mode = params.get("mode") ? params.get("mode") : "production";
      const filename = params.get("image").replace(/\.[^.]+$/, "");

      const output = params.get("output")
        ? params.get("output")
        : params.get("o")
        ? params.get("o")
        : "json";

      const file =
        params.get("file") && params.get("file") === "true" ? true : false;

      const simulate =
        params.get("simulate") && params.get("simulate") === "true"
          ? true
          : false;

      const url =
        mode === "dev"
          ? `http://localhost:3333/api/wled/image${query}`
          : `https://pixelmagictool.vercel.app/api/wled/image${query}`;

      try {
        const response = await fetch(url, {
          method: "POST",
          body: body,
        });

        const data = await response.text();

        if (!response.ok) {
          const { issues } = JSON.parse(data);

          Object.entries(issues).forEach((issue) => {
            const [error, message] = issue;

            if (error !== "_errors") {
              toast(`Error: [${error}] ${message["_errors"]}`, "error");
            }
          });

          return;
        }

        if (file) {
          downloadFile(data, filename, output);
        }

        if (simulate && output === "json") {
          await requestSimulate(data);
        }

        const code = document.getElementById("code");
        code.textContent = data;
      } catch (error) {
        toast(error, "error");
      }
    }

    async function requestSimulate(body) {
      const url = `${protocol}//${hostname}/json/state`;

      try {
        const response = await fetch(url, {
          method: "POST",
          body,
        });

        const { ok, status, statusText } = response;

        if (!ok) {
          toast(`Error: [${status}] ${statusText}`, "error");
          return;
        }

        const { success } = await response.json();

        if (success) {
          toast("Preset sent successfully!");
        }
      } catch (error) {
        toast(error, "error");
      }
    }

    function downloadFile(text, filename, output) {
      let mimeType;
      let fileExtension;
      let response;

      switch (output) {
        case "json":
          mimeType = "application/json";
          fileExtension = "json";
          break;
        case "ha":
          mimeType = "application/x-yaml";
          fileExtension = "yaml";
          break;
        case "curl":
          mimeType = "text/plain";
          fileExtension = "txt";
          break;
      }

      const blob = new Blob([text], { type: mimeType });
      const url = URL.createObjectURL(blob);

      const anchorElement = document.createElement("a");
      anchorElement.href = url;
      anchorElement.download = `${filename}.${fileExtension}`;

      anchorElement.click();

      URL.revokeObjectURL(url);
    }

    function toast(message, type = "success", duration = 2000) {
      const toast = document.createElement("div");
      const wait = 100;

      toast.style.animation = "fadeIn";
      toast.style.animationDuration = `${duration + wait}ms`;
      toast.style.animationTimingFunction = "linear";

      toast.classList.add("toast", type);

      const body = document.createElement("span");
      body.classList.add("toast-body");

      body.textContent = message;

      toast.appendChild(body);

      const progress = document.createElement("div");
      progress.classList.add("toast-progress");

      progress.style.animation = "progress";
      progress.style.animationDuration = `${duration + wait}ms`;
      progress.style.animationDelay = "0s";

      toast.appendChild(progress);

      document.getElementById("toast-container").appendChild(toast);

      setTimeout(() => {
        toast.style.opacity = 0;
        setTimeout(() => {
          toast.remove();
        }, wait);
      }, duration);
    }

    (async () => {
      await execute();
    })();
    // window.addEventListener("load", async () => {
    //   await execute();
    // });
  </script>
</html>