import { Selector, createSelector } from '@ngrx/store';
import {
  InfoResponse,
  Info,
  EventJson
} from '@ucap-webmessenger/protocol-event';
import { EntityState, createEntityAdapter } from '@ngrx/entity';
import { FileInfo, FileDownloadInfo } from '@ucap-webmessenger/protocol-file';

export interface InfoListState extends EntityState<Info<EventJson>> {}
export interface FileInfoListState extends EntityState<FileInfo> {}
export interface FileInfoCheckListState extends EntityState<FileDownloadInfo> {}

export interface State {
  infoListProcessing: boolean;
  infoList: InfoListState;
  infoStatus: InfoResponse | null;
  remainInfo: boolean;

  fileInfoListProcessing: boolean;
  fileInfoList: FileInfoListState;
  fileInfoCheckList: FileInfoCheckListState;
  fileInfoSyncDate: string;
}

export const adapterInfoList = createEntityAdapter<Info<EventJson>>({
  selectId: info => info.seq,
  sortComparer: (a, b) => {
    return a.seq - b.seq;
  }
});
export const adapterFileInfoList = createEntityAdapter<FileInfo>({
  selectId: info => info.seq,
  sortComparer: (a, b) => {
    return b.seq - a.seq;
  }
});
export const adapterFileInfoCheckList = createEntityAdapter<FileDownloadInfo>({
  selectId: info => info.seq,
  sortComparer: (a, b) => {
    return b.seq - a.seq;
  }
});

const infoListInitialState: InfoListState = adapterInfoList.getInitialState({});
const fileInfoListInitialState: FileInfoListState = adapterFileInfoList.getInitialState(
  {}
);
const fileInfoCheckListInitialState: FileInfoCheckListState = adapterFileInfoCheckList.getInitialState(
  {}
);

export const initialState: State = {
  infoListProcessing: false,
  infoList: infoListInitialState,
  infoStatus: null,
  remainInfo: false,

  fileInfoListProcessing: false,
  fileInfoList: fileInfoListInitialState,
  fileInfoCheckList: fileInfoCheckListInitialState,
  fileInfoSyncDate: ''
};

const {
  selectAll: ngeSelectAllInfoList,
  selectEntities: ngeSelectEntitiesInfoList,
  selectIds: ngeSelectIdsInfoList,
  selectTotal: ngeSelectTotalInfoList
} = adapterInfoList.getSelectors();
const {
  selectAll: ngeSelectAllFileInfoList,
  selectEntities: ngeSelectEntitiesFileInfoList,
  selectIds: ngeSelectIdsFileInfoList,
  selectTotal: ngeSelectTotalFileInfoList
} = adapterFileInfoList.getSelectors();
const {
  selectAll: ngeSelectAllFileInfoCheckList,
  selectEntities: ngeSelectEntitiesFileInfoCheckList,
  selectIds: ngeSelectIdsFileInfoCheckList,
  selectTotal: ngeSelectTotalFileInfoCheckList
} = adapterFileInfoCheckList.getSelectors();

export function selectors<S>(selector: Selector<any, State>) {
  const selectInfoList = createSelector(
    selector,
    (state: State) => state.infoList
  );
  const selectFileInfoList = createSelector(
    selector,
    (state: State) => state.fileInfoList
  );
  const selectFileInfoCheckList = createSelector(
    selector,
    (state: State) => state.fileInfoCheckList
  );

  return {
    infoListProcessing: createSelector(
      selector,
      (state: State) => state.infoListProcessing
    ),
    remainInfo: createSelector(
      selector,
      (state: State) => state.remainInfo
    ),
    infoList: createSelector(
      selector,
      (state: State) => state.infoList
    ),
    infoStatus: createSelector(
      selector,
      (state: State) => state.infoStatus
    ),

    selectAllInfoList: createSelector(
      selectInfoList,
      ngeSelectAllInfoList
    ),
    selectEntitiesInfoList: createSelector(
      selectInfoList,
      ngeSelectEntitiesInfoList
    ),
    selectInfoList: (seq: number) =>
      createSelector(
        selectInfoList,
        ngeSelectEntitiesInfoList,
        (_, entities) => (!!entities ? entities[seq] : undefined)
      ),

    fileInfoListProcessing: createSelector(
      selector,
      (state: State) => state.fileInfoListProcessing
    ),
    fileInfoSyncDate: createSelector(
      selector,
      (state: State) => state.fileInfoSyncDate
    ),
    fileInfoList: createSelector(
      selector,
      (state: State) => state.fileInfoList
    ),
    fileInfoCheckList: createSelector(
      selector,
      (state: State) => state.fileInfoCheckList
    ),
    selectAllFileInfoList: createSelector(
      selectFileInfoList,
      ngeSelectAllFileInfoList
    ),
    selectEntitiesFileInfoList: createSelector(
      selectFileInfoList,
      ngeSelectEntitiesFileInfoList
    ),
    selectFileInfoList: (seq: number) =>
      createSelector(
        selectFileInfoList,
        ngeSelectEntitiesFileInfoList,
        (_, entities) => (!!entities ? entities[seq] : undefined)
      ),
    selectAllFileInfoCheckList: createSelector(
      selectFileInfoCheckList,
      ngeSelectAllFileInfoCheckList
    ),
    selectEntitiesFileInfoCheckList: createSelector(
      selectFileInfoCheckList,
      ngeSelectEntitiesFileInfoCheckList
    ),
    selectFileInfoCheckList: (seq: number) =>
      createSelector(
        selectFileInfoCheckList,
        ngeSelectEntitiesFileInfoCheckList,
        (_, entities) => (!!entities ? entities[seq] : undefined)
      )
  };
}
