import expect from 'expect';

import createTestState from 'mtest/helpers/createTestState';
import { makeFakeChannel } from 'mtest/fetchMocks/channel';
import { makeFakeGame } from 'mtest/fetchMocks/games';

import {
  getCurrentGameForChannelDirectory,
  channelDirectoryIsLoaded,
  channelDirectoryChannelList,
} from 'mweb/common/selectors/pages/channelDirectory';
import { ALL_CHANNELS } from 'mweb/common/reducers/data/channels';

describe('channel directory page selectors', () => {
  describe('getCurrentGameForChannelDirectory', () => {
    it('returns undefined if the the page reducer does not have an alias', () => {
      const state = createTestState();
      expect(getCurrentGameForChannelDirectory(state)).toEqual(undefined);
    });

    it('returns the game object', () => {
      const game = makeFakeGame();
      const state = createTestState({
        pages: {
          channelDirectory: {
            currentGameAlias: game.name,
          },
        },
        data: {
          games: {
            gameDetails: {
              [game.name]: game,
            },
            gameNameLookup: {
              [game.name]: game.name,
            },
          },
        },
      });
      expect(getCurrentGameForChannelDirectory(state)).toEqual(game);
    });
  });

  describe('channelDirectoryIsLoaded', () => {
    it('returns false if the the page reducer does not have an alias', () => {
      const state = createTestState();
      expect(channelDirectoryIsLoaded(state)).toEqual(false);
    });

    describe('ALL_CHANNELS', () => {
      it('returns true when there are any channels', () => {
        const channel = makeFakeChannel();
        const state = createTestState({
          pages: {
            channelDirectory: {
              currentGameAlias: ALL_CHANNELS,
            },
          },
          data: {
            channels: {
              channelDetails: {
                [channel.name]: channel,
              },
              channelsByGameLoadStatus: {
                [ALL_CHANNELS]: {
                  pagesLoaded: 1,
                },
              },
            },
          },
        });
        expect(channelDirectoryIsLoaded(state)).toEqual(true);
      });

      it('returns true when there are no channels but we have tried to fetch ALL_CHANNELS', () => {
        const state = createTestState({
          pages: {
            channelDirectory: {
              currentGameAlias: ALL_CHANNELS,
            },
          },
          data: {
            channels: {
              channelsByGameLoadStatus: {
                [ALL_CHANNELS]: {
                  pagesLoaded: 1,
                },
              },
            },
          },
        });
        expect(channelDirectoryIsLoaded(state)).toEqual(true);
      });

      it('returns false when there are no channels and we have not tried to fetch ALL_CHANNELS', () => {
        const state = createTestState({
          pages: {
            channelDirectory: {
              currentGameAlias: ALL_CHANNELS,
            },
          },
        });
        expect(channelDirectoryIsLoaded(state)).toEqual(false);
      });
    });

    describe('inidividual game', () => {
      describe('unresolvable alias', () => {
        it('returns false when we have not tried to load this alias before', () => {
          const state = createTestState({
            pages: {
              channelDirectory: {
                currentGameAlias: 'alias',
              },
            },
          });
          expect(channelDirectoryIsLoaded(state)).toEqual(false);
        });

        it('returns true when we have tried to load this alias before', () => {
          const state = createTestState({
            pages: {
              channelDirectory: {
                currentGameAlias: 'alias',
              },
            },
            data: {
              channels: {
                channelsByGameLoadStatus: {
                  alias: {},
                },
              },
            },
          });
          expect(channelDirectoryIsLoaded(state)).toEqual(true);
        });
      });

      describe('resolvable alias', () => {
        it('returns true when there are any channels for this game', () => {
          const gameName = 'game';
          const channel = makeFakeChannel({ game: gameName });
          const state = createTestState({
            pages: {
              channelDirectory: {
                currentGameAlias: gameName,
              },
            },
            data: {
              channels: {
                channelDetails: {
                  [channel.name]: channel,
                },
              },
              games: {
                gameNameLookup: {
                  [gameName]: gameName,
                },
              },
            },
          });
          expect(channelDirectoryIsLoaded(state)).toEqual(true);
        });

        it('returns true when there are not any channels for this game but we have tried to load', () => {
          const gameName = 'game';
          const state = createTestState({
            pages: {
              channelDirectory: {
                currentGameAlias: gameName,
              },
            },
            data: {
              channels: {
                channelsByGameLoadStatus: {
                  [gameName]: {},
                },
              },
              games: {
                gameNameLookup: {
                  [gameName]: gameName,
                },
              },
            },
          });
          expect(channelDirectoryIsLoaded(state)).toEqual(true);
        });

        it('returns false when there are not any channels for this game and we have not tried to load', () => {
          const gameName = 'game';
          const channel = makeFakeChannel({ game: 'other' });
          const state = createTestState({
            pages: {
              channelDirectory: {
                currentGameAlias: gameName,
              },
            },
            data: {
              channels: {
                channelDetails: {
                  [channel.name]: channel,
                },
              },
              games: {
                gameNameLookup: {
                  [gameName]: gameName,
                },
              },
            },
          });
          expect(channelDirectoryIsLoaded(state)).toEqual(false);
        });
      });
    });
  });

  describe('channelDirectoryChannelList', () => {
    const gameName = 'game';
    const channel1 = makeFakeChannel({
      viewerCount: 1,
      game: gameName,
      name: 'channel1',
    });
    const channel2 = makeFakeChannel({
      viewerCount: 12,
      game: 'other',
      name: 'channel2',
    });
    const channel3 = makeFakeChannel({
      viewerCount: 5,
      game: gameName,
      name: 'channel3',
    });
    const channelDetails = {
      [channel1.name]: channel1,
      [channel2.name]: channel2,
      [channel3.name]: channel3,
    };

    it('returns a properly ordered list of channels for a specific game', () => {
      const state = createTestState({
        pages: {
          channelDirectory: {
            currentGameAlias: gameName,
          },
        },
        data: {
          channels: {
            channelDetails: { ...channelDetails },
          },
          games: {
            gameNameLookup: {
              [gameName]: gameName,
            },
          },
        },
      });

      expect(channelDirectoryChannelList(state)).toEqual([channel3, channel1]);
    });

    it('returns a properly ordered list of channels for ALL_CHANNELS', () => {
      const state = createTestState({
        pages: {
          channelDirectory: {
            currentGameAlias: ALL_CHANNELS,
          },
        },
        data: {
          channels: {
            channelDetails: { ...channelDetails },
            channelsByGameLoadStatus: {
              [ALL_CHANNELS]: {
                pagesLoaded: 1,
              },
            },
          },
        },
      });

      expect(channelDirectoryChannelList(state)).toEqual([
        channel2,
        channel3,
        channel1,
      ]);
    });

    it('returns a properly ordered list of channels for ALL_CHANNELS, respecting pageSize argument', () => {
      const state = createTestState({
        pages: {
          channelDirectory: {
            currentGameAlias: ALL_CHANNELS,
          },
        },
        data: {
          channels: {
            channelDetails: { ...channelDetails },
            channelsByGameLoadStatus: {
              [ALL_CHANNELS]: {
                pagesLoaded: 1,
              },
            },
          },
        },
      });

      expect(channelDirectoryChannelList(state, 2)).toEqual([
        channel2,
        channel3,
      ]);
    });
  });
});
