package it.integry.integrywmsnative.core.menu;

import com.annimon.stream.Stream;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import it.integry.integrywmsnative.core.class_router.configs.BaseMenuConfiguration;
import it.integry.integrywmsnative.core.class_router.configs.MenuConfiguration;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.menu.exception.MenuNotFoundException;
import it.integry.integrywmsnative.core.model.StbMenu;

@Singleton
public class MenuService {

    private static final String MENU_COD_OPZ = "MM007";

    private final MenuRESTConsumer menuRESTConsumer;

    private List<StbMenu> mInternalCachedMenu;
    private List<StbMenu> mInternalCachedFlatMenu;

    @Inject
    public MenuService(MenuRESTConsumer menuRESTConsumer) {
        this.menuRESTConsumer = menuRESTConsumer;
    }

    public void init(Runnable onMenuInitialized, RunnableArgs<Exception> onFailed) {
        menuRESTConsumer.retrieveMenu(MENU_COD_OPZ, menu -> {
            if(menu != null) {
                this.mInternalCachedMenu = menu.getStbMenuChildren();
                this.mInternalCachedFlatMenu = new ArrayList<>();
                flattenMenu(this.mInternalCachedMenu);
            }

            onMenuInitialized.run();
        }, onFailed);
    }

    public List<StbMenu> getMenu() throws Exception {
        if(mInternalCachedMenu == null) throw new MenuNotFoundException();

        return mInternalCachedMenu;
    }


    public boolean isGroupEnabled(MenuConfiguration.MenuGroup androidMenuGroup) throws Exception {
        List<StbMenu> dbMenu = getMenu();

        return Stream.of(this.mInternalCachedFlatMenu)
                .anyMatch(x -> x.getCodOpz().equalsIgnoreCase(androidMenuGroup.getCodMenu()));
    }


    public boolean isItemEnabled(BaseMenuConfiguration.MenuItem androidMenuItem) throws Exception {
        List<StbMenu> dbMenu = getMenu();

        return Stream.of(this.mInternalCachedFlatMenu)
                .anyMatch(x -> x.getCodOpz().equalsIgnoreCase(androidMenuItem.getCodMenu()));
    }

    private void flattenMenu(List<StbMenu> menu) {
        for(StbMenu stbMenu : menu) {
            this.mInternalCachedFlatMenu.add(stbMenu);

            if(stbMenu.getStbMenuChildren() != null && !stbMenu.getStbMenuChildren().isEmpty()) {
                flattenMenu(stbMenu.getStbMenuChildren());
            }
        }
    }

    public void invalidateCache() {
        this.mInternalCachedMenu = null;
        this.mInternalCachedFlatMenu = null;
    }

}
