package com.fp.frontend.controller.pgeneral.menu;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import org.primefaces.event.SelectEvent;

import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.dto.query.DtoQuery;
import com.fp.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.pgeneral.gene.CatalogDetailController;
import com.fp.frontend.controller.pgeneral.lov.LevelLovController;
import com.fp.frontend.controller.pgeneral.lov.SubLevelLovController;
import com.fp.frontend.controller.pgeneral.lov.TransactionLovController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;
import com.fp.persistence.pgeneral.menu.TgeneMenu;
import com.fp.persistence.pgeneral.menu.TgeneMenuLevelDesc;
import com.fp.persistence.pgeneral.menu.TgeneMenuLevelTran;
import com.fp.persistence.pgeneral.menu.TgeneMenuSubLevelDesc;
import com.fp.persistence.pgeneral.menu.TgeneMenuSubLevelTran;
import com.fp.persistence.pgeneral.trans.TgeneTransaction;

/**
 * Clase controladora del bean TgeneMenu.
 *
 * @author WPA
 * @version 2.1
 */
@ManagedBean
@ViewScoped
public class MenuController extends AbstractController<TgeneMenu> {

    private static final long serialVersionUID = 1L;

    public MenuController() throws Exception {
        super(TgeneMenu.class);
    }

    @ManagedProperty(value = "#{levelDescController}")
    private LevelDescController levelDesc;

    @ManagedProperty(value = "#{levelController}")
    private LevelController level;

    @ManagedProperty(value = "#{subLevelDescController}")
    private SubLevelDescController subLevelDesc;

    @ManagedProperty(value = "#{subLevelController}")
    private SubLevelController subLevel;

    @ManagedProperty(value = "#{menuLevelTranController}")
    private MenuLevelTranController levelTran;

    @ManagedProperty(value = "#{menuSubLevelTranController}")
    private MenuSubLevelTranController subLevelTran;

    private TgeneMenuLevelDesc menuleveldesc;

    @PostConstruct
    private void postconstruct() {
        this.init();
        // Inicializa autoconsulta
        super.startQuery();
        // Consulta
        this.querydatabase();
    }

    /**
     * Incializa el controlador, cuando se esta utilizando una pagina que utliza
     * el controlador.
     */
    private void init() {
        try {
            this.menuleveldesc = null;
            this.recperpage = 4; // Cambiar al # reg a mirar.
            this.lrecord = new ArrayList<>();
            this.beanalias = "TGENEMENU";
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    public void update() {
        try {
            //Menu level
            this.levelDesc.setGenemenu(this.record);
            this.levelDesc.initRecPage();
            this.levelDesc.setLrecord(new ArrayList<TgeneMenuLevelDesc>());

            //Menu Sublevel
            super.getMfilelds().put("pk.levelcode", null);
            super.getMfilelds().put("leveldescription", null);
            this.subLevelDesc.setGenemenu(this.record);
            this.subLevelDesc.setLrecord(new ArrayList<TgeneMenuSubLevelDesc>());

            //Menu levelTran
            super.getMfilelds().put("pk.levelcodetran", null);
            super.getMfilelds().put("leveldescriptiontran", null);
            this.levelTran.setGenemenu(this.record);
            this.levelTran.setLrecord(new ArrayList<TgeneMenuLevelTran>());

            //Menu levelTran
            this.menuleveldesc = null;
            super.getMfilelds().put("pk.levelcodesubtran", null);
            super.getMfilelds().put("leveldescriptionsubtran", null);
            super.getMfilelds().put("pk.sublevelcodesubtran", null);
            super.getMfilelds().put("subLeveldescriptionsubtran", null);
            this.subLevelTran.setGenemenu(this.record);
            this.subLevelTran.setLrecord(new ArrayList<TgeneMenuSubLevelTran>());

            super.update();
        } catch (Exception ex) {
            MessageHelper.setMessageError(ex);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void querydatabase() {
        try {

            Request request = this.callerhelper.getRequest();
            DtoQuery dto = super.getDtoQuery(true);
            dto.setOrderby("t.pk");

            HashMap<String, DtoQuery> mtables = new HashMap<String, DtoQuery>();
            mtables.put(this.beanalias, dto); // permite adicionar mas de una tabla.

            request.setQueryTables(mtables);

            Response resp = this.callerhelper.executeQuery(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                this.lrecord = new ArrayList<TgeneMenu>();
                MessageHelper.setMessageError(resp);
            } else {
                this.lrecord = (List<TgeneMenu>) resp.get(this.beanalias);
                super.postQuery(this.lrecord);
            }

        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    public void save() {
        try {
            boolean parentSave = true;
            Request request = this.callerhelper.getRequest();
            //Dto Menu
            DtoSave dtosave = super.getDtoSave();
            //Dto Menu Level Desc
            DtoSave dtosaveleveldesc = this.levelDesc.getDtoSave();
            //Dto Menu Level
            DtoSave dtosavelevel = this.level.getDtoSave();
            //Dto Menu SubLevel Desc
            DtoSave dtosavesubleveldesc = this.subLevelDesc.getDtoSave();
            //Dto Menu SubLevel
            DtoSave dtosavesublevel = this.subLevel.getDtoSave();
            //Dto Menu Level Tran
            DtoSave dtosaveleveltran = this.levelTran.getDtoSave();
            //Dto Menu SubLevel Tran
            DtoSave dtosavesubleveltran = this.subLevelTran.getDtoSave();

            //			if(!dtosave.pendingProcess() && !dtosaveleveldesc.pendingProcess() && !dtosavesubleveldesc.pendingProcess() && !dtosaveleveltran.pendingProcess() && !dtosavesubleveltran.pendingProcess()){
            //				return;
            //			}
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();

            if (dtosave.pendingProcess()) {
                msave.put(this.beanalias, dtosave);
                parentSave = false;
            }
            if (parentSave) {
                if (dtosaveleveldesc.pendingProcess()) {
                    msave.put(this.levelDesc.getBeanalias(), dtosaveleveldesc);
                    msave.put(this.level.getBeanalias(), dtosavelevel);
                }
                if (dtosavesubleveldesc.pendingProcess()) {
                    msave.put(this.subLevelDesc.getBeanalias(), dtosavesubleveldesc);
                    msave.put(this.subLevel.getBeanalias(), dtosavesublevel);
                }
                if (dtosaveleveltran.pendingProcess()) {
                    msave.put(this.levelTran.getBeanalias(), dtosaveleveltran);
                }
                if (dtosavesubleveltran.pendingProcess()) {
                    msave.put(this.subLevelTran.getBeanalias(), dtosavesubleveltran);
                }
            }

            request.setSaveTables(msave);
            Response resp = this.callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                if (!parentSave) {
                    this.save();
                } else {
                    this.levelDesc.postCommit(resp);
                    this.subLevelDesc.postCommit(resp);
                    this.levelTran.postCommit(resp);
                    this.subLevelTran.postCommit(resp);
                    MessageHelper.setMessageInfo(resp);
                }
            } else {
                MessageHelper.setMessageError(resp);
            }

        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void generateQuery(TgeneMenu tgenemenu) throws Exception {
        this.record = tgenemenu;
        this.generateQuery();
    }

    /**
     * M&eacute;todo que ejecuta el evento de seleccion del menu
     *
     * @throws Exception
     */
    public void generateQuery() throws Exception {

        //Menu level
        this.levelDesc.setGenemenu(this.record);
        this.levelDesc.initRecPage();
        this.levelDesc.query();

        //Menu Sublevel
        super.getMfilelds().put("pk.levelcode", null);
        super.getMfilelds().put("leveldescription", null);
        this.subLevelDesc.setGenemenu(this.record);
        this.subLevelDesc.setLrecord(new ArrayList<TgeneMenuSubLevelDesc>());

        //Menu levelTran
        super.getMfilelds().put("pk.levelcodetran", null);
        super.getMfilelds().put("leveldescriptiontran", null);
        this.levelTran.setGenemenu(this.record);
        this.levelTran.setLrecord(new ArrayList<TgeneMenuLevelTran>());

        //Menu levelTran
        this.menuleveldesc = null;
        super.getMfilelds().put("pk.levelcodesubtran", null);
        super.getMfilelds().put("leveldescriptionsubtran", null);
        super.getMfilelds().put("pk.sublevelcodesubtran", null);
        super.getMfilelds().put("subLeveldescriptionsubtran", null);
        this.subLevelTran.setGenemenu(this.record);
        this.subLevelTran.setLrecord(new ArrayList<TgeneMenuSubLevelTran>());
    }

    /**
     * Entrega una lista de objetos TgeneMenu
     *
     * @return lrecord Lista de objetos TgeneMenu
     */
    public static List<TgeneMenu> find() {
        try {
            MenuController cc = new MenuController();
            cc.init();
            cc.recperpage = 300;
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord;
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }

    }

    /**
     * Encuentra por el id de TgeneMenu
     *
     * @param id
     * @return
     */
    public static TgeneMenu findPerfil(Integer id) {
        try {
            if (id == null || id == 0) {
                return null;
            }
            MenuController cc = new MenuController();
            cc.init();
            cc.recperpage = 300;
            cc.addFilter("pk", id.toString());
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord.get(0);
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    /**
     * Llama al Lov MenuLevel
     */
    public void openMenuLevelLov() {
        if (this.record == null) {
            MessageHelper.setMessageError("msg_menucodeRequired");
            return;
        }
        List<String> values = new ArrayList<String>();
        values.add(this.record.getPk().toString());
        Map<String, List<String>> params = new HashMap<>();
        params.put("pk.menucode", values);
        LevelLovController.openLov(params);
    }

    /**
     * Llama al Lov MenuSubLevel
     */
    public void openMenuSubLevelLov() {
        if (this.record == null) {
            MessageHelper.setMessageError("msg_menucodeRequired");
            return;
        }
        if (this.menuleveldesc == null) {
            MessageHelper.setMessageError("msg_menuLevelRequired");
            return;
        }
        List<String> menucode = new ArrayList<String>();
        List<String> levelcode = new ArrayList<String>();
        menucode.add(this.menuleveldesc.getPk().getMenucode().toString());
        levelcode.add(this.menuleveldesc.getPk().getLevelcode().toString());
        Map<String, List<String>> params = new HashMap<>();
        params.put("pk.menucode", menucode);
        params.put("pk.levelcode", levelcode);
        SubLevelLovController.openLov(params);
    }

    /**
     * Gestiona la respuesta del Lov MenuLevel
     *
     * @param event
     * @throws Exception
     */
    public void onReturnMenuLevelLov(SelectEvent event) throws Exception {
        TgeneMenuLevelDesc t = (TgeneMenuLevelDesc) event.getObject();
        super.addField("pk.levelcode", t.getPk().getLevelcode().toString());
        super.addField("leveldescription", t.getDescription());
        this.subLevelDesc.setGenemenulevel(t);
        this.subLevelDesc.initRecPage();
        this.subLevelDesc.query();
    }

    /**
     * Gestiona la respuesta del Lov MenuLevel para transacciones por nivel
     *
     * @param event
     * @throws Exception
     */
    public void onReturnMenuLevelTranLov(SelectEvent event) throws Exception {
        TgeneMenuLevelDesc t = (TgeneMenuLevelDesc) event.getObject();
        super.addField("pk.levelcodetran", t.getPk().getLevelcode().toString());
        super.addField("leveldescriptiontran", t.getDescription());
        this.levelTran.setGenemenulevel(t);
        this.levelTran.initRecPage();
        this.levelTran.query();
    }

    /**
     * Gestiona la respuesta del Lov MenuLevel para transacciones por subnivel
     *
     * @param event
     * @throws Exception
     */
    public void onReturnMenuLevelTran2Lov(SelectEvent event) throws Exception {
        TgeneMenuLevelDesc t = (TgeneMenuLevelDesc) event.getObject();
        this.menuleveldesc = t;
        super.addField("pk.levelcodesubtran", t.getPk().getLevelcode().toString());
        super.addField("leveldescriptionsubtran", t.getDescription());
        super.addField("pk.sublevelcodesubtran", null);//
        super.addField("subLeveldescriptionsubtran", null);//
        this.subLevelTran.setLrecord(null);
        this.subLevelTran.setGenemenulevel(t);
    }

    /**
     * Gestiona la respuesta del Lov MenuLevel
     *
     * @param event
     * @throws Exception
     */
    public void onReturnMenuSubLevelLov(SelectEvent event) throws Exception {
        TgeneMenuSubLevelDesc t = (TgeneMenuSubLevelDesc) event.getObject();
        super.addField("pk.sublevelcodesubtran", t.getPk().getSublevel().toString());
        super.addField("subLeveldescriptionsubtran", t.getDescription());
        this.subLevelTran.setGenemenusublevel(t);
        this.subLevelTran.initRecPage();
        this.subLevelTran.query();
    }

    /**
     * Abre el lov de transacciones
     */
    public void openTransactionLov() {
        Map<String, List<String>> params = new HashMap<>();
        List<String> l = new ArrayList<>();
        l.add("TRANSACTION"); // valor del parametro
        params.put("processtype", l);

        TransactionLovController.openLov(params);
    }

    /**
     * Gestiona la respuesta del lov
     *
     * @param event
     * @throws Exception
     */
    public void onReturnTransactionLov(SelectEvent event) throws Exception {
        TgeneTransaction t = (TgeneTransaction) event.getObject();
        this.levelTran.getRecord().getPk().setTransactionmodule(t.getPk().getTransactionmodule());
        this.levelTran.getRecord().getPk().setTransactioncode(t.getPk().getTransactioncode());
        this.levelTran.getRecord().getPk().setTransactionversion(t.getPk().getTransactionversion());
        this.levelTran.getRecord().put("name", t.getName());
    }

    /**
     * Gestiona la respuesta del lov para el subnivel
     *
     * @param event
     * @throws Exception
     */
    public void onReturnSubTransactionLov(SelectEvent event) throws Exception {
        TgeneTransaction t = (TgeneTransaction) event.getObject();
        this.subLevelTran.getRecord().getPk().setTransactionmodule(t.getPk().getTransactionmodule());
        this.subLevelTran.getRecord().getPk().setTransactioncode(t.getPk().getTransactioncode());
        this.subLevelTran.getRecord().getPk().setTransactionversion(t.getPk().getTransactionversion());
        this.subLevelTran.getRecord().put("name", t.getName());
    }

    /**
     * Entrega el valor de levelDesc
     *
     * @return levelDesc
     */
    public LevelDescController getLevelDesc() {
        return levelDesc;
    }

    /**
     * Fija el valor de levelDesc
     *
     * @param levelDesc
     */
    public void setLevelDesc(LevelDescController levelDesc) {
        this.levelDesc = levelDesc;
    }

    /**
     * Entrega el valor de level
     *
     * @return level
     */
    public LevelController getLevel() {
        return level;
    }

    /**
     * Fija el valor de level
     *
     * @param level
     */
    public void setLevel(LevelController level) {
        this.level = level;
    }

    /**
     * Entrega el valor de subLevelDesc
     *
     * @return subLevelDesc
     */
    public SubLevelDescController getSubLevelDesc() {
        return subLevelDesc;
    }

    /**
     * Fija el valor de subLevelDesc
     *
     * @param subLevelDesc
     */
    public void setSubLevelDesc(SubLevelDescController subLevelDesc) {
        this.subLevelDesc = subLevelDesc;
    }

    /**
     * Entrega el valor de menuLevel
     *
     * @return menuLevel
     */
    public MenuLevelTranController getLevelTran() {
        return levelTran;
    }

    /**
     * Fija el valor de menuLevel
     *
     * @param menuLevel
     */
    public void setLevelTran(MenuLevelTranController levelTran) {
        this.levelTran = levelTran;
    }

    /**
     * Entrega el valor de subLevelTran
     *
     * @return subLevelTran
     */
    public MenuSubLevelTranController getSubLevelTran() {
        return subLevelTran;
    }

    /**
     * Fija el valor de subLevelTran
     *
     * @param subLevelTran
     */
    public void setSubLevelTran(MenuSubLevelTranController subLevelTran) {
        this.subLevelTran = subLevelTran;
    }

    /**
     * Entrega el valor de subLevel
     *
     * @return subLevel
     */
    public SubLevelController getSubLevel() {
        return subLevel;
    }

    /**
     * Fija el valor de subLevel
     *
     * @param subLevel
     */
    public void setSubLevel(SubLevelController subLevel) {
        this.subLevel = subLevel;
    }

}
