import { ReactNode, createContext, useContext, useMemo } from 'react';

import { Media, Season, Series, Type, UserMediaAdvancement } from '@/back-api';
import {
  ActivePlaylistServiceProps,
  useActivePlaylistServiceWrapped,
} from '@/service/ActivePlaylist';
import { MediaServiceProps, useMediaServiceWrapped } from '@/service/Media';
import { SeasonServiceProps, useSeasonServiceWrapped } from '@/service/Season';
import { SeriesServiceProps, useSeriesServiceWrapped } from '@/service/Series';
import { TypeServiceProps, useTypeServiceWrapped } from '@/service/Type';
import {
  RightGroup,
  SessionServiceProps,
  getRestConfig,
  useSessionServiceWrapped,
} from '@/service/session';
import { DataStoreType } from '@/utils/data-store';
import { AdvancementServiceProps, useAdvancementServiceWrapped } from './Advancement';

export type ServiceContextType = {
  session: SessionServiceProps;
  media: MediaServiceProps;
  series: SeriesServiceProps;
  season: SeasonServiceProps;
  type: TypeServiceProps;
  advancement: AdvancementServiceProps;
  activePlaylist: ActivePlaylistServiceProps;
};


function emptyStore<TYPE>(): DataStoreType<TYPE> {
  return {
    data: [] as TYPE[],
    isLoading: true,
    get: (_value: any, _key: any) => {
      console.error('!!! WTF !!!');
      return undefined;
    },
    gets: (_value: any, _key: any) => {
      console.error('!!! WTF !!!');
      return [];
    },
    error: undefined,
    update: (_request: Promise<TYPE>, _key?: string) => {
      console.error('!!! WTF !!!');
      return new Promise((_resolve, reject) => { reject("fail") });
    },
    updateRaw: (_data: TYPE, _key?: string) => { },
    remove: (_id: number | string, _request: Promise<void>, _key?: string): void => {
      console.error('!!! WTF !!!');
    }
  };
}

export const ServiceContext = createContext<ServiceContextType>({
  session: {
    setToken: (_token: string) => { },
    isConnected: false,
    clearToken: () => { },
    hasReadRight: (_part: RightGroup) => false,
    hasWriteRight: (_part: RightGroup) => false,
    getRestConfig: getRestConfig,
  },
  media: {
    store: emptyStore<Media>(),
  },
  series: {
    store: emptyStore<Series>(),
  },
  season: {
    store: emptyStore<Season>(),
  },
  type: {
    store: emptyStore<Type>(),
  },
  advancement: {
    store: emptyStore<UserMediaAdvancement>(),
  },
  activePlaylist: {
    playMediaList: [],
    MediaOffset: undefined,
    MediaActive: undefined,
    setNewPlaylist: (_listIds: number[]) => {
      console.error('!!! WTF !!!');
    },
    setNewPlaylistShuffle: (_listIds: number[]) => {
      console.error('!!! WTF !!!');
    },
    playInList: (_id: number, _listIds: number[]) => {
      console.error('!!! WTF !!!');
    },
    play: (_id: number) => {
      console.error('!!! WTF !!!');
    },
    previous: () => {
      console.error('!!! WTF !!!');
    },
    next: () => {
      console.error('!!! WTF !!!');
    },
    first: () => {
      console.error('!!! WTF !!!');
    },
    clear: () => {
      console.error('!!! WTF !!!');
    },
  },
});

export const useServiceContext = () => useContext(ServiceContext);

export const ServiceContextProvider = ({
  children,
}: {
  children: ReactNode;
}) => {
  const session = useSessionServiceWrapped();
  const media = useMediaServiceWrapped(session);
  const series = useSeriesServiceWrapped(session);
  const season = useSeasonServiceWrapped(session);
  const type = useTypeServiceWrapped(session);
  const advancement = useAdvancementServiceWrapped(session);
  const activePlaylist = useActivePlaylistServiceWrapped(media);
  const contextObjectData = useMemo(
    () => ({
      session,
      media,
      series,
      season,
      advancement,
      activePlaylist,
      type,
    }),
    [session, media, series, season]
  );
  return (
    <ServiceContext.Provider value={contextObjectData}>
      {children}
    </ServiceContext.Provider>
  );
};
