import React, { createContext, useContext, useState, ReactNode } from 'react';
import { useMyIonStore } from './MyIonStore';
import { MatchingFrezyRanking, MatchingFrenzyResult } from './MatchingFrezyRanking';
import { ConnectiveRevisionAllResult, ConnectiveRevisionResult } from './ConnectiveRevisionRanking';
import { MATCH_FRENZY_SCOREBOARD_KEY } from '../constants';
import IListeningPracticeQuestion from '../interfaces/IListeningPracticeQuestion';

const MyIonQuizContext = createContext<MyContextProps | undefined>(undefined);

export const MyIonQuizProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [my_context, setMyContext] = useState<string>('initial value');
  const { myIonStoreRead, myIonStoreWrite } = useMyIonStore();

  function Helloworld() {
    listening_practice_correction_list;
  }
  const [listening_practice_result, setListeningPracticeResult] = useState<number>(0);
  const [listening_practice_current_test, setListeningPracticeCurrentTest] = useState<number>(0);
  const [listening_practice_correction_list, setListeningPracticeCorrectionList] = useState<any[] | []>([]);
  //
  function appendToListeningPracticeCorrectionList(question: IListeningPracticeQuestion) {
    setListeningPracticeCorrectionList([...listening_practice_correction_list, question]);
  }
  //
  function resetListeningPracticeCorrectionList() {
    setListeningPracticeCorrectionList([]);
  }
  //
  const [matching_frenzy_result, setMatchingFrenzyResult] = useState<number>(0);
  const [matching_frenzy_current_test, setMatchingFrenzyCurrentTest] = useState<number>(0);
  //
  const getCategoryKey = (category: string) => `${MATCH_FRENZY_SCOREBOARD_KEY}/${category}`;
  //
  async function loadMatchingFrenzyScoreBoard(cat_name: string): Promise<MatchingFrezyRanking> {
    let category_key = getCategoryKey(cat_name);

    let current_result = JSON.parse(await myIonStoreRead(category_key));
    if (!current_result || JSON.stringify(current_result) == '{}') {
      current_result = { ranking: [] };
    }
    return current_result;
  }

  async function saveMatchingFrenzyResultToScoreBoard(cat_name: string, result: MatchingFrenzyResult) {
    let category_key = getCategoryKey(cat_name);
    let current_result: MatchingFrezyRanking = await loadMatchingFrenzyScoreBoard(cat_name);
    current_result['ranking'] = [...current_result['ranking'], result];
    current_result['ranking'].sort((a: MatchingFrenzyResult, b: MatchingFrenzyResult) => b.result - a.result).splice(3);
    myIonStoreWrite(category_key, JSON.stringify(current_result));
  }
  //
  const [connective_revision_progress, setConnectiveRevisionProgress] = useState<number>(0);
  const [connective_revision_current_test, setConnectiveRevisionCurrentTest] = useState<number>(0);
  //
  const CONNECT_REVISION_SCOREBOARD_KEY = 'connective_revision_scoreboard';
  async function loadConnectiveRevisionScoreBoard(): Promise<ConnectiveRevisionAllResult> {
    let current_result = JSON.parse(await myIonStoreRead(CONNECT_REVISION_SCOREBOARD_KEY));
    if (!current_result || JSON.stringify(current_result) == '{}') {
      current_result = {};
    }
    return current_result;
  }

  async function saveConnectiveRevisionResultToScoreBoard(quiz_index: string, progress: number) {
    let current_result: ConnectiveRevisionAllResult = await loadConnectiveRevisionScoreBoard();
    current_result = { ...current_result, [quiz_index]: progress };
    myIonStoreWrite(CONNECT_REVISION_SCOREBOARD_KEY, JSON.stringify(current_result));
  }

  return (
    <MyIonQuizContext.Provider
      value={{
        my_context,
        setMyContext,
        //
        listening_practice_current_test,
        setListeningPracticeCurrentTest,
        //
        listening_practice_result,
        setListeningPracticeResult,
        //
        listening_practice_correction_list,
        setListeningPracticeCorrectionList,
        appendToListeningPracticeCorrectionList,
        resetListeningPracticeCorrectionList,
        //
        matching_frenzy_current_test,
        setMatchingFrenzyCurrentTest,
        loadMatchingFrenzyScoreBoard,
        saveMatchingFrenzyResultToScoreBoard,
        matching_frenzy_result,
        setMatchingFrenzyResult,
        //
        connective_revision_progress,
        setConnectiveRevisionProgress,
        connective_revision_current_test,
        setConnectiveRevisionCurrentTest,
        loadConnectiveRevisionScoreBoard,
        saveConnectiveRevisionResultToScoreBoard,
        //
        Helloworld
      }}
    >
      {children}
    </MyIonQuizContext.Provider>
  );
};

export const useMyIonQuizContext = (): MyContextProps => {
  const context = useContext(MyIonQuizContext);
  if (!context) {
    throw new Error('useMyContext must be used within a MyProvider');
  }
  return context;
};

interface MyContextProps {
  my_context: string;
  setMyContext: React.Dispatch<React.SetStateAction<string>>;
  //
  //
  listening_practice_result: number;
  setListeningPracticeResult: React.Dispatch<React.SetStateAction<number>>;
  //
  listening_practice_current_test: number;
  setListeningPracticeCurrentTest: React.Dispatch<React.SetStateAction<number>>;
  //
  listening_practice_correction_list: IListeningPracticeQuestion[];
  setListeningPracticeCorrectionList: React.Dispatch<React.SetStateAction<IListeningPracticeQuestion[]>>;
  appendToListeningPracticeCorrectionList: (question: IListeningPracticeQuestion) => void;
  resetListeningPracticeCorrectionList: () => void;
  //
  matching_frenzy_result: number;
  setMatchingFrenzyResult: React.Dispatch<React.SetStateAction<number>>;
  matching_frenzy_current_test: number;
  setMatchingFrenzyCurrentTest: React.Dispatch<React.SetStateAction<number>>;
  loadMatchingFrenzyScoreBoard: (cat_name: string) => Promise<MatchingFrezyRanking>;
  saveMatchingFrenzyResultToScoreBoard: (cat_name: string, result: MatchingFrenzyResult) => Promise<void>;
  //
  connective_revision_progress: number;
  setConnectiveRevisionProgress: React.Dispatch<React.SetStateAction<number>>;
  connective_revision_current_test: number;
  setConnectiveRevisionCurrentTest: React.Dispatch<React.SetStateAction<number>>;
  loadConnectiveRevisionScoreBoard: () => Promise<ConnectiveRevisionAllResult>;
  saveConnectiveRevisionResultToScoreBoard: (quiz_index: string, progress: number) => Promise<void>;
  //
  Helloworld: () => void;
}
