import { useState } from "react";
import styles from "../styles/Builder.module.css";

interface IMap {
  [key: string]: boolean;
}

const pluginList = ["Sort", "Filter", "Comment", "Alternating Colors"];

// TODO 选项匹配插件名称
// TODO 代码包含一个完整的运行案例，直接运行，或者npm i 后运行，README.md引导
// TODO 下载代码压缩文件
// TODO 下载完成之后，服务器新复制的项目清除掉
// TODO 测试并发能力

function Builder() {
  const pluginMap: IMap = {};

  const [msgList, setMsgList] = useState<string[]>([]);
  const [progressValue, setProgressValue] = useState<number>(0);
  const [buildId, setBuildId] = useState<string>("");

  //   const
  const check = (e: React.ChangeEvent<HTMLInputElement>) => {
    pluginMap[e.target.value] = e.target.checked;
  };
  const build = () => {
    const buildList = [];
    for (const plugin in pluginMap) {
      if (pluginMap[plugin] === true) {
        buildList.push(plugin);
      }
    }
    postData("/api/build", { buildList }).then((data) => {
      setBuildId(data.buildId);
      startBuild(data.buildId);
    });
  };

  const download = () => {

    fetch("/api/download?buildId=" + buildId, {
      method: "GET", // *GET, POST, PUT, DELETE, etc.
      mode: "cors", // no-cors, *cors, same-origin
      cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
      credentials: "same-origin", // include, *same-origin, omit
      headers: {
        "Content-Type": "application/octet-stream",
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: "follow", // manual, *follow, error
      referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
    }).then ((res) => res.blob()).then((blob)=>{
      downloadFile(blob,'luckysheet-custom-build.zip')
    })

  };

  /**
   * reference: https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
   * @param url
   * @param data
   * @returns
   */
  async function postData(url = "", data = {}) {
    // Default options are marked with *
    const response = await fetch(url, {
      method: "POST", // *GET, POST, PUT, DELETE, etc.
      mode: "cors", // no-cors, *cors, same-origin
      cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
      credentials: "same-origin", // include, *same-origin, omit
      headers: {
        "Content-Type": "application/json",
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: "follow", // manual, *follow, error
      referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
      body: JSON.stringify(data), // body data type must match "Content-Type" header
    });
    return response.json(); // parses JSON response into native JavaScript objects
  }

  async function getFile(url = "") {
    // Default options are marked with *
    const response = await fetch(url, {
      method: "GET", // *GET, POST, PUT, DELETE, etc.
      mode: "cors", // no-cors, *cors, same-origin
      cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
      credentials: "same-origin", // include, *same-origin, omit
      headers: {
        "Content-Type": "application/octet-stream",
        // 'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: "follow", // manual, *follow, error
      referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
    });
    return response; // parses JSON response into native JavaScript objects
  }

  function startBuild(buildId: string) {
    // when "Start" button pressed
    if (!window.EventSource) {
      // IE or an old browser
      alert("The browser doesn't support EventSource.");
      return;
    }

    const eventSource = new EventSource("/api/progress?buildId=" + buildId);

    let retryCount = 0;
    eventSource.onopen = function (e) {
      console.log("Event: open");
    };

    eventSource.onerror = function (this: EventSource) {
      console.log(`Event: readyState=${this.readyState})`);
      if (this.readyState == EventSource.CLOSED) {
        console.log("Event: Connection was closed.");
      } else if (this.readyState == EventSource.CONNECTING) {
        eventSource.close();
        console.log("Event: Connection was closed.");
        // if (++retryCount === 5) {
        //   eventSource.close();
        // }
      } else {
        console.log("Event: Error has occured.");
      }
    };

    eventSource.addEventListener("progress", function (e) {
      const dataList = e.data.split("-");
      const msg = dataList[0];
      const progress = dataList[1];

      setMsgList((msgList) => [...msgList, msg]);
      setProgressValue(progress * 100);

      if (msg === "Success" || msg === "Fail") {
        eventSource.close();
      }
    });
  }

   /**
 * 下载文件
 * @param content 文件流
 * @param fileName 文件名称
 */
function downloadFile(blob: any, fileName: string)  {
      // const blob = new Blob([content], {
      //   type: 'application/octet-stream'
      // });
      const a = document.createElement("a");
      const url = window.URL.createObjectURL(blob);
      a.href = url;
      a.download = fileName;

      document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
      a.click();
      window.URL.revokeObjectURL(url);
      a.remove();  //afterwards we remove the element again   
    }
  
  return (
    <div className={styles.container}>
      <h2>Luckysheet Custom Builder</h2>
      <div className="container">
        <h3>Choose plugins</h3>
        <div>
          {pluginList.map((plugin) => {
            return (
              <p key={plugin}>
                <input
                  type="checkbox"
                  id={plugin}
                  value={plugin}
                  onChange={check}
                ></input>
                <label htmlFor={plugin}>{plugin}</label>
              </p>
            );
          })}
        </div>

        <div className={styles.operate}>
          <button onClick={build}>build</button>
        </div>

        <div>
          {progressValue === 0 ? (
            ""
          ) : (
            <div>
              <progress
                id="progress-bar"
                max="100"
                value={progressValue}
              ></progress>
              <span>{progressValue}%</span>
            </div>
          )}

          <div>
            <h3>Build Log</h3>
            <ul>
              {msgList.map((msg, i) => (
                <li key={i}>{msg}</li>
              ))}
            </ul>
          </div>

          <div>
            {/* <button onClick={download}>download</button> */}
            {progressValue === 100 ? (
              <button onClick={download}>download</button>
            ) : (
              ""
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

export default Builder;
