import { TFunction } from "i18next";
import { runInAction } from "mobx";
import { sprintf } from "sprintf-js";
import { getMillis } from "taehui-ts/date";

import { Note } from "src/avatar/Avatar";
import { formatText, toDate } from "src/Utility";
import { wwwAXIOS } from "src/Www";
import {
  AvatarAPIWantAvatar,
  AvatarWwwLevelsAPI,
  GetAvatarAbilitiesAPI,
  GetAvatarAPI,
  GetAvatarFavoritesAPI,
  GetAvatarLastsAPI,
  GetAvatarWwwLevelsAPI,
} from "src/wwwAPI";

export default function setAvatarStore() {
  let lastMillisAvatar = getMillis();
  let lastMillisWwwLevels = getMillis();

  return {
    input: "",
    wantAvatars: [] as AvatarAPIWantAvatar[],
    avatarID: "",
    avatarName: "",
    avatarIntro: "",
    totalCount: "",
    totalLength: "",
    highestCount: "",
    date: "",
    avatarLevels: [] as number[],
    avatarAbility5K: 0,
    avatarAbility5KClass: 0,
    avatarAbility5KPlace: 0,
    avatarAbility5KCount: 0,
    avatarAbility7K: 0,
    avatarAbility7KClass: 0,
    avatarAbility7KPlace: 0,
    avatarAbility7KCount: 0,
    avatarAbility9K: 0,
    avatarAbility9KClass: 0,
    avatarAbility9KPlace: 0,
    avatarAbility9KCount: 0,
    favorites5K: [] as Note[],
    favorites7K: [] as Note[],
    favorites9K: [] as Note[],
    favorites10K: [] as Note[],
    favorites14K: [] as Note[],
    favorites24K: [] as Note[],
    favorites48K: [] as Note[],
    lasts5K: [] as Note[],
    lasts7K: [] as Note[],
    lasts9K: [] as Note[],
    lasts10K: [] as Note[],
    lasts14K: [] as Note[],
    lasts24K: [] as Note[],
    lasts48K: [] as Note[],
    abilities5K: [] as Note[],
    abilities7K: [] as Note[],
    abilities9K: [] as Note[],
    wwwLevels: [] as AvatarWwwLevelsAPI[],
    dateSet: [] as string[],
    dateValues: [] as number[],
    quitStatusValues: [] as number[],
    isFavorites5KLoading: false,
    isFavorites7KLoading: false,
    isFavorites9KLoading: false,
    isFavorites10KLoading: false,
    isFavorites14KLoading: false,
    isFavorites24KLoading: false,
    isFavorites48KLoading: false,
    isLasts5KLoading: false,
    isLasts7KLoading: false,
    isLasts9KLoading: false,
    isLasts10KLoading: false,
    isLasts14KLoading: false,
    isLasts24KLoading: false,
    isLasts48KLoading: false,
    isAbilities5KLoading: false,
    isAbilities7KLoading: false,
    isAbilities9KLoading: false,
    isWwwLevelLoading: false,
    favoritesTabPosition: 0,
    lastsTabPosition: 0,
    abilitiesTabPosition: 0,

    setFavoritesTabPosition(favoritesTabPosition: number) {
      this.favoritesTabPosition = favoritesTabPosition;
    },

    setLastsTabPosition(lastsTabPosition: number) {
      this.lastsTabPosition = lastsTabPosition;
    },

    setAbilitiesTabPosition(abilitiesTabPosition: number) {
      this.abilitiesTabPosition = abilitiesTabPosition;
    },

    get isLoading() {
      return (
        this.isFavorites5KLoading ||
        this.isFavorites7KLoading ||
        this.isFavorites9KLoading ||
        this.isFavorites10KLoading ||
        this.isFavorites14KLoading ||
        this.isFavorites24KLoading ||
        this.isFavorites48KLoading ||
        this.isLasts5KLoading ||
        this.isLasts7KLoading ||
        this.isLasts9KLoading ||
        this.isLasts10KLoading ||
        this.isLasts14KLoading ||
        this.isLasts24KLoading ||
        this.isLasts48KLoading ||
        this.isWwwLevelLoading
      );
    },

    setInput(input: string) {
      this.input = input;
    },

    async getAvatar(
      t: TFunction,
      { avatarID, avatarName }: { avatarID?: string; avatarName?: string },
    ) {
      this.wantAvatars = [];
      this.avatarID = "";
      if (avatarID || avatarName) {
        lastMillisAvatar = getMillis();
        const { status, data } = await wwwAXIOS.get<GetAvatarAPI>("/avatar", {
          params: { avatarID, avatarName },
        });
        if (getMillis() >= lastMillisAvatar) {
          switch (status) {
            case 200:
              if (Array.isArray(data)) {
                runInAction(() => {
                  this.wantAvatars = data;
                });
              } else {
                runInAction(() => {
                  this.avatarID = data.avatarID;
                  this.avatarName = data.avatarName;
                  this.avatarIntro = data.avatarIntro;
                  this.totalCount = formatText(data.totalCount);
                  this.totalLength = sprintf(
                    t("totalLengthText"),
                    Math.floor(data.totalLength / 1000 / 60 / 60),
                    Math.floor((data.totalLength / 1000 / 60) % 60),
                    Math.floor((data.totalLength / 1000) % 60),
                  );
                  this.highestCount = formatText(data.highestCount);
                  this.date = toDate(data.date);
                  this.avatarLevels = data.avatarLevels;
                  this.avatarAbility5K = data.avatarAbility5K;
                  this.avatarAbility5KClass = data.avatarAbility5KClass;
                  this.avatarAbility5KPlace = data.avatarAbility5KPlace;
                  this.avatarAbility5KCount = data.avatarAbility5KCount;
                  this.avatarAbility7K = data.avatarAbility7K;
                  this.avatarAbility7KClass = data.avatarAbility7KClass;
                  this.avatarAbility7KPlace = data.avatarAbility7KPlace;
                  this.avatarAbility7KCount = data.avatarAbility7KCount;
                  this.avatarAbility9K = data.avatarAbility9K;
                  this.avatarAbility9KClass = data.avatarAbility9KClass;
                  this.avatarAbility9KPlace = data.avatarAbility9KPlace;
                  this.avatarAbility9KCount = data.avatarAbility9KCount;
                  this.dateSet = data.dateSet.map((date) =>
                    new Date(date).toLocaleDateString(),
                  );
                  this.dateValues = data.dateValues;
                  this.quitStatusValues = data.quitStatusValues;
                });
              }
              break;
          }
        }
      }
    },

    async getAvatarFavorites5K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "5K",
        (isLoading) => (this.isFavorites5KLoading = isLoading),
        (favorites) => (this.favorites5K = favorites),
      );
    },

    async getAvatarFavorites7K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "7K",
        (isLoading) => (this.isFavorites7KLoading = isLoading),
        (favorites) => (this.favorites7K = favorites),
      );
    },

    async getAvatarFavorites9K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "9K",
        (isLoading) => (this.isFavorites9KLoading = isLoading),
        (favorites) => (this.favorites9K = favorites),
      );
    },

    async getAvatarFavorites10K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "10K",
        (isLoading) => (this.isFavorites10KLoading = isLoading),
        (favorites) => (this.favorites10K = favorites),
      );
    },

    async getAvatarFavorites14K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "14K",
        (isLoading) => (this.isFavorites14KLoading = isLoading),
        (favorites) => (this.favorites14K = favorites),
      );
    },

    async getAvatarFavorites24K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "24K",
        (isLoading) => (this.isFavorites24KLoading = isLoading),
        (favorites) => (this.favorites24K = favorites),
      );
    },

    async getAvatarFavorites48K(t: TFunction) {
      await this.getAvatarFavorites(
        t,
        "48K",
        (isLoading) => (this.isFavorites48KLoading = isLoading),
        (favorites) => (this.favorites48K = favorites),
      );
    },

    async getAvatarFavorites(
      t: TFunction,
      www: string,
      onLoading: (isLoading: boolean) => void,
      onAwait: (lasts: Note[]) => void,
    ) {
      let lastMillis = getMillis();

      return (async () => {
        lastMillis = getMillis();
        onLoading(true);
        const { status, data } = await wwwAXIOS.get<GetAvatarFavoritesAPI>(
          `/avatar/favorites/${www}`,
          {
            params: { avatarID: this.avatarID },
          },
        );
        if (getMillis() >= lastMillis) {
          switch (status) {
            case 200:
              runInAction(() => {
                onAwait(
                  data.map((favorite) => ({
                    ...favorite,
                    fittedText: sprintf(t("textHandled"), favorite.totalCount),
                  })),
                );
                onLoading(false);
              });
              break;
          }
        }
      })();
    },

    async getAvatarLasts5K() {
      await this.getAvatarLasts(
        "5K",
        (isLoading) => (this.isLasts5KLoading = isLoading),
        (lasts) => (this.lasts5K = lasts),
      );
    },

    async getAvatarLasts7K() {
      await this.getAvatarLasts(
        "7K",
        (isLoading) => (this.isLasts7KLoading = isLoading),
        (lasts) => (this.lasts7K = lasts),
      );
    },

    async getAvatarLasts9K() {
      await this.getAvatarLasts(
        "9K",
        (isLoading) => (this.isLasts9KLoading = isLoading),
        (lasts) => (this.lasts9K = lasts),
      );
    },

    async getAvatarLasts10K() {
      await this.getAvatarLasts(
        "10K",
        (isLoading) => (this.isLasts10KLoading = isLoading),
        (lasts) => (this.lasts10K = lasts),
      );
    },

    async getAvatarLasts14K() {
      await this.getAvatarLasts(
        "14K",
        (isLoading) => (this.isLasts14KLoading = isLoading),
        (lasts) => (this.lasts14K = lasts),
      );
    },

    async getAvatarLasts24K() {
      await this.getAvatarLasts(
        "24K",
        (isLoading) => (this.isLasts24KLoading = isLoading),
        (lasts) => (this.lasts24K = lasts),
      );
    },

    async getAvatarLasts48K() {
      await this.getAvatarLasts(
        "48K",
        (isLoading) => (this.isLasts48KLoading = isLoading),
        (lasts) => (this.lasts48K = lasts),
      );
    },

    async getAvatarLasts(
      www: string,
      onLoading: (isLoading: boolean) => void,
      onAwait: (lasts: Note[]) => void,
    ) {
      let lastMillis = getMillis();

      return (async () => {
        lastMillis = getMillis();
        onLoading(true);
        const { status, data } = await wwwAXIOS.get<GetAvatarLastsAPI>(
          `/avatar/lasts/${www}`,
          {
            params: { avatarID: this.avatarID },
          },
        );
        if (getMillis() >= lastMillis) {
          switch (status) {
            case 200:
              runInAction(() => {
                onAwait(
                  data.map((last) => ({
                    ...last,
                    fittedText: toDate(last.date),
                  })),
                );
                onLoading(false);
              });
              break;
          }
        }
      })();
    },

    async getAvatarAbilities5K() {
      await this.getAvatarAbilities(
        "5K",
        (isLoading) => (this.isAbilities5KLoading = isLoading),
        (abilities) => (this.abilities5K = abilities),
      );
    },

    async getAvatarAbilities7K() {
      await this.getAvatarAbilities(
        "7K",
        (isLoading) => (this.isAbilities7KLoading = isLoading),
        (abilities) => (this.abilities7K = abilities),
      );
    },

    async getAvatarAbilities9K() {
      await this.getAvatarAbilities(
        "9K",
        (isLoading) => (this.isAbilities9KLoading = isLoading),
        (abilities) => (this.abilities9K = abilities),
      );
    },

    async getAvatarAbilities(
      www: string,
      onLoading: (isLoading: boolean) => void,
      onAwait: (abilities: Note[]) => void,
    ) {
      let lastMillis = getMillis();

      return (async () => {
        lastMillis = getMillis();
        onLoading(true);
        const { status, data } = await wwwAXIOS.get<GetAvatarAbilitiesAPI>(
          `/avatar/ability/${www}`,
          {
            params: { avatarID: this.avatarID },
          },
        );
        if (getMillis() >= lastMillis) {
          switch (status) {
            case 200:
              runInAction(() => {
                onAwait(
                  data.map((ability) => ({
                    ...ability,
                    fittedText: toDate(ability.date),
                  })),
                );
                onLoading(false);
              });
              break;
          }
        }
      })();
    },

    async getAvatarWwwLevels() {
      lastMillisWwwLevels = getMillis();
      this.isWwwLevelLoading = true;
      const { status, data } = await wwwAXIOS.get<GetAvatarWwwLevelsAPI>(
        "/avatar/wwwLevels",
        {
          params: { avatarID: this.avatarID },
        },
      );
      if (getMillis() >= lastMillisWwwLevels) {
        switch (status) {
          case 200:
            runInAction(() => {
              this.wwwLevels = data;
              this.isWwwLevelLoading = false;
            });
            break;
        }
      }
    },
  };
}
