import { ChartDataPoint } from './../model/ChartDataPoint.model';
import { PrivateCharts } from './../model/PrivateCharts.model';
import { AppState } from "src/app/store/app.reducers";
import { Chart } from '../model/Chart.model';
import { ChartsActions, SET_PRIVATE_CHARTS, SET_PUBLIC_CHARTS, PUT_USER_CHART, REMOVE_CHART, ADD_ADDED_CHART, REMOVE_ADDED_CHART, ADD_CHART_DATA } from './charts.actions';

export interface ChartsFeatureState extends AppState{
    charts: ChartsState
}

export interface ChartsState{
    publicCharts: Chart[];
    privateCharts: PrivateCharts;
    chartsData: Map<number, ChartDataPoint[]>;
}

const initialState: ChartsState = {
    publicCharts: null,
    privateCharts: null,
    chartsData: new Map()
}

export function chartsReducers(state = initialState, action: ChartsActions){
    switch (action.type){
        case SET_PRIVATE_CHARTS:
            return {
                ...state,
                privateCharts: action.privateCharts
            };
        case SET_PUBLIC_CHARTS:
            return {
                ...state,
                publicCharts: action.publicCharts
            };
        case PUT_USER_CHART:
            let index: number;
            let privates: PrivateCharts = state.privateCharts;
            if (privates && privates.usersCharts !== null && privates.usersCharts !== undefined){
                let userCharts: Chart[] = privates.usersCharts;
                index = userCharts.findIndex((chart: Chart) => chart.id === action.chart.id);
                index > -1 ? userCharts[index] = action.chart : userCharts.unshift(action.chart);
                privates.usersCharts = userCharts;
            }
            let publics: Chart[] = state.publicCharts;
            if (state.publicCharts != null){
                index = publics.findIndex((chart: Chart) => chart.id === action.chart.id);
                if (action.chart.publicChart)
                    index > -1 ? publics[index] = action.chart : publics.unshift(action.chart);
                else if (index > -1){
                    publics.splice(index, 1);
                }
            }
            return {
                ...state,
                privateCharts: privates,
                publicCharts: publics
            }
        case ADD_ADDED_CHART:
            if(state.privateCharts === null)
                return state;
            return {
                ...state,
                privateCharts: {
                    ...state.privateCharts,
                    addedCharts: [...state.privateCharts.addedCharts, action.chart]
                }
            }
        case REMOVE_ADDED_CHART: 
            if(state.privateCharts === null)
                return state;
            let addedCharts: Chart[] = state.privateCharts.addedCharts;
            let updatedAddedCharts = addedCharts.filter((chart: Chart) => { return chart.id !== action.chartId })
            return {
                ...state,
                privateCharts: {
                    ...state.privateCharts,
                    addedCharts: updatedAddedCharts
                }
            }
        case REMOVE_CHART:
            let publicCharts: Chart[] = state.publicCharts === null ? state.publicCharts : state.publicCharts.filter((chart: Chart) => chart.id !== action.chartId)
            let privateCharts;
            if (state.privateCharts === null){
                privateCharts = state.privateCharts;
            }
            else{
                privateCharts = {
                    ...state.privateCharts,
                    addedCharts: state.privateCharts.addedCharts.filter((chart: Chart) => chart.id !== action.chartId),
                    usersCharts: state.privateCharts.usersCharts.filter((chart: Chart) => chart.id !== action.chartId)
                }
            }
            return {
                ...state,
                publicCharts: publicCharts,
                privateCharts: privateCharts
            }
        case ADD_CHART_DATA:
            let chartsData: Map<number, ChartDataPoint[]> = state.chartsData; 
            let chartDataPoints: ChartDataPoint[] = chartsData.get(action.chartId);
            if (!chartDataPoints){
                chartsData.set(action.chartId, action.chartData);
            }
            return {
                ...state,
                chartsData: chartsData
            }
        default:
            return state;
    }
}
