package com.fp.general.security.rules;

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

import com.fp.common.helper.Constant;
import com.fp.common.logger.APPLogger;
import com.fp.dto.Response;
import com.fp.dto.query.QueryRequest;
import com.fp.general.db.DataHelper;
import com.fp.general.exception.GeneralException;
import com.fp.general.helper.MenuHelper;
import com.fp.persistence.pgeneral.menu.TgeneMenuLevel;
import com.fp.persistence.pgeneral.menu.TgeneMenuLevelDesc;
import com.fp.persistence.pgeneral.menu.TgeneMenuProfile;
import com.fp.persistence.pgeneral.menu.TgeneMenuSubLevel;
import com.fp.persistence.pgeneral.menu.TgeneMenuSubLevelDesc;

/**
 * Clase que se encarga de armar y entregar el menu, asociado a un perfil.
 * 
 * @author Jorge Vaca
 * @version 2.1
 */
public class Menu extends MenuHelper {

    /** Map que contiene los datos del menu. */
    private final Map<String, Object> rootmenu = new HashMap<String, Object>();

    /*
     * (non-Javadoc)
     * 
     * @see com.fp.dto.rules.QueryRule#process(com.fp.dto.query.QueryRequest)
     */
    @Override
    public QueryRequest process(QueryRequest pQueryRequest) throws Exception {
        Response response = pQueryRequest.getResponse();
        String profile = pQueryRequest.getProfile();
        String language = pQueryRequest.getLanguage();
        TgeneMenuProfile menuprofile = DataHelper.getInstance().getTgeneMenuProfile(profile);
        if (menuprofile != null) {
            List<TgeneMenuLevel> lMenuLevel = DataHelper.getInstance().getTgeneMenuLevel(menuprofile.getMenucode());
            List<Map<String, Object>> lLevels = new ArrayList<Map<String, Object>>();
            for (TgeneMenuLevel obj : lMenuLevel) {
                this.completeLevel(obj, lLevels, language);
            }
            rootmenu.put("items", lLevels);
            rootmenu.put("label", "t");
            response.put("rootmenu", rootmenu);
        } else {
            throw new GeneralException("GENE-0017", "EL PERFIL {0} NO TIENE ASOCIADO UN MENU", profile);
        }
        return pQueryRequest;
    }

    /**
     * Metodo que completa datos del grupo de menu.
     * 
     * @param pTgeneMenuGroup Definicion de grupo de menu.
     * @param pGroup Grupo de menu a completar datos.
     * @param languagecode Codigo de lenguage.
     * @return boolean
     * @throws Exception
     */
    private boolean completeLevel(TgeneMenuLevel pTgeneMenuLevel, List<Map<String, Object>> lLevels, String languagecode) throws Exception {
        TgeneMenuLevelDesc tgeneMenuLevelDesc = DataHelper.getInstance().getTgeneMenuLevelDesc(pTgeneMenuLevel.getPk().getMenucode(),
                pTgeneMenuLevel.getPk().getLevelcode(), languagecode);
        if (tgeneMenuLevelDesc != null) {
            String labelMenu = tgeneMenuLevelDesc.getDescription();
            if (labelMenu == null) {
                labelMenu = "ETIQUETA DE MENU NO DEFINIDA";
            }
            Map<String, Object> mlevel = new HashMap<String, Object>();
            mlevel.put("t", Constant.capitalize(labelMenu));
            mlevel.put("sl", Constant.ifYes(pTgeneMenuLevel.getHavesublevel()) == true ? "Y" : "N");
            List<Object> lData = super.completTransactionByLevel(tgeneMenuLevelDesc, languagecode);
            if (Constant.ifYes(pTgeneMenuLevel.getHavesublevel())) {
                this.fillSubLevel(pTgeneMenuLevel, lData, languagecode);
            }
            mlevel.put("items", lData);
            lLevels.add(mlevel);
        }
        return true;
    }

    /**
     * Metodo que se encarga de construir ya dicionar el segundo nivel del menu.
     * 
     * @param pTgeneMenuLevel Datos del segundo nivel del menu.
     * @param lData Lista que contiene los datos del primer nivel del menu, al cual se adiciona los datos del segundo
     *            nivel del menu.
     * @param languagecode Codigo de lenguaje del usuario.
     * @throws Exception
     */
    private void fillSubLevel(TgeneMenuLevel pTgeneMenuLevel, List<Object> lData, String languagecode) throws Exception {
        List<TgeneMenuSubLevel> lSubLevel = DataHelper.getInstance().getTgeneMenuSuLevels(pTgeneMenuLevel.getPk().getMenucode(),
                pTgeneMenuLevel.getPk().getLevelcode());
        if (lSubLevel == null) {
            return;
        }
        for (TgeneMenuSubLevel obj : lSubLevel) {
            Map<String, Object> mLevel = new HashMap<String, Object>();
            this.completeSubLevel(obj, mLevel, languagecode);
            if (!mLevel.isEmpty()) {
                lData.add(mLevel);
            } else {
                APPLogger.getLogger().debug(
                        "\nETIQUETA DE SUBNIVEL NO DEFINIDA\n\tmenucode=" + obj.getPk().getMenucode() + ";\n\tlevelcode="
                                + obj.getPk().getLevelcode() + ";\n\tsublevelcode=" + obj.getPk().getSublevel() + ";\n\tlanguage=" + languagecode);
            }
        }
    }

    /**
     * Metodo que completa datos del segundo nivel del menu.
     * 
     * @param pMenuSubLevel Datos del segundo nivel del menu.
     * @param mLevel Map que contiene informacion de todas las opciones del segundo nivel del menu.
     * @param languagecode Codigo de lenguaje del usuario.
     * @throws Exception
     */
    private void completeSubLevel(TgeneMenuSubLevel pMenuSubLevel, Map<String, Object> mLevel, String languagecode) throws Exception {
        TgeneMenuSubLevelDesc subleveldesc = DataHelper.getInstance().getTgeneMenuSubLevelDesc(pMenuSubLevel.getPk().getMenucode(),
                pMenuSubLevel.getPk().getLevelcode(), pMenuSubLevel.getPk().getSublevel(), languagecode);
        if (subleveldesc != null) {
            String labelMenu = subleveldesc.getDescription();
            if (labelMenu == null) {
                labelMenu = "ETIQUETA DE MENU NO DEFINIDA";
            }
            mLevel.put("t", Constant.capitalize(labelMenu));
            super.completTransactionBySubLevel(subleveldesc, mLevel, languagecode);
        }
    }
}
