/**
 * @author: Leonid Vinikov <czf.leo123@gmail.com>
 * @description: Responsible for hooks & actions.
 */
import $flow, { errors } from "@appsflow/core";
import {
    createSlice,
    PreloadedState,
    Slice,
    SliceCaseReducers,
} from '@reduxjs/toolkit';
import { getRoutes } from "./managers/routes";
import { getStore } from "./store";

export class Controller extends $flow.Controller {
    routes: {} = {};

    readonly slice: Slice;

    public constructor() {
        super();

        const initialState = ( this.constructor as typeof Controller ).getSliceInitialState();

        if ( Object.keys( initialState ).length ) {
            this.slice = this.createSlice();
        }
    }

    static getName() {
        return 'Flow/Redux/Controller'
    }

    static getSliceInitialState() : any {
        return {};
    }

    initialize() {
        this.register();
        this.setupHooks();
    }

    setupHooks() {
    }

    registerRoutes() {
        this.routes = getRoutes().register( Object.values( this.getRoutes() ), this );
    }

    getCommands(): { [ p: string ]: any } {
        return super.getCommands();
    }

    getData(): { [ p: string ]: any } {
        return super.getData();
    }

    getInternal(): { [ p: string ]: any } {
        return super.getInternal();
    }

    getRoutes(): { [ p: string ]: any }  {
        return {};
    }

    getReducers(): SliceCaseReducers<any> {
        throw new errors.ForceMethod( this, 'getReducers' );
    }

    getSlice(): Slice<PreloadedState<any>, SliceCaseReducers<any>, string> {
        return this.slice;
    }

    getState(): any {
        return getStore().getState()[ this.getName() ]
    }

    private createSlice() {
        const currentConstructor = ( this.constructor as typeof Controller )

        return createSlice( {
            name: currentConstructor.getName(),
            initialState: currentConstructor.getSliceInitialState(),
            reducers: this.getReducers()
        } );
    }
}

export default Controller;
