// import item from "@/pages/website/routes/list/item";
import ListModule from "..";
import { ShowItem } from "../state";
type ColDataType = {
  offset: number;
  items: any[];
  halfOffset: number;
  dragging: boolean;
  speed: number;
};

export default (listModule: ListModule) => {
  const cols: ColDataType[] = []; //{offset, items:[], halfOffset: 0, dragging: false}
  const totalRow = listModule.state.totalRow || 8;
  let CanvasWidth = 0;
  let CanvasHeight = 0;
  let textH = 0;
  let paddingOffset = 0;
  let totalSizeCount = 0; //每行或每列的数量
  let itemOffset = 0;

  let ctx: CanvasRenderingContext2D;
  let scale = 1;

  return {
    async initListCanvasDatas(wWidth: number, wHeight: number) {
      const scrollType = listModule.state.scrollType;
      const items = await listModule.actions.loadData(wWidth, wHeight);
      scale = Math.max(devicePixelRatio, 2);

      // textH = 24 * scale;
      CanvasWidth = wWidth * scale;
      CanvasHeight = wHeight * scale;
      paddingOffset = 12 * scale;
      totalSizeCount = Math.ceil(items.length / totalRow) * 2;

      if (scrollType == "vertical") {
        listModule.actions.initVerticalList(items);
      }
      if (scrollType == "horizontal") {
        listModule.actions.initHorizontalList(items);
      }
    },
    initVerticalList(items) {
      itemOffset = (CanvasWidth - paddingOffset * (totalRow + 1)) / totalRow;
      for (let i = 0; i < totalRow; i++) {
        let off = i * totalSizeCount;
        let arr: ShowItem[] = [];
        for (let k = 0; k < totalSizeCount; k++) {
          arr.push(items[(off + k) % items.length]);
        }
        listModule.actions.shuffleSelf(arr, totalSizeCount);
        //计算总高度
        let halfOffset = 0;
        arr.forEach((item) => {
          let h = ((item.h * 1.0) / item.w) * itemOffset;
          item.offsetY = h + textH + paddingOffset; //y step;
          halfOffset += item.offsetY;
        });

        const colData = {
          items: [...arr, ...arr],
          offset: 0,
          halfOffset: halfOffset,
          dragging: false,
          speed: i % 2 == 0 ? 1 : 2,
        };
        cols.push(colData);
      }
    },
    initHorizontalList(items) {
      itemOffset = (CanvasHeight - paddingOffset * (totalRow + 1)) / totalRow;
      for (let i = 0; i < totalRow; i++) {
        let off = i * totalSizeCount;
        let arr: ShowItem[] = [];
        for (let k = 0; k < totalSizeCount; k++) {
          arr.push(items[(off + k) % items.length]);
        }
        listModule.actions.shuffleSelf(arr, totalSizeCount);

        //计算总高度
        let halfOffset = 0;
        arr.forEach((item) => {
          let w = ((item.w * 1.0) / item.h) * itemOffset;
          item.offsetX = w + textH + paddingOffset; //y step;
          halfOffset += item.offsetX;
        });

        const colData = {
          items: [...arr, ...arr],
          offset: 0,
          halfOffset: halfOffset,
          dragging: false,
          speed: i % 2 == 0 ? 1 : 2,
        };
        cols.push(colData);
      }
    },

    startListRunning(canvas: HTMLCanvasElement) {
      listModule.actions.initDragEvents(canvas);
      canvas.width = CanvasWidth;
      canvas.height = CanvasHeight;
      ctx = canvas.getContext("2d");

      const cache = document.createElement("canvas");
      cache.width = CanvasWidth;
      cache.height = CanvasHeight;
      const cacheCtx = cache.getContext("2d");
      cacheCtx.font = "24px sans-serif";
      cacheCtx.fillStyle = "#FFFFFF";
      cacheCtx.textBaseline = "top";

      let loopId = 0;

      let n = cols.length;
      let i = 0;
      let lastTime = Date.now();
      let dtaTime = 0;
      function loop() {
        dtaTime = Date.now() - lastTime;
        lastTime = Date.now();
        n = cols.length;
        while (n--) {
          let item = cols[n];
          if (!item.dragging) {
            //没有拖拽进行累积
            item.offset = Math.floor(item.offset + item.speed);
          }
          //   console.log(item.offset);
          if (item.offset >= item.halfOffset) item.offset -= item.halfOffset;
          if (item.offset < 0) item.offset += item.halfOffset;
        }
        cacheCtx.clearRect(0, 0, CanvasWidth, CanvasHeight);
        n = cols.length;
        for (i = 0; i < n; i++) {
          listModule.actions.listDraw(cols[i], i, cacheCtx);
        }
        ctx.clearRect(0, 0, CanvasWidth, CanvasHeight);
        ctx.drawImage(cache, 0, 0);
        loopId = requestAnimationFrame(loop);
      }
      loop();
    },
    listDraw(col: ColDataType, row: number, ctx: any) {
      const scrollType = listModule.state.scrollType;
      let x = 0,
        y = 0,
        offseStep = itemOffset + paddingOffset;

      if (scrollType == "vertical") {
        x =
          row > 0 ? Math.floor(row * offseStep) + paddingOffset : paddingOffset;
        y = col.offset + CanvasHeight;
      }
      if (scrollType == "horizontal") {
        x = col.offset + CanvasWidth;
        y =
          row > 0 ? Math.floor(row * offseStep) + paddingOffset : paddingOffset;
      }

      const items = col.items;
      let total = items.length;

      for (let k = 0; k < total; k++) {
        //绘制
        let item = items[k];

        if (scrollType == "vertical") {
          y -= item.offsetY; //从下往上绘制
          if (y > CanvasHeight || y < -item.offsetY) continue; //超出部分，不进行绘制提交
          ctx.drawImage(
            item.img,
            0,
            0,
            item.w,
            item.h,
            Math.floor(x),
            Math.floor(y),
            Math.floor(itemOffset),
            Math.floor(item.offsetY - textH - paddingOffset)
          );
        }
        if (scrollType == "horizontal") {
          x -= item.offsetX;
          if (x > CanvasWidth || x < -item.offsetX) continue;
          ctx.drawImage(
            item.img,
            0,
            0,
            item.w,
            item.h,
            Math.floor(x),
            Math.floor(y),
            Math.floor(item.offsetX - textH - paddingOffset),
            Math.floor(itemOffset)
          );
        }

        // let text =
        //   item.name.length > 20
        //     ? item.name.substring(0, 19) + "..."
        //     : item.name;
        // ctx.fillText(text, x, Math.round(y + item.offsetY - textH * 1.2));
      }
    },

    endListRuning() {},

    initDragEvents(canvas: HTMLCanvasElement) {
      let down = false;
      let downIndex = -1;
      let downY = 0;
      let downX = 0;

      let initOffset = 0;
      let downTime = 0;
      let moving = false;
      let fingers = {};
      const scrollType = listModule.state.scrollType;

      function onMouseDown(e: MouseEvent) {
        let x = e.clientX * scale;
        let y = e.clientY * scale;
        downY = e.clientY * scale;
        downX = e.clientX * scale;
        down = true;
        downIndex =
          scrollType == "vertical"
            ? Math.floor(x / (itemOffset + paddingOffset))
            : Math.floor(y / (itemOffset + paddingOffset));

        cols[downIndex].dragging = true;
        initOffset = cols[downIndex].offset;
        downTime = Date.now();
      }

      function onMouseMove(e) {
        if (!down || downIndex < 0) return;
        moving = true;

        console.log("move");
        let dtaOffset = 0;
        if (scrollType == "vertical") {
          dtaOffset = e.clientY * scale - dtaOffset;
        }
        if (scrollType == "horizontal") {
          dtaOffset = e.clientX * scale - dtaOffset;
        }

        cols[downIndex].offset = initOffset + dtaOffset;
      }
      function onMouseUp(e) {
        console.log("up");
        down = false;
        if (downIndex >= 0) {
          cols[downIndex].dragging = false;
          let dtaTime = Date.now() - downTime;
          if (dtaTime < 200 && !moving) {
            const col = cols[downIndex];
            let offset = col.offset;
            if (offset >= col.halfOffset) offset -= col.halfOffset;
            if (offset < 0) offset += col.halfOffset;

            let n = col.items.length;
            let z =
              scrollType == "vertical"
                ? offset + CanvasHeight
                : offset + CanvasWidth;
            for (let k = 0; k < n; k++) {
              const item = col.items[k];
              if (scrollType == "vertical") {
                z -= item.offsetY;
                if (downY > z && downY < z + item.offsetY) {
                  console.log("click->", item.name);
                  listModule.actions.popDialog(e, item);
                  break;
                }
              }
              if (scrollType == "horizontal") {
                z -= item.offsetX;
                if (downX > z && downX < z + item.offsetX) {
                  console.log("click->", item.name);
                  listModule.actions.popDialog(e, item);
                  break;
                }
              }
            }
          }
        }
        downIndex = -1;
        moving = false;
      }
      function onTouchstart(e: TouchEvent) {
        let touches = e.touches;
        for (let i = 0; i < touches.length; i++) {
          let touch = touches[i];
          if (fingers[touch.identifier]) {
            continue;
          }
          let x = touch.clientX * scale;
          let y = touch.clientY * scale;
          let downIndex =
            scrollType == "vertical"
              ? Math.floor(x / (itemOffset + paddingOffset))
              : Math.floor(y / (itemOffset + paddingOffset));
          cols[downIndex].dragging = true;
          let offset = cols[downIndex].offset;
          fingers[touch.identifier] = {
            identifier: touch.identifier,
            downY: y,
            downX: x,
            downIndex: downIndex,
            offset: offset,
            downTime: Date.now(),
          };
        }
      }
      function onTouchMove(e: TouchEvent) {
        let touches = e.changedTouches;
        for (let i = 0; i < touches.length; i++) {
          let touch = touches[i];
          let finger = fingers[touch.identifier];
          if (!finger) {
            continue;
          }
          finger.moving = true;
          let dtaOffset = 0;
          if (scrollType == "vertical") {
            dtaOffset = touch.clientY * scale - finger.downY;
          }
          if (scrollType == "horizontal") {
            dtaOffset = touch.clientX * scale - finger.downY;
          }
          cols[finger.downIndex].offset = finger.offset + dtaOffset;
        }
      }

      function onTouchEnd(e: TouchEvent) {
        let touches = e.changedTouches;
        for (let i = 0; i < touches.length; i++) {
          let touch = touches[i];
          let finger = fingers[touch.identifier];

          if (!finger) {
            continue;
          }

          cols[finger.downIndex].dragging = false;
          let dtaTime = Date.now() - finger.downTime;
          if (dtaTime < 200 && !finger.moving) {
            const col = cols[finger.downIndex];
            let offset = col.offset;
            if (offset >= col.halfOffset) offset -= col.halfOffset;
            if (offset < 0) offset += col.halfOffset;
            let n = col.items.length;
            let z =
              scrollType == "vertical"
                ? offset + CanvasHeight
                : offset + CanvasWidth;
            for (let k = 0; k < n; k++) {
              const item = col.items[k];

              if (scrollType == "vertical") {
                z -= item.offsetY;
                if (finger.downY > z && finger.downY < z + item.offsetY) {
                  listModule.actions.popDialog(touch, item);
                  break;
                }
              }
              if (scrollType == "horizontal") {
                z -= item.offsetX;
                if (finger.downX > z && finger.downX < z + item.offsetX) {
                  listModule.actions.popDialog(touch, item);
                  break;
                }
              }
            }
          }
          delete fingers[touch.identifier];
        }
      }

      canvas.addEventListener("mousedown", onMouseDown, false);
      canvas.addEventListener("mousemove", onMouseMove, false);
      document.addEventListener("mouseup", onMouseUp, false);

      canvas.addEventListener("touchstart", onTouchstart, false);
      canvas.addEventListener("touchmove", onTouchMove, false);
      document.addEventListener("touchend", onTouchEnd, false);
    },
  };
};
