import * as actions from './search.action';

import { Criterion } from './model';

export interface State {
    pristine: boolean;
    currentStep: string;
    datasetName: string;
    criteriaStepChecked: boolean;
    outputStepChecked: boolean;
    resultStepChecked: boolean;
    coneSearchAdded: boolean;
    criteriaList: Criterion[];
    outputList: number[];
    searchData: any[];
    dataLengthIsLoading: boolean;
    dataLengthIsLoaded: boolean;
    dataLength: number;
    selectedData: any[];
    processWip: boolean;
    processDone: boolean;
    processId: string;
}

export const initialState: State = {
    pristine: true,
    currentStep: null,
    datasetName: null,
    criteriaStepChecked: false,
    outputStepChecked: false,
    resultStepChecked: false,
    coneSearchAdded: false,
    criteriaList: [],
    outputList: [],
    searchData: [],
    dataLengthIsLoading: false,
    dataLengthIsLoaded: false,
    dataLength: null,
    selectedData: [],
    processWip: false,
    processDone: false,
    processId: null
};

export function reducer(state: State = initialState, action: actions.Actions): State {
    switch (action.type) {
        case actions.CHANGE_STEP:
            const currentStep: string = action.payload;
            return {
                ...state,
                currentStep
            };

        case actions.SELECT_DATASET:
            const datasetName: string = action.payload;
            return {
                ...state,
                pristine: false,
                datasetName
            };

        case actions.NEW_SEARCH:
            return {
                ...initialState,
                currentStep: 'dataset'
            };

        case actions.CRITERIA_CHECKED:
            return {
                ...state,
                criteriaStepChecked: true
            };

        case actions.OUTPUT_CHECKED:
            return {
                ...state,
                outputStepChecked: true
            };

        case actions.RESULT_CHECKED:
            return {
                ...state,
                resultStepChecked: true
            };

        case actions.IS_CONE_SEARCH_ADDED:
            const coneSearchAdded: boolean = action.payload;

            return {
                ...state,
                coneSearchAdded
            };

        case actions.UPDATE_CRITERIA_LIST:
            const criteriaList: Criterion[] = action.payload;
            return {
                ...state,
                criteriaList
            };

        case actions.ADD_CRITERION:
            const criterion: Criterion = action.payload;
            return {
                ...state,
                criteriaList: [...state.criteriaList, criterion]
            };

        case actions.DELETE_CRITERION:
            const id: number = action.payload;
            return {
                ...state,
                criteriaList: [...state.criteriaList.filter(c => c.id !== id)]
            };

        case actions.UPDATE_OUTPUT_LIST:
            const outputList: number[] = action.payload;
            return {
                ...state,
                outputList
            };

        case actions.RETRIEVE_DATA_SUCCESS:
            const searchData: any[] = action.payload;
            return {
                ...state,
                searchData
            };

        case actions.GET_DATA_LENGTH:
            return {
                ...state,
                dataLengthIsLoading: true
            };

        case actions.GET_DATA_LENGTH_SUCCESS:
            const dataLength: number = action.payload;
            return {
                ...state,
                dataLengthIsLoading: false,
                dataLengthIsLoaded: true,
                dataLength
            };

        case actions.GET_DATA_LENGTH_FAIL:
            return {
                ...state,
                dataLengthIsLoading: false
            };

        case actions.ADD_SELECTED_DATA:
            const addData: number | string = action.payload;
            return {
                ...state,
                selectedData: [...state.selectedData, addData]
            };

        case actions.DELETE_SELECTED_DATA:
            const deleteData: number | string = action.payload;
            return {
                ...state,
                selectedData: [...state.selectedData.filter(d => d !== deleteData)]
            };

        case actions.EXECUTE_PROCESS:
            return {
                ...state,
                processWip: true,
                processDone: false
            };

        case actions.EXECUTE_PROCESS_WIP:
            const processId: string = action.payload;
            return {
                ...state,
                processId
            };

        case actions.EXECUTE_PROCESS_SUCCESS:
            return {
                ...state,
                processWip: false,
                processDone: true
            };

        case actions.EXECUTE_PROCESS_FAIL:
            return {
                ...state,
                processWip: false,
                processDone: false,
                processId: null
            };

        case actions.DESTROY_RESULTS:
            return {
                ...state,
                searchData: null,
                dataLength: null
            };

        case actions.RESET_SEARCH:
            return { ...initialState };

        default:
            return state;
    }
}

export const getPristine = (state: State) => state.pristine;
export const getCurrentStep = (state: State) => state.currentStep;
export const getDatasetName = (state: State) => state.datasetName;
export const getCriteriaStepChecked = (state: State) => state.criteriaStepChecked;
export const getOutputStepChecked = (state: State) => state.outputStepChecked;
export const getResultStepChecked = (state: State) => state.resultStepChecked;
export const getIsConeSearchAdded = (state: State) => state.coneSearchAdded;
export const getCriteriaList = (state: State) => state.criteriaList;
export const getOutputList = (state: State) => state.outputList;
export const getSearchData = (state: State) => state.searchData;
export const getDataLengthIsLoading = (state: State) => state.dataLengthIsLoading;
export const getDataLengthIsLoaded = (state: State) => state.dataLengthIsLoaded;
export const getDataLength = (state: State) => state.dataLength;
export const getSelectedData = (state: State) => state.selectedData;
export const getProcessWip = (state: State) => state.processWip;
export const getProcessDone = (state: State) => state.processDone;
export const getProcessId = (state: State) => state.processId;