import { finales, initials, tones } from "./data";
import { IState } from "./store";
import { SylPart, Syllable, Tone } from "./types";
import { GetSyllablesByInitAndFin, getRandomArray, toggle } from "./utils";

export enum ActionType {
    toggleOne, toggleAll, refresh, setPause, setCount, setStatus, playing
}

export enum ToggleType { init, fin }
export type TogglePayload = { type: ToggleType, part: SylPart }

export type Action = { type: ActionType, payload?: number | ToggleType | TogglePayload };

interface IFounds { foundSyllables:Syllable[], foundTones: Tone[], randomTones: Tone[] }

interface IInitResult {
  allInitiales?:boolean,
  initiales: SylPart[],
  foundSyllables:Syllable[],
  foundTones: Tone[],
  randomTones: Tone[]
}

interface IFinResult {
  allfinales?:boolean,
  finales: SylPart[],
  foundSyllables:Syllable[],
  foundTones: Tone[],
  randomTones: Tone[]
}

const proceedFounds = ( initiales: SylPart[], finales:SylPart[], count: number):IFounds=>
{
  const foundSyllables:Syllable[] = GetSyllablesByInitAndFin( initiales, finales )
  const foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) )
  const randomTones = getRandomArray(foundTones, count)
  return { foundSyllables, foundTones, randomTones }
}

const ProceedAllInitials = (state: IState):IInitResult =>
{
  const toggled = state.allInitiales ? [] as SylPart[] : initials
  return {
    allInitiales: !state.allInitiales,
    initiales: toggled,
    ...proceedFounds(toggled, state.finales, state.sylCount)
  }
}

const ProceedAllFinales = (state: IState):IFinResult =>
{
  const toggled = state.allfinales ? [] as SylPart[] : finales
  return {
    allfinales: !state.allfinales,
    finales: toggled,
    ...proceedFounds(state.initiales, toggled, state.sylCount)
  }
}

const ProceedInitiale = (state: IState, index: SylPart):IInitResult =>
{
  const toggled = toggle(state.initiales,index)
  return {
    initiales: toggled,
    ...proceedFounds(toggled, state.finales, state.sylCount)
  }
}

const ProceedFinale = (state: IState, index: SylPart):IFinResult =>
{
  const toggled = toggle(state.finales,index)
  return {
    finales: toggled,
    ...proceedFounds(state.initiales, toggled, state.sylCount)
  }
}

export const reducer = (state:IState, action:Action):IState => {
  switch (action.type) {
    case ActionType.setPause: return { ...state, sylPause: action.payload as number }
    case ActionType.setCount: return { ...state,
                                       sylCount: action.payload as number,
                                       randomTones: getRandomArray(state.foundTones, action.payload as number) }
    case ActionType.refresh: return { ...state, randomTones: getRandomArray(state.foundTones, state.sylCount)}
    case ActionType.toggleAll:  {
      if (action.payload as ToggleType === ToggleType.init) return { ...state, ...ProceedAllInitials(state) }
      if (action.payload as ToggleType === ToggleType.fin)  return { ...state, ...ProceedAllFinales(state) }
      return state
    }
    case ActionType.toggleOne:  {
      if ( (action.payload as TogglePayload).type === ToggleType.init)
        return {  ...state, ...ProceedInitiale(state, (action.payload as TogglePayload).part )  }
        if ( (action.payload as TogglePayload).type === ToggleType.fin)
        return {  ...state, ...ProceedFinale(state, (action.payload as TogglePayload).part )  }
      return state
    }
    default: return state
  }
}