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

import {
  ActivePlaylistServiceProps,
  useActivePlaylistServiceWrapped,
} from '@/service/ActivePlaylist';
import { AlbumServiceProps, useAlbumServiceWrapped } from '@/service/Album';
import { ArtistServiceProps, useArtistServiceWrapped } from '@/service/Artist';
import { useGenderServiceWrapped } from '@/service/Gender';
import { SessionState } from '@/service/SessionState';
import { TrackServiceProps, useTrackServiceWrapped } from '@/service/Track';
import {
  RightPart,
  SessionServiceProps,
  getRestConfig,
  useSessionServiceWrapped,
} from '@/service/session';
import { Album, Artist, Gender, Track } from '@/back-api';
import { DataStoreType } from '@/utils/data-store';

export type ServiceContextType = {
  session: SessionServiceProps;
  track: TrackServiceProps;
  artist: ArtistServiceProps;
  album: AlbumServiceProps;
  gender: AlbumServiceProps;
  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) => { },
    clearToken: () => { },
    hasReadRight: (part: RightPart) => false,
    hasWriteRight: (part: RightPart) => false,
    state: SessionState.NO_USER,
    getRestConfig: getRestConfig,
  },
  track: {
    store: emptyStore<Track>(),
  },
  artist: {
    store: emptyStore<Artist>(),
  },
  album: {
    store: emptyStore<Album>(),
  },
  gender: {
    store: emptyStore<Gender>(),
  },
  activePlaylist: {
    playTrackList: [],
    trackOffset: undefined,
    trackActive: 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 !!!');
    },
  },
});

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

export const ServiceContextProvider = ({
  children,
}: {
  children: ReactNode;
}) => {
  const session = useSessionServiceWrapped();
  const track = useTrackServiceWrapped(session);
  const artist = useArtistServiceWrapped(session);
  const album = useAlbumServiceWrapped(session);
  const gender = useGenderServiceWrapped(session);
  const activePlaylist = useActivePlaylistServiceWrapped(track);
  const contextObjectData = useMemo(
    () => ({
      session,
      track,
      artist,
      album,
      activePlaylist,
      gender,
    }),
    [session, track, artist, album]
  );
  return (
    <ServiceContext.Provider value={contextObjectData}>
      {children}
    </ServiceContext.Provider>
  );
};
