import { getLocal, changSaveLocal } from "@/util/localUtil";
import { reactive, watchEffect } from "vue";

// 发送手机验证码
export enum CountdownStuts {
  never,
  sendIng,
  effective,
}
export type CountdownStore = {
  status: CountdownStuts;
  miss: number;
  create: number;
};

export const countdownFactory = (miss: number = 60, key: string = "") => {
  const store: { [key in string]: CountdownStore } = reactive(
    getLocal("codeStore" + key, {})
  );
  console.log(store);
  changSaveLocal("codeStore" + key, () => store);

  const get = (key: string) => {
    if (!store[key]) {
      store[key] = {
        status: CountdownStuts.never,
        miss: 0,
        create: 0,
      };
    }
    return store[key];
  };
  const set = async (key: string, use: (key: string) => void) => {
    const storeItem = get(key);
    console.log(storeItem);
    if (storeItem.status !== CountdownStuts.never) {
      return;
    }
    try {
      storeItem.status = CountdownStuts.sendIng;
      await use(key);
      storeItem.status = CountdownStuts.effective;
      storeItem.miss = miss;
      storeItem.create = new Date().getTime();
    } catch (e) {
      console.error(e);
      storeItem.status = CountdownStuts.never;
    }
  };

  const setItemStore = (item: CountdownStore) => {
    if (item.status === CountdownStuts.effective) {
      const diffMis = (new Date().getTime() - item.create) / 1000;
      if (diffMis > miss) {
        item.status = CountdownStuts.never;
      } else {
        item.miss = Math.ceil(miss - diffMis);
      }
    } else {
      item.create = 0;
      item.miss = 0;
    }
  };

  watchEffect((onCleanup) => {
    const intervals: number[] = [];
    for (const key in store) {
      const item = get(key);
      setItemStore(item);
      if (item.status === CountdownStuts.effective) {
        intervals.push(
          setInterval(() => {
            setItemStore(item);
          }, 1000)
        );
      }
    }

    onCleanup(() => {
      intervals.forEach(clearInterval);
    });
  });

  return {
    get,
    set(key: string, send: (key: string) => void) {
      set(key, send || (() => null));
    },
  };
};
