package com.reyun.service.impl;

import com.reyun.model.*;
import com.reyun.repository.*;
import com.reyun.service.*;
import com.reyun.util.ResultModel;
import com.reyun.util.ResultStatus;
import com.reyun.util.ValidateUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sunhao on 17/4/21.
 * desc:看单service
 */
@Service
public class CustomMenuServiceImpl implements CustomMenuService {

    @Autowired
    private CustomMenuRepository customMenuRepository;
    @Autowired
    private CustomMenuShareRepository customMenuShareRepository;
    @Autowired
    private CustomMenuTemplateRepository customMenuTemplateRepository;
    @Autowired
    private CustomMenuFavoritesRepository customMenuFavoritesRepository;
    @Autowired
    private CustomMenuShareTempRepository customMenuShareTempRepository;
    @Autowired
    private AppRepository appRepository;
    @Autowired
    private CategoryRepository categoryRepository;
    @Autowired
    private FunnelRepository funnelRepository;
    @Autowired
    private EventStatsRepository eventStatsRepository;
    @Autowired
    private RetentionRepository retentionRepository;
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private EventService eventService;
    @Autowired
    private ConfigParamService configParamService;
    @Autowired
    private EventStatsService eventStatsService;
    @Autowired
    private FunnelService funnelService;
    @Autowired
    private RetentionService retentionService;
    @Autowired
    private ComplicateEventsService complicateEventsService;

    private final static String CUSTOM_MENU_NUMBER = "custom_menu_number";

    private final static String CUSTOM_TEMPLATE_NUMBER = "custom_template_number";
    //事件分析,漏斗,留存
    private final static String TEMPLATE_TYPE_EVENT = "eventstats";
    private final static String TEMPLATE_TYPE_FUNNEL = "funnel";
    private final static String TEMPLATE_TYPE_RETENTION = "retention";
    private final static String TEMPLATE_NAME_PREFIX = "分享_";

    private final static double MATCH_PERCENT_ZERO = 0.00D;
    private final static double MATCH_PERCENT_ONE = 1.00D;

    private final static String VIEW_TYPE_DAY = "day";
    private final static String VIEW_TYPE_WEEK = "week";
    private final static int RETENTION_VIEW_WEEK_DAYS = 14;

    /**
     * 列出所有的行业看单模板(即所有人分享列表)
     * created by sunhao 20170424
     */
    @Override
    public List<CustomMenuShare> listAllSharedMenuByCategory(Long accountId, Long appId) {

        List<CustomMenuShare> customMenuShareList = new ArrayList<>();

        App app = appRepository.findOne(appId);

        if (null != app) {

            Long appCategory = Long.parseLong(app.getAppGenre());
            //列出所有分享看单,非以下类型取其他
            if (!appCategory.equals(39L) && !appCategory.equals(29L) && !appCategory.equals(17L)) {
                appCategory = 8L;
            }
            customMenuShareList = customMenuShareRepository.listAllShared();

            for (CustomMenuShare customMenuShare : customMenuShareList) {

                //看单模板
                customMenuShare.setTemplates(customMenuShareTempRepository.findShareTemplateById(customMenuShare.getId()));

                //计算匹配度
                if (accountId.equals(customMenuShare.getAccountId())) {
                    //自己分享的看单匹配度100%
                    //customMenuShare.setMatchPercent(MATCH_PERCENT_ONE);
                    customMenuShare.setHasFavorite(false);
                    customMenuShare.setHasUsed(false);
                } else {
                    //customMenuShare.setMatchPercent(this.calculateMatchPercent(customMenuShare.getTemplates(), app.getId()));
                    //是否收藏或已加入看单
                    customMenuShare.setHasFavorite(null != customMenuFavoritesRepository.findFavoriteMenuByShareId(app.getAccount(),
                            app.getId(), customMenuShare.getId()));
                    customMenuShare.setHasUsed(null != customMenuRepository.findCustomMenuByShareId(app.getAccount(), app.getId(),
                            customMenuShare.getId()));
                }
            }
        }

        return customMenuShareList;
    }

    /**
     * 计算匹配度
     * 看单匹配率[n个模板,模板匹配率P],计算公式((P1+P2+...+Pn)/n)*100%
     * 单个模板匹配率[i个事件,j个属性,事件匹配E(0,1),属性匹配个数A],计算公式:P= (E1(1+A1)+E2(1+A2)+...+Ei(1+Ai))/(i+j)
     * created by sunhao 20170424
     */
    private Double calculateMatchPercent(List<CustomMenuShareTemplate> customMenuShareTemplateList, Long appId) {

        Double resultPercent = MATCH_PERCENT_ZERO;

        //获取用户的所有事件和属性
        Map<String, List<String>> eventAttrMap = eventService.findAllEventWithAttr(appId);

        if (CollectionUtils.isEmpty(eventAttrMap)) {
            eventAttrMap = new HashMap<>();
        }

        //分别计算模板的匹配率求和
        for (CustomMenuShareTemplate customMenuShareTemplate : customMenuShareTemplateList) {

            Double tempMatch = MATCH_PERCENT_ZERO;

            switch (customMenuShareTemplate.getMenuType()) {

                case TEMPLATE_TYPE_EVENT:
                    //计算事件分析匹配度
                    tempMatch = this.eventStatsMatchPercent(customMenuShareTemplate, eventAttrMap);
                    resultPercent += tempMatch;
                    break;
                case TEMPLATE_TYPE_FUNNEL:
                case TEMPLATE_TYPE_RETENTION:
                    //计算漏斗留存匹配度
                    tempMatch = this.funnelAndRetentionMatchPercent(customMenuShareTemplate, eventAttrMap);
                    resultPercent += tempMatch;
                    break;
            }

            customMenuShareTemplate.setHasMatch(tempMatch.equals(MATCH_PERCENT_ONE));
        }

        //模板匹配率平均值
        resultPercent = resultPercent / customMenuShareTemplateList.size();

        return resultPercent;
    }


    /**
     * 计算事件分析匹配度
     * 单个事件,N(N>=0)个属性
     * <p>
     * eventStats:{"event":"install","relation":"and","params":[{"attr":"_country","type":"string","value":"中国","operator":"="}],
     * "viewField":"_count","fieldOperate":""}
     * <p>
     * created by sunhao 20170424
     */
    private Double eventStatsMatchPercent(CustomMenuShareTemplate customMenuShareTemplate, Map<String, List<String>> eventAttrMap) {

        Double result;

        //模板事件
        JSONObject conditionJson = JSONObject.fromObject(customMenuShareTemplate.getQueryCondition());

        //用户自己事件
        String eventName = conditionJson.getString("event");
        List<String> attrList = eventAttrMap.get(eventName);

        //匹配显示属性
        if (!StringUtils.isEmpty(conditionJson.getString("fieldOperate"))) {

            JSONArray paramJsonArray = conditionJson.getJSONArray("params");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("attr", conditionJson.getString("viewField"));
            paramJsonArray.add(jsonObject);
        }

        //获取匹配度
        result = this.getOneEventMatchPercent(conditionJson, attrList);

        //设置查询条件
        customMenuShareTemplate.setQueryCondition(conditionJson.toString());

        return result;
    }

    /**
     * 计算漏斗和留存匹配度
     * M(M>2)个事件,N(N>=0)个属性
     * <p>
     * funnel:[{"event":"where","relation":"or","params":[{"attr":"city","type":"string","value":"北京,上海","operator":"in"},{"attr":"province","type":"string","value":"北京","operator":"="}]},
     * {"event":"net","relation":"and","params":[{"operator":"=","value":"移动","attr":"carrier","type":"string"}]}]
     * <p>
     * retention:[{"event":"install","relation":"and","params":[{"operator":"=","value":"爱奇艺","attr":"_campaignid","type":"string"}]},
     * {"event":"payment","relation":"and","params":[]}]
     * <p>
     * created by sunhao 20170424
     */
    private Double funnelAndRetentionMatchPercent(CustomMenuShareTemplate customMenuShareTemplate, Map<String, List<String>> eventAttrMap) {

        Double result = MATCH_PERCENT_ZERO;

        JSONArray eventArray = JSONArray.fromObject(customMenuShareTemplate.getQueryCondition());

        for (int i = 0; i < eventArray.size(); i++) {

            //模板事件
            JSONObject eventObject = eventArray.getJSONObject(i);

            //用户自己事件
            String eventName = eventObject.getString("event");
            List<String> attrList = eventAttrMap.get(eventName);

            //获取匹配度和
            result += this.getOneEventMatchPercent(eventObject, attrList);
        }

        //更新后的查询条件
        customMenuShareTemplate.setQueryCondition(eventArray.toString());

        return result / eventArray.size();
    }

    /**
     * 获取单个事件的匹配度
     * created by sunhao 20170424
     */
    private Double getOneEventMatchPercent(JSONObject eventJsonObject, List<String> attrList) {

        Double result = MATCH_PERCENT_ZERO;

        JSONArray paramJsonArray = eventJsonObject.getJSONArray("params");

        //事件匹配,事件若没匹配,无需继续匹配属性,整个匹配度为0
        if (!CollectionUtils.isEmpty(attrList)) {

            //只有事件匹配没有属性,则100%
            if (!CollectionUtils.isEmpty(paramJsonArray)) {

                double attrMatch = MATCH_PERCENT_ZERO;
                //属性匹配
                for (int j = 0; j < paramJsonArray.size(); j++) {

                    JSONObject attrObject = paramJsonArray.getJSONObject(j);

                    if (attrList.contains(attrObject.getString("attr"))) {
                        attrMatch++;
                        attrObject.put("attrMatch", true);
                    } else {
                        attrObject.put("attrMatch", false);
                    }
                }

                result = attrMatch / paramJsonArray.size();

            } else {

                result = MATCH_PERCENT_ONE;
            }

            eventJsonObject.put("eventMatch", true);

        } else {

            eventJsonObject.put("eventMatch", false);
        }

        eventJsonObject.put("params", paramJsonArray);

        return result;
    }


    /**
     * 查询我的看单
     * created by sunhao 20170424
     */
    @Override
    public List<CustomMenu> listMyCustomMenu(Long accountId, Long appId) {

        //查询看单
        List<CustomMenu> customMenuList = customMenuRepository.findValidCustomMenuByApp(appId);

        for (CustomMenu customMenu : customMenuList) {

            //查询我的看单模板
            customMenu.setTemplates(customMenuTemplateRepository.findMyTemplateById(customMenu.getId()));
        }

        return customMenuList;
    }


    /**
     * 查询我的收藏夹
     * created by sunhao 20170424
     */
    @Override
    public List<CustomMenuShare> listMyFavorite(Long accountId, Long appId) {

        List<CustomMenuShare> customMenuShareList = new ArrayList<>();

        List<CustomMenuFavorites> customMenuFavoriteList = customMenuFavoritesRepository.findAllFavorites(accountId, appId);

        for (CustomMenuFavorites customMenuFavorites : customMenuFavoriteList) {

            CustomMenuShare customMenuShare = customMenuShareRepository.findShareById(customMenuFavorites.getShareId());

            //设置ID
            customMenuShare.setId(customMenuFavorites.getId());
            //shareId
            customMenuShare.setShareId(customMenuFavorites.getShareId());
            //分享是否有效
            customMenuShare.setShareValid(customMenuFavorites.getShareValid());
            //是否收藏
            customMenuShare.setHasFavorite(true);
            //是否使用
            customMenuShare.setHasUsed(customMenuRepository.findByShareId(appId, customMenuFavorites.getShareId()).intValue() > 0);
            //填充匹配度
            customMenuShare.setMatchPercent(customMenuFavorites.getMatchPercent());
            //填充分析看单的模板
            List<CustomMenuShareTemplate> customMenuShareTemplateList = customMenuShareTempRepository.findShareTemplateById(customMenuFavorites.getShareId());
            //匹配填充
            this.calculateMatchPercent(customMenuShareTemplateList, appId);
            customMenuShare.setTemplates(customMenuShareTemplateList);

            customMenuShareList.add(customMenuShare);
        }

        return customMenuShareList;
    }

    /**
     * 创建自己的看单
     * created by sunhao 20170425
     */
    @Override
    public CustomMenu createMyMenu(Long accountId, Long appId, String name) {

        CustomMenu customMenuSave = new CustomMenu();

        Account account = accountRepository.findOne(accountId);

        if (null != account) {

            //保存主表
            App app = appRepository.findOne(appId);

            //创建者名字,名字->公司->email(需要?)
            String accountName = StringUtils.isEmpty(account.getName()) ? account.getCompany() : account.getName();
            accountName = StringUtils.isEmpty(accountName) ? account.getEmail() : accountName;
            customMenuSave.setCreateAccountName(accountName);
            customMenuSave.setCategory(Long.parseLong(app.getAppGenre()));
            customMenuSave.setCategoryName(categoryRepository.findNameByCategoryId(Long.parseLong(app.getAppGenre())));
            customMenuSave.setCreateAccount(account.getId());
            customMenuSave.setCreateDate(new Date());
            customMenuSave.setAppId(appId);
            customMenuSave.setHasShare(false);
            customMenuSave.setSource(false);
            customMenuSave.setDelFlag(false);
            customMenuSave.setName(name);

            //保存CustomMenu
            customMenuSave = customMenuRepository.save(customMenuSave);
            List<CustomMenu> menuList = customMenuRepository.findValidCustomMenuByApp(appId);
//            List<CustomMenu> list = new ArrayList<>();
//            if(ValidateUtil.isValid(menuList)){
//                for(CustomMenu c : menuList){
//                    c.setOrderindex(c.getOrderindex() + 1);
//                    list.add(c);
//                }
//            }
            //list.add(customMenuSave);
            customMenuSave.setOrderindex(menuList.size());
            customMenuSave = customMenuRepository.save(customMenuSave);
        }
        return customMenuSave;
    }

    /**
     * 添加模板到我的看单
     * created by sunhao 20170426
     */
    @Override
    public CustomMenuTemplate addCustomMenuTemplate(Account account, Long appId, Long menuId, CustomMenuTemplate customMenuTemplate) {

        //构建模板
        customMenuTemplate.setAccountId(account.getId());
        customMenuTemplate.setModifyAccount(account.getId());
        customMenuTemplate.setCreateDate(new Date());
        customMenuTemplate.setModifyDate(new Date());
        customMenuTemplate.setCustomMenuId(menuId);
        customMenuTemplate.setDelFlag(false);

        //填充condition,sql
        customMenuTemplate = this.fillTemplateInfo(customMenuTemplate);

        if (null != customMenuTemplate.getOriginalReportId()) {
            CustomMenuTemplate save = customMenuTemplateRepository.save(customMenuTemplate);
            List<CustomMenuTemplate> list = customMenuTemplateRepository.findMyTemplateById(customMenuTemplate.getCustomMenuId());

            save.setOrderindex(list.size());
//            List<CustomMenuTemplate> listNew = new ArrayList<>();
//            if(ValidateUtil.isValid(list)){
//                for(CustomMenuTemplate c : list){
//                    c.setOrderindex(c.getOrderindex() + 1);
//                    listNew.add(c);
//                }
//            }
//            listNew.add(save);
            save = customMenuTemplateRepository.save(save);
            return save;
        }

        return null;
    }

    /**
     * 填充模板的条件和SQL
     */
    private CustomMenuTemplate fillTemplateInfo(CustomMenuTemplate customMenuTemplate) {

        switch (customMenuTemplate.getMenuType()) {

            case TEMPLATE_TYPE_EVENT:

                EventStats eventStats = eventStatsRepository.findEventStats(customMenuTemplate.getOriginalReportId());
                if (null != eventStats) {
                    customMenuTemplate.setName(eventStats.getName());
                    customMenuTemplate.setOriginalReportId(eventStats.getId());
                }
                break;

            case TEMPLATE_TYPE_FUNNEL:

                Funnel funnel = funnelRepository.findOne(customMenuTemplate.getOriginalReportId());
                if (null != funnel) {
                    customMenuTemplate.setName(funnel.getName());
                    customMenuTemplate.setOriginalReportId(funnel.getId());
                }
                break;

            case TEMPLATE_TYPE_RETENTION:

                Retention retention = retentionRepository.findOne(customMenuTemplate.getOriginalReportId());
                if (null != retention) {
                    customMenuTemplate.setName(retention.getName());
                    customMenuTemplate.setOriginalReportId(retention.getId());
                }
                break;
        }

        return customMenuTemplate;
    }

    /**
     * 删除我的看单
     * created by sunhao 20170424
     */
    @Override
    public boolean deleteMyMenu(Long accountId, Long appId, Long menuId) {

        boolean result = false;

        int affectNum = customMenuRepository.deleteMyMenu(accountId, appId, menuId);
        //此看单后面的看单顺序依次提前
        CustomMenu one = customMenuRepository.findOne(menuId);
        List<CustomMenu> customMenuList = customMenuRepository.findValidCustomMenuByApp(appId);
        List<CustomMenu> list = new ArrayList<>();
        if(ValidateUtil.isValid(customMenuList)){
            for(CustomMenu cu : customMenuList){
                if(cu.getOrderindex() > one.getOrderindex()){
                    cu.setOrderindex(cu.getOrderindex() - 1);
                    list.add(cu);
                }
            }
        }
        if(list.size() > 0){
            customMenuRepository.save(list);
        }

        if (affectNum > 0) {

            CustomMenu customMenu = one;

            if (customMenu.getSource()) {
                //是来自分享,更新使用数量
                customMenuShareRepository.minusUserNumber(customMenu.getShareId());
                result = true;

            } else {
                //是否分享,分享调用取消分享。
                CustomMenuShare customShare = customMenuShareRepository.findShareByOriginalMenu(menuId);
                if (null != customShare) {
                    result = this.cancelShareMyMenu(accountId, appId, menuId);
                }
            }
        }

        return result;
    }

    /**
     * 从分享添加到我的看单
     */
    @Override
    public List<CustomMenuTemplate> addToMyMenu(Account account, Long appId, CustomMenuShare customMenuShare) {

        List<CustomMenuTemplate> customMenuTemplateList = new ArrayList<>();

        //根据条件生成相应的报表模板
        CustomMenuShare customShare = customMenuShareRepository.findShareById(customMenuShare.getId());

        if (null != customShare && !customShare.getDelFlag()) {

            //看单名字重复处理,后缀加上_1
            int nameNumber = customMenuRepository.findNameLikeNumber(appId, customShare.getName()).intValue();
            String name = nameNumber > 0 ? customMenuShare.getName() + "_" + (nameNumber + 1) : customMenuShare.getName();
            //添加到我的看单
            CustomMenu saveMenu = new CustomMenu();
            saveMenu.setCategoryName(customShare.getCategoryName());
            saveMenu.setCategory(customShare.getCategory());
            saveMenu.setAppId(appId);
            saveMenu.setName(name);
            saveMenu.setCreateAccount(account.getId());
            saveMenu.setCreateAccountName(account.getName());
            saveMenu.setCreateDate(new Date());
            saveMenu.setShareId(customShare.getId());
            saveMenu.setShareAccountId(customShare.getAccountId());
            saveMenu.setShareAccountName(customShare.getAccountName());
            saveMenu.setShareDate(customShare.getShareDate());
            saveMenu.setHasShare(true);
            saveMenu.setSource(true);
            saveMenu.setDelFlag(false);
            //保存
            saveMenu = customMenuRepository.save(saveMenu);

            //添加相应的模板,生成SQL等
            customMenuTemplateList = this.createReportStatsFromTemplate(customMenuShare.getTemplates(),
                    account, appId, saveMenu.getId());

            //保存模板
            customMenuTemplateList = customMenuTemplateRepository.save(customMenuTemplateList);

            //更新使用人数
            customMenuShareRepository.addUserNumber(customMenuShare.getId());

        }

        return customMenuTemplateList;
    }


    /**
     * 根据模板自动创建事件,漏斗,留存
     * created by sunhao 20170426
     */
    private List<CustomMenuTemplate> createReportStatsFromTemplate(List<CustomMenuShareTemplate> customMenuShareTemplateList,
                                                                   Account account, Long appId, Long menuId) {

        List<CustomMenuTemplate> resultList = new ArrayList<>();

        for (CustomMenuShareTemplate customMenuShareTemplate : customMenuShareTemplateList) {

            Date createDate = new Date();
            int nameNumber;

            StringBuilder nameString = new StringBuilder();
            CustomMenuTemplate template = new CustomMenuTemplate(customMenuShareTemplate);

            template.setCustomMenuId(menuId);
            template.setCreateDate(new Date());
            template.setAccountId(account.getId());
            template.setModifyAccount(account.getId());
            template.setDelFlag(false);
            //来自分享的模板名字加前缀
            nameString.append(TEMPLATE_NAME_PREFIX).append(template.getName());

            switch (template.getMenuType()) {

                case TEMPLATE_TYPE_EVENT:
                    //相同名字后面数字自增
                    nameNumber = eventStatsRepository.findCountLikeName(account.getId(), appId, nameString.toString()).intValue();
                    if (nameNumber > 0) {
                        nameString.append("_").append(nameNumber + 1);
                    }

                    EventStats eventStats = new EventStats();
                    eventStats.setName(nameString.toString());
                    eventStats.setApp(appId);
                    eventStats.setEventCondition(customMenuShareTemplate.getQueryCondition());
                    eventStats.setCreateAccount(account.getId());
                    eventStats.setCreateTime(createDate);
                    eventStats.setModifyTime(createDate);
                    eventStats.setModifyAccount(account.getId());
                    eventStats.setValid(true);
                    eventStats = eventStatsService.createEventStats(eventStats);

                    if (null != eventStats) {
                        template.setOriginalReportId(eventStats.getId());
                        template.setName(nameString.toString());
                    }

                    break;

                case TEMPLATE_TYPE_FUNNEL:
                    //相同名字后面数字自增
                    nameNumber = funnelRepository.findCountLikeName(account.getId(), appId, nameString.toString()).intValue();
                    if (nameNumber > 0) {
                        nameString.append("_").append(nameNumber + 1);
                    }
                    Funnel funnel = new Funnel();
                    funnel.setName(nameString.toString());
                    funnel.setApp(appId);
                    funnel.setEventInfo(customMenuShareTemplate.getQueryCondition());
                    funnel.setEvents(customMenuShareTemplate.getEvents());
                    funnel.setCreateAccount(account.getId());
                    funnel.setCreateTime(createDate);
                    funnel.setModifyTime(createDate);
                    funnel.setWindow(1);
                    funnel = funnelService.create(funnel, account.getId());

                    if (null != funnel) {
                        template.setOriginalReportId(funnel.getId());
                        template.setName(nameString.toString());
                    }
                    break;

                case TEMPLATE_TYPE_RETENTION:
                    //相同名字后面数字自增
                    nameNumber = retentionRepository.findCountLikeName(account.getId(), appId, nameString.toString()).intValue();
                    if (nameNumber > 0) {
                        nameString.append("_").append(nameNumber + 1);
                    }
                    Retention retention = new Retention();
                    retention.setName(nameString.toString());
                    retention.setApp(appId);
                    retention.setEventInfo(customMenuShareTemplate.getQueryCondition());
                    retention.setRelativeTime(customMenuShareTemplate.getRelativeTime());
                    retention.setAccount(account.getId());
                    retention.setCreateTime(createDate);
                    retention.setModifyTime(createDate);
                    retention = retentionService.create(retention, account.getId());
                    if (null != retention) {
                        template.setOriginalReportId(retention.getId());
                        template.setName(nameString.toString());
                    }
                    break;

                default:
                    break;
            }

            //加入返回值
            if (null != template.getOriginalReportId()) {
                resultList.add(template);
            }
        }

        return resultList;
    }

    /**
     * 添加到收藏夹
     * created by sunhao 20170424
     */
    @Override
    public boolean addToFavorite(Long accountId, Long appId, Long menuId) {

        boolean result = false;

        //查询是否收藏过
        CustomMenuFavorites usedCustomMenuFavorites = customMenuFavoritesRepository.findHasAddToFavorite(accountId, appId, menuId);

        if (null != usedCustomMenuFavorites) {

            //收藏过直接更新
            int affectNum = customMenuFavoritesRepository.restoreFavorites(accountId, appId, menuId);

            if (affectNum > 0) {
                result = customMenuShareRepository.addFavoriteNumber(menuId) > 0;
            }

        } else {
            //未收藏过插入新记录
            CustomMenuShare customMenuShare = customMenuShareRepository.findShareById(menuId);
            if (null != customMenuShare && !customMenuShare.getDelFlag()) {
                //查询模板
                List<CustomMenuShareTemplate> customMenuShareTemplateList = customMenuShareTempRepository.findShareTemplateById(customMenuShare.getId());
                //计算匹配度
                Double matchPercent = this.calculateMatchPercent(customMenuShareTemplateList, appId);
                //保存收藏夹
                CustomMenuFavorites saveResult = customMenuFavoritesRepository.save(new CustomMenuFavorites(accountId, appId, customMenuShare.getId(), matchPercent));

                //更新收藏数量
                if (null != saveResult) {

                    customMenuShareRepository.addFavoriteNumber(customMenuShare.getId());
                    result = true;
                }
            }
        }

        return result;
    }

    /**
     * 删除收藏夹
     * created by sunhao 20170424
     */
    @Override
    public boolean deleteFavorite(Long accountId, Long appId, Long menuId) {

        boolean result = false;

        int affectNum = customMenuFavoritesRepository.deleteFavorites(accountId, appId, menuId);

        //更新收藏数量
        if (affectNum > 0) {

            customMenuShareRepository.minusFavoriteNumber(menuId);
            result = true;
        }

        return result;
    }

    /**
     * 校验我的看单的个数
     * created by sunhao 20170425
     */
    @Override
    public boolean validMyMenuNumber(Long accountId, Long appId) {

        //用户所有看单
        BigInteger menuNumber = customMenuRepository.findMyMenuNumber(appId);
        //限制看单数
        String number = configParamService.getConfigParamByKey(CUSTOM_MENU_NUMBER);

        return menuNumber.intValue() < Integer.parseInt(number);
    }

    /**
     * 校验看单名称
     */
    @Override
    public boolean validMyMenuName(Long appId, String menuName) {

        BigInteger menuNumber = customMenuRepository.findMyMenuNumberByName(appId, menuName);
        return menuNumber.intValue() == 0;
    }


    /**
     * 将热云看单添加到我的看单
     * created by sunhao 20170426
     */
    public List<CustomMenuTemplate> addReyunToMyMenu(Account account, Long appId) {

        List<CustomMenuTemplate> templateList = new ArrayList<>();

        App app = appRepository.findOne(appId);

        Long appCategory = Long.parseLong(app.getAppGenre());
//        Long appCategory = 8L;
        //如果APP类型不是以下四类,默认添加基础类型看单
        if (!appCategory.equals(17L) && !appCategory.equals(29L) && !appCategory.equals(39L) && !appCategory.equals(8L)) {
            appCategory = 8L;
        }

        List<CustomMenuShare> customMenuShareList = customMenuShareRepository.findReyunMenu(appCategory);

        for (CustomMenuShare customMenuShare : customMenuShareList) {

            List<CustomMenuShareTemplate> customMenuTemplateList = customMenuShareTempRepository.findShareTemplateById(customMenuShare.getId());

            customMenuShare.setTemplates(customMenuTemplateList);

            templateList = this.addToMyMenu(account, appId, customMenuShare);
        }

        return templateList;
    }

    @Override
    public boolean cancelShareMyMenu(Long accountId, Long appId, Long menuId) {

        CustomMenuShare customMenuShare = customMenuShareRepository.findShareByOriginalMenu(menuId);

        if (null != customMenuShare) {

            //删除分享
            int affectNum = customMenuShareRepository.deleteShareMenu(customMenuShare.getId());

            if (affectNum > 0) {

                //取消我的看单中的分享状态
                customMenuRepository.updateMyMenuShare(customMenuShare.getOriginalMenu(), false);
                //取消分享,所有收藏此看单的变成无效
                customMenuFavoritesRepository.updateFavoritesShareInvalid(customMenuShare.getId());

                return true;
            }
        }

        return false;
    }

    /**
     * 查询我的看单和我的收藏是否为空
     * created by sunhao 20170426
     */
    @Override
    public boolean findAllMenuAndFavorite(Long accountId, Long appId) {

        //查询所有的看单,包括失效的。
        List<CustomMenu> customMenuList = customMenuRepository.findAllCustomMenuByApp(appId);

        List<CustomMenuFavorites> customMenuFavoritesList = customMenuFavoritesRepository.findAllFavorites(accountId, appId);

        return !(CollectionUtils.isEmpty(customMenuList) && CollectionUtils.isEmpty(customMenuFavoritesList));

    }


    /**
     * 校验看单内模板是否存在和模板数量是否超标
     * created by sunhao 20170426
     */
    @Override
    public ResultModel validMenuTemplate(Long accountId, Long menuId, Long templateId, String menuType) {

        //查询是否添加过此模板
        CustomMenuTemplate template = customMenuTemplateRepository.findMyTemplateByReportId(menuId, templateId, menuType);

        if (null == template) {
            //用户看单的所有模板
            BigInteger tempNumber = customMenuTemplateRepository.countNumberByMenu(menuId);
            //限制模板数
            String number = configParamService.getConfigParamByKey(CUSTOM_TEMPLATE_NUMBER);

            if (tempNumber.intValue() >= Integer.parseInt(number)) {
                return ResultModel.ERROR(ResultStatus.NUMBER_LIMIT);
            }

        } else {
            return ResultModel.ERROR(ResultStatus.RECORD_EXIST);
        }

        return ResultModel.OK();
    }

    /**
     * 修改看单名字
     * created by sunhao 20170426
     */
    @Override
    public boolean updateMyMenuName(Long accountId, Long menuId, String name) {

        int affectNum = customMenuRepository.updateMyMenuName(accountId, menuId, name, new Date());

        return affectNum > 0;
    }


    /**
     * 删除模板
     */
    @Override
    public boolean deleteMyMenuTemplate(Long accountId, Long templateId) {

        int affectNum = customMenuTemplateRepository.updateTemplateInvalid(accountId, templateId);
        CustomMenuTemplate one = customMenuTemplateRepository.findOne(templateId);
        List<CustomMenuTemplate> customMenuTemplateList = customMenuTemplateRepository.findMyTemplateById(one.getCustomMenuId());
        List<CustomMenuTemplate> list = new ArrayList<>();
        if(ValidateUtil.isValid(customMenuTemplateList)){
            for(CustomMenuTemplate cu : customMenuTemplateList){
                if(cu.getOrderindex() > one.getOrderindex()){
                    cu.setOrderindex(cu.getOrderindex() - 1);
                    list.add(cu);
                }
            }
        }
        if(list.size() > 0){
            customMenuTemplateRepository.save(list);
        }
        return affectNum > 0;
    }


    @Override
    public Map<String, List> queryAllReport(Long accountId, Long appId, Long originalReportId, String menuType, String startDate, String endDate, String viewFlag) {

        Map<String, List> resultData = new HashMap<>();

        String dimension = "";
//        String viewFlag = VIEW_TYPE_DAY;

        switch (menuType) {

            case TEMPLATE_TYPE_EVENT:

                EventStats eventStats = eventStatsRepository.findOne(originalReportId);

                if (null != eventStats) {
                    resultData = complicateEventsService.queryComplicatedEvent(appId, accountId, startDate, endDate,
                            eventStats.getEventCondition(), viewFlag);
                }
                break;

            case TEMPLATE_TYPE_FUNNEL:

                Funnel funnel = funnelRepository.findOne(originalReportId);

                if (null != funnel) {

                    resultData = funnelService.funnelDataQuery(startDate, endDate, funnel.getEventInfo(), funnel.getEvents(), 1, appId, false);
                }
                break;

            case TEMPLATE_TYPE_RETENTION:

//                try {
//                    //留存超过14天之后按照周显示
//                    viewFlag = DateUtil.daysBetween(startDate, endDate) + 1 > RETENTION_VIEW_WEEK_DAYS ? VIEW_TYPE_WEEK : viewFlag;
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }

                Retention retention = retentionRepository.findOne(originalReportId);

                if (null != retention) {
                    resultData = retentionService.retentionReport(startDate, endDate, false, retention.getEventInfo(),
                            appId, null, "-all", viewFlag, 7, false, accountId,null,false);
                }
                break;
        }

        return resultData;
    }


    /**
     * 查询所有看单简单数据
     * created by sunhao 20170428
     */
    @Override
    public List<CustomMenu> listMyMenuList(Long accountId, Long appId) {

        return customMenuRepository.findValidCustomMenuByApp(appId);
    }


    /**
     * 查询我的看单详情
     * created by sunhao 20170428
     */
    @Override
    public CustomMenu getMyMenuDetail(Long menuId) {

        CustomMenu customMenu = customMenuRepository.findOne(menuId);

        if (null != customMenu) {
            //查询我的看单模板
            customMenu.setTemplates(customMenuTemplateRepository.findMyTemplateById(customMenu.getId()));
        }

        return customMenu;
    }

    /**
     * 更新我的看单和分享看单的账户名称
     */
    @Override
    public int updateMenuAccountName(Long accountId, String accountName) {

        //修改创建者名字
        int numCreate = customMenuRepository.updateAccountName(accountId, accountName);
        //修改分享者名字
        int numShare = customMenuRepository.updateShareAccountName(accountId, accountName);
        //修改行业看单分享名字
        int numMyShare = customMenuShareRepository.updateAccountName(accountId, accountName);

        return numCreate + numShare + numMyShare;
    }

    /**
     * 修改看单顺序
     */
    @Override
    public boolean updateMyMenuIndex(Long accountId, Long appid, Long menuId, int index) {
        List<CustomMenu> customMenuList = customMenuRepository.findValidCustomMenuByApp(appid);
        CustomMenu customMenu = customMenuRepository.findOne(menuId);
        List<CustomMenu> list = new ArrayList<>();
        //看单前移
        if(customMenu.getOrderindex() > index){
            for(CustomMenu cu : customMenuList){
                if((cu.getOrderindex() > index || cu.getOrderindex() == index) && cu.getOrderindex() < customMenu.getOrderindex()){
                    cu.setOrderindex(cu.getOrderindex() + 1);
                    cu.setModifyAccount(accountId);
                    cu.setModifyDate(new Date());
                    list.add(cu);
                }
            }
        }//看单后移
        else if(customMenu.getOrderindex() > index){
            for(CustomMenu cu : customMenuList){
                if((cu.getOrderindex() < index || cu.getOrderindex() == index) && cu.getOrderindex() > customMenu.getOrderindex()){
                    cu.setOrderindex(cu.getOrderindex() - 1);
                    cu.setModifyAccount(accountId);
                    cu.setModifyDate(new Date());
                    list.add(cu);
                }
            }
        }

        if(list.size() > 0){
            customMenu.setOrderindex(index);
            list.add(customMenu);
            customMenuRepository.save(list);
        }
        return true;
    }

    @Override
    public boolean updateMyMenuTemplateIndex(Long accountId, Long id, int index) {
        CustomMenuTemplate one = customMenuTemplateRepository.findOne(id);
        List<CustomMenuTemplate> menuTemplateList = customMenuTemplateRepository.findMyTemplateById(one.getCustomMenuId());
        List<CustomMenuTemplate> list = new ArrayList<>();
        //看单前移
        if(one.getOrderindex() > index){
            for(CustomMenuTemplate cu : menuTemplateList){
                if((cu.getOrderindex() > index || cu.getOrderindex() == index) && cu.getOrderindex() < one.getOrderindex()){
                    cu.setModifyAccount(accountId);
                    cu.setModifyDate(new Date());
                    cu.setOrderindex(cu.getOrderindex() + 1);
                    list.add(cu);
                }
            }
        }//看单后移
        else if(one.getOrderindex() > index){
            for(CustomMenuTemplate cu : menuTemplateList){
                if((cu.getOrderindex() < index || cu.getOrderindex() == index) && cu.getOrderindex() > one.getOrderindex()){
                    cu.setModifyAccount(accountId);
                    cu.setModifyDate(new Date());
                    cu.setOrderindex(cu.getOrderindex() - 1);
                    list.add(cu);
                }
            }
        }

        if(list.size() > 0){
            one.setOrderindex(index);
            list.add(one);
            customMenuTemplateRepository.save(list);
        }
        return true;
    }

    @Override
    public CustomMenuTemplate updateMyMenuTemplateType(Long accountId, Long id, String type) {
        CustomMenuTemplate one = customMenuTemplateRepository.findOne(id);
        one.setType(type);
        one.setModifyDate(new Date());
        one.setModifyAccount(accountId);

        CustomMenuTemplate save = customMenuTemplateRepository.save(one);
        return save;
    }

    @Override
    public List<CustomMenu> listByReportId(Long originalReportId, String type) {
        List<Long> menuIdList = customMenuTemplateRepository.findMenuByOriginal(originalReportId,type);
        if(ValidateUtil.isValid(menuIdList)){
            List<CustomMenu> menuList = customMenuRepository.findAllByIds(menuIdList);
            return menuList;
        }
        return null;
    }

    @Override
    public List<CustomMenuShare> findIndustry() {
        return customMenuShareRepository.findIndustry();
    }

    /**
     * 根据分享ID和APPID校验是否已经加入过我的看单
     * created by sunhao 20170505
     */
    @Override
    public boolean validIsExists(Long appId, Long shareId) {

        return customMenuRepository.findByShareId(appId, shareId).intValue() > 0;
    }
}
