package com.jeeww.core.service.impl;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jeeww.core.CommonConstants;
import com.jeeww.core.dao.QueryDAO;
import com.jeeww.core.ext.MapResultTransformer;
import com.jeeww.core.service.BaseService;
import com.jeeww.core.utils.AgileUiDataUtils;
import com.jeeww.core.utils.BeanUtilsEx;
import com.jeeww.core.utils.JsonUtils;
import com.jeeww.core.utils.MessageUtils;
import com.jeeww.core.utils.AgileUtils;
import com.jeeww.core.vo.ComboConfig;
import com.jeeww.core.vo.Pager;
import com.jeeww.core.vo.TreeConfig;
import com.jeeww.core.vo.TreeGridConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 类描述：接口.
 * @author 蒋文武
 */
@Service("BaseServiceImpl")
public class BaseServiceImpl implements BaseService {

    /**
     * logger.
     */
    private Logger logger = Logger.getLogger(BaseServiceImpl.class);
    /**
     * queryDAO.
     */
    @Autowired
    private QueryDAO queryDAO;

    /**
     * @return the queryDAO
     */
    public QueryDAO getBaseDAO() {
        return queryDAO;
    }

    @Override
    public String getGridByHQLNamedQuery(final String namedQuery, final Pager pager) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("----------HQL命名分页查询执行----------");
        }
        Object searchModel = pager.getSearchModel();
        String queryString = AgileUtils.stringEvaluate(queryDAO.getNamedQueryString(namedQuery), searchModel);
        int resultCount = queryDAO.getCountByHQL(AgileUtils.getCountQueryString(queryString), searchModel);
        Query query = queryDAO.getQuery(queryString, searchModel);
        int resultStartIndex = (pager.getPage() - 1) * pager.getPageSize();
        query.setFirstResult(resultStartIndex);
        query.setMaxResults(pager.getPageSize());
        List<?> list = query.list();
        pager.setResultCount(resultCount);
        pager.setResult(list);
        return AgileUiDataUtils.getDataForAgileGrid(pager);
    }

    @Override
    public String getGridBySQLNamedQuery(final String namedQuery, final Pager pager) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("----------SQL命名分页查询执行----------");
        }
        Object searchModel = pager.getSearchModel();
        String queryString = AgileUtils.stringEvaluate(queryDAO.getNamedQueryString(namedQuery), searchModel);
        int resultCount = queryDAO.getCountBySQL(AgileUtils.getCountQueryString(queryString), searchModel);
        SQLQuery query = queryDAO.getSQLQuery(queryString, searchModel);
        int resultStartIndex = (pager.getPage() - 1) * pager.getPageSize();
        query.setFirstResult(resultStartIndex);
        query.setMaxResults(pager.getPageSize());
        query.setResultTransformer(MapResultTransformer.INSTANCE);
        List<?> list = query.list();
        pager.setResultCount(resultCount);
        pager.setResult(list);
        return AgileUiDataUtils.getDataForAgileGrid(pager);
    }

    @Override
    public String getGridByHQL(final String hql, final Pager pager) throws Exception {
        Object searchModel = pager.getSearchModel();
        int resultCount = queryDAO.getCountByHQL(AgileUtils.getCountQueryString(hql), searchModel);
        Query query = queryDAO.getQuery(hql, searchModel);
        List<?> list = query.list();
        pager.setResultCount(resultCount);
        pager.setResult(list);
        return AgileUiDataUtils.getDataForAgileGrid(pager);
    }

    @Override
    public String getGridBySQL(final String sql, final Pager pager) throws Exception {
        Object searchModel = pager.getSearchModel();
        int resultCount = queryDAO.getCountBySQL(AgileUtils.getCountQueryString(sql), searchModel);
        SQLQuery query = queryDAO.getSQLQuery(sql, searchModel);
        int resultStartIndex = (pager.getPage() - 1) * pager.getPageSize();
        query.setFirstResult(resultStartIndex);
        query.setMaxResults(pager.getPageSize());
        query.setResultTransformer(MapResultTransformer.INSTANCE);
        List<?> list = query.list();
        pager.setResultCount(resultCount);
        pager.setResult(list);
        return AgileUiDataUtils.getDataForAgileGrid(pager);
    }

    @Override
    public JSONArray getTreeBySQLNamedQuery(final Object searchModel, final TreeConfig treeConfig) throws Exception {
        JSONArray treeNodes = new JSONArray(); // 菜单下面的资源信息
        String namedQuery = treeConfig.getTreeNamedQueryIdForTree();
        List<Map<String, Object>> subMenuList = queryDAO.queryBySQLNamedQuery(namedQuery, searchModel); // 查询子菜单
        for (int i = 0; i < subMenuList.size(); i++) {
            Map<String, Object> obj = subMenuList.get(i);
            JSONObject node = new JSONObject(); // 单个子节点
            node.put(treeConfig.getTreeIdName(), obj.get(treeConfig.getTreeIdProperty()));
            node.put(treeConfig.getTreeTextName(), obj.get(treeConfig.getTreeNameProperty()));
            BeanUtilsEx.copyProperties(searchModel, obj);
            if (queryDAO.checkIsHave(treeConfig.getTreeNamedQueryIdForCheck(), searchModel)) {
                node.put(treeConfig.getTreeChildrenName(), getTreeBySQLNamedQuery(searchModel, treeConfig));
            }
            treeNodes.add(node);
        }
        return treeNodes;
    }

    @Override
    public String getComboBySQLNamedQuery(final Object searchModel, final ComboConfig comboConfig) throws Exception {
        JSONArray comboNodes = new JSONArray();
        List<Map<String, Object>> subMenuList = queryDAO.queryBySQLNamedQuery(
                comboConfig.getComboNamedQueryIdForCombo(), searchModel);
        for (int i = 0; i < subMenuList.size(); i++) {
            Map<String, Object> obj = subMenuList.get(i);
            JSONObject node = new JSONObject(); // 单个子节点
            node.put(comboConfig.getComboIdName(), obj.get(comboConfig.getComboIdProperty()));
            node.put(comboConfig.getComboTextName(), obj.get(comboConfig.getComboNameProperty()));
            if (!StringUtils.isEmpty(comboConfig.getComboDescProperty())) {
                node.put(comboConfig.getComboDescName(), obj.get(comboConfig.getComboDescProperty()));
            }
            comboNodes.add(node);
        }
        return JSON.toJSONString(comboNodes);
    }

    @Override
    public String getTreeGridByHQLNamedQuery(final Object searchModel, final TreeGridConfig treeGridConfig)
            throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("通过HQL获得treeGrid数据.");
        }
        JSONArray treeGridNodes = new JSONArray();
        List<?> treeGridDataList = queryDAO.queryByHQLNamedQuery(treeGridConfig.getNamedQueryId(), searchModel);
        for (Object treeGridRow : treeGridDataList) {
            JSONObject treeGridNode = JsonUtils.entity2JSONObject(treeGridRow, 1);
            String parentId = BeanUtilsEx.getProperty(treeGridNode, treeGridConfig.getParentPropertyName());
            if (!StringUtils.isEmpty(parentId)) {
                treeGridNode.put(CommonConstants.DATA_GRID_PARENT_FLAG, parentId);
            }
            treeGridNodes.add(treeGridNode);
        }
        JSONObject treeGridObj = new JSONObject();
        treeGridObj.put(CommonConstants.TOTAL, treeGridNodes.size());
        treeGridObj.put(CommonConstants.ROWS, treeGridNodes);
        return JSON.toJSONString(treeGridObj);
    }

    @Override
    public String getTreeGridBySQLNamedQuery(final Object searchModel, final TreeGridConfig treeGridConfig)
            throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("通过SQL获得treeGrid数据.");
        }
        JSONArray treeGridNodes = new JSONArray();
        List<Map<String, Object>> treeGridDataList = queryDAO.queryBySQLNamedQuery(treeGridConfig.getNamedQueryId(),
                searchModel);
        for (int i = 0; i < treeGridDataList.size(); i++) {
            Map<String, Object> treeGridRow = treeGridDataList.get(i);
            JSONObject treeGridNode = new JSONObject();
            treeGridNode.putAll(JSONObject.parseObject(JSON.toJSONString(treeGridRow)));
            Object parentId = treeGridRow.get(treeGridConfig.getParentPropertyName());
            if (parentId != null && !parentId.equals("")) {
                treeGridNode.put(CommonConstants.DATA_GRID_PARENT_FLAG, parentId);
            }
            treeGridNodes.add(treeGridNode);
        }
        JSONObject treeGridObj = new JSONObject();
        treeGridObj.put(CommonConstants.TOTAL, treeGridNodes.size());
        treeGridObj.put(CommonConstants.ROWS, treeGridNodes);
        return JSON.toJSONString(treeGridObj);
    }

    @Override
    public String getFormBySQLNamedQuery(final String namedQuery, final Object searchModel, final Class<?> customerDTO)
            throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("----------HQL命名分页查询执行----------");
        }
        List<?> result = queryDAO.queryBySQLNamedQuery(namedQuery, searchModel, customerDTO);
        if (result != null && !result.isEmpty()) {
            return AgileUiDataUtils.getDataForAgileForm(result.get(0));
        }
        return null;
    }

    @Override
    public String getFormBySQLNamedQuery(final String namedQuery, final Object searchModel) throws Exception {
        String returnResult = null;
        List<?> result = queryDAO.queryBySQLNamedQuery(namedQuery, searchModel);
        if (result != null && !result.isEmpty()) {
            returnResult = AgileUiDataUtils.getDataForAgileForm(result.get(0));
        }
        if (logger.isDebugEnabled()) {
            logger.debug("----------getFormBySQLNamedQuery返回结果：");
            logger.debug(returnResult);
        }
        return returnResult;
    }

    @Override
    public String getFormByHQLNamedQuery(final String namedQuery, final Object searchModel) throws Exception {
        return null;
    }

    @Override
    public String getNormalDataBySQLNamedQuery(final String namedQuery, final Object searchModel,
            final Class<?> customerDTO) throws Exception {
        String returnResult = null;
        List<?> result = queryDAO.queryBySQLNamedQuery(namedQuery, searchModel, customerDTO);
        if (result != null && !result.isEmpty()) {
            returnResult = AgileUiDataUtils.getNormalData(result);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("----------getFormBySQLNamedQuery返回结果：");
            logger.debug(returnResult);
        }
        return null;
    }

    @Override
    public String getNormalDataBySQLNamedQuery(final String namedQuery, final Object searchModel) throws Exception {
        String returnResult = null;
        List<?> result = queryDAO.queryBySQLNamedQuery(namedQuery, searchModel);
        if (result != null && !result.isEmpty()) {
            returnResult = AgileUiDataUtils.getNormalData(result);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("----------getFormBySQLNamedQuery返回结果：");
            logger.debug(returnResult);
        }
        return returnResult;
    }

    @Override
    public void executeDynamicSql(final String namedQuery, final Object parametersModel) throws Exception {
        SQLQuery sqlQuery = queryDAO.getSQLQueryByNamed(namedQuery, parametersModel);
        sqlQuery.setProperties(parametersModel);
        sqlQuery.executeUpdate();
    }

    @Override
    public JSONObject successMsg(final String msgKey) throws Exception {
        return MessageUtils.addSuccessMsg(msgKey);
    }

    @Override
    public JSONObject successMsg(final String msgKey, final Object msgParams) throws Exception {
        return MessageUtils.addSuccessMsg(msgKey, msgParams);
    }

    @Override
    public JSONObject errorMsg(final String msgKey) throws Exception {
        return MessageUtils.addErrorMsg(msgKey);
    }

    @Override
    public JSONObject normalMsg(final String bsKey, final String msgKey) throws Exception {
        return MessageUtils.addMsg(bsKey, msgKey);
    }
}
