/**
 * Description: CmLotteryRule业务实现类
 * Copyright:   Copyright (c)2015
 * Company:     江苏三六五网络股份有限公司
 *
 * @author: 江苏三六五网络股份有限公司
 * @version: 1.0
 * Create at:   2015-08-19 上午 11:24:24
 * <p/>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2015-08-19   江苏三六五网络股份有限公司   1.0         Initial
 */
package com.house365.ws.service.impl;

import com.google.common.base.Strings;
import com.house365.beans.entity.CmCreditRecordEntity;
import com.house365.beans.entity.CmCreditRuleEntity;
import com.house365.beans.entity.CmLotteryRuleEntity;
import com.house365.beans.entity.CmUserEntity;
import com.house365.dao.system.interfaces.Dao;
import com.house365.rest.exception.IllegalServiceInputException;
import com.house365.rest.exception.NeedRollBackException;
import com.house365.service.system.impl.DefaultServiceImpl;
import com.house365.ws.dao.interfaces.ICmCreditRecordDao;
import com.house365.ws.dao.interfaces.ICmLotteryRuleDao;
import com.house365.ws.dao.interfaces.ICmUserDao;
import com.house365.ws.service.interfaces.ICmCreditRuleService;
import com.house365.ws.service.interfaces.ICmLotteryRuleService;
import com.house365.ws.service.interfaces.ICmUserService;
import com.house365.ws.util.CmCommonUtils;
import com.house365.ws.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * CmLotteryRule业务实现类<br>
 *
 * @author 江苏三六五网络股份有限公司
 * @version 1.0, 2015-08-19
 * @see
 * @since 1.0
 */
@Service("cmLotteryRuleService")
public class CmLotteryRuleServiceImpl<T extends CmLotteryRuleEntity> extends DefaultServiceImpl<T> implements ICmLotteryRuleService<T> {
    /**
     * 自动注入的数据访问对象
     */
    @Autowired
    ICmUserService<CmUserEntity> iCmUserService;

    @Autowired
    private ICmLotteryRuleDao<T> cmLotteryRuleDao;

    @Autowired
    private ICmCreditRecordDao<CmCreditRecordEntity> cmCreditRecordDao;

    @Autowired
    private ICmUserDao<CmUserEntity> cmUserDao;

    @Autowired
    private ICmCreditRuleService<CmCreditRuleEntity> iCmCreditRuleService;

    public static void main(String[] args) {
        float rule1 = 0.1f;
        float rule2 = 0.2f;
        float rule3 = 0.4f;
        float rule4 = 1f;
        float rule5 = 1f;
        float rule6 = 1f;

        List<Float> ruleList = new ArrayList();
        ruleList.add(rule1);
        ruleList.add(rule2);
        ruleList.add(rule3);
        ruleList.add(rule4);
        ruleList.add(rule5);
        ruleList.add(rule6);
        Float totalProbability = 0f;
        for (float rule : ruleList) {
            totalProbability += rule;
        }


        int rule1Count = 0;
        int rule2Count = 0;
        int rule3Count = 0;
        int rule4Count = 0;
        int rule5Count = 0;
        int rule6Count = 0;

        for (int z = 0; z < 10000; z++) {
            Random random = new Random();
            Float currentRandom = random.nextFloat() * 100 % totalProbability;

            float startProbability = 0;
            for (float rule : ruleList) {
                float endProbability = startProbability + rule;
                if (currentRandom >= startProbability && currentRandom < endProbability) {
                    if (0f <= currentRandom && currentRandom < 0.1f) {
                        rule1Count++;
                        break;
                    } else if (0.1f <= currentRandom && currentRandom < 0.3) {
                        rule2Count++;
                        break;
                    } else if (0.3f <= currentRandom && currentRandom < 0.7) {
                        rule3Count++;
                        break;
                    } else if (0.7f <= currentRandom && currentRandom < 1.7) {
                        rule4Count++;
                        break;
                    } else if (1.7f <= currentRandom && currentRandom < 2.7) {
                        rule5Count++;
                        break;
                    } else if (2.7f <= currentRandom && currentRandom < 3.7) {
                        rule6Count++;
                        break;
                    }
                }
                startProbability = endProbability;
            }
        }
        System.out.println(rule1Count);
        System.out.println(rule2Count);
        System.out.println(rule3Count);
        System.out.println(rule4Count);
        System.out.println(rule5Count);
        System.out.println(rule6Count);
    }

    @Override
    protected Dao<T> getDao() {
        return cmLotteryRuleDao;
    }

    /**
     * 获取用户签到抽奖积分
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param user
     * @param subRule    抽奖扣除积分规则
     * @param userId
     * @param useridType
     * @param cityKey
     * @return
     * @throws Exception
     * @author yinchangming
     * @version [v1.0.0, 2015年8月19日]
     * @since [产品/模块版本](可选)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = NeedRollBackException.class)
    public synchronized CmLotteryRuleEntity transGetSignedLotteryScore(String userId, Integer useridType, String cityKey) throws Exception {
        CmUserEntity cmUser = iCmUserService.getUserByUserIdCityKeyUserType(userId, cityKey, useridType);

        if (cmUser == null) {
            throw new IllegalServiceInputException("0");
        }

        if (!Strings.isNullOrEmpty(cityKey) && Strings.isNullOrEmpty(cmUser.getCityId())) {
            cmUser.setCityId(cityKey);
        }

        //今日未签到，不能抽奖
//        String lastSignTimeStr = null;
//        if (cmUser.getLastSignTime() != null) {
//            lastSignTimeStr = DateUtils.dateToStr(cmUser.getLastSignTime());
//        }
        String nowTimeStr = DateUtils.dateToStr(new Date());
//        if (!(nowTimeStr.equals(lastSignTimeStr))) {
//            throw new IllegalServiceInputException("今日未签到!");
//        }

        //签到后，第一次抽奖免费
        String lastSignLotteryTimeStr = null;
        if (cmUser.getLastSignLotteryTime() != null) {
            lastSignLotteryTimeStr = DateUtils.dateToStr(cmUser.getLastSignLotteryTime());
        }

        //先获取随机积分
        CmLotteryRuleEntity lRule = transGetRandomScore();
        lRule.setUserCredits(cmUser.getCredits());

        //更新用户表
        //为零，不计
        if (lRule == null) {
            throw new IllegalServiceInputException("1");
        }
        //如果最后一次抽奖时间在今天，则判断积分是否够扣除，是则扣除积分
        if (nowTimeStr.equals(lastSignLotteryTimeStr)) {
            CmCreditRuleEntity subLotteryRule = iCmCreditRuleService.getById(15);
            if (cmUser.getCredits() < Math.abs(subLotteryRule.getCredits())) {
                throw new IllegalServiceInputException("2");
            }
            try {
                //扣除抽奖所需积分
                cmUserDao.updateCredits(cmUser.getId(), subLotteryRule.getCredits());
                lRule.setUserCredits(cmUser.getCredits() + subLotteryRule.getCredits());
                if (subLotteryRule.getCredits() != 0) {
                    //记录扣除积分记录 和 更新时间
                    cmCreditRecordDao.saveLotteryCreditsRecord(cmUser, subLotteryRule.getCredits());
                }
            } catch (Exception e) {
                throw new NeedRollBackException(e.getMessage());
            }

            cmUser.setCredits(cmUser.getCredits() + subLotteryRule.getCredits());
        }
        if (lRule.getCredits() == 0 && lRule.getId() == 1) {
            throw new IllegalServiceInputException("3");
        } else if (lRule.getCredits() == 0 && lRule.getId() == 2) {
            throw new IllegalServiceInputException("4");
        }
        try {
            //抽奖获得积分记录
            cmCreditRecordDao.saveSignLotteryCreditsRecord(cmUser, lRule.getCredits());
            //更新抽奖后最新积分 和 抽奖时间
            cmUserDao.updateCredits(cmUser.getId(), lRule.getCredits());
            lRule.setUserCredits(cmUser.getCredits() + lRule.getCredits());
        } catch (Exception e) {
            throw new NeedRollBackException(e.getMessage());
        }
        iCmUserService.clearUserCache(cmUser.getUserId());

        return lRule;
    }

    /**
     * 获取用户签到积分
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param userId
     * @return
     * @throws Exception
     * @author yinchangming
     * @version [v1.0.0, 2015年8月19日]
     * @since [产品/模块版本](可选)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Integer transGetSignedScore(CmUserEntity user, String cityKey) throws Exception {
        user.setCredits(user.getCredits() == null ? 0 : user.getCredits());
        //获取额外奖励
        Integer bonus = CmCommonUtils.getSignCreditsByContinuousSignCount(user.getContinuousSignCount());
        //user.setCredits(user.getCredits()+bonus);
        user.setUpdateTime(new Date());
        user.setLastSignTime(new Date());
        CmCreditRecordEntity record = cmCreditRecordDao.saveSignCreditsRecord(user, bonus);
        user.setCredits(record.getRemainingAmount());
        cmUserDao.update(user);
        iCmUserService.clearUserCache(user.getUserId());

        return user.getCredits();
    }

    /**
     * 获取随机签到积分
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @return
     * @author yinchangming
     * @version [v1.0.0, 2015年8月19日]
     * @since [产品/模块版本](可选)
     */

    private CmLotteryRuleEntity transGetRandomScore() {
        //获取所有积分概率
        List<CmLotteryRuleEntity> ruleList = (List<CmLotteryRuleEntity>) cmLotteryRuleDao.queryAll();
        //概率综合
        Float totalProbability = 0f;
        for (CmLotteryRuleEntity rule : ruleList) {
            totalProbability += rule.getProbability();
        }
        //所有概率和之间的随机数
        Random random = new Random();
        Float currentRandom = random.nextFloat() * 100 % totalProbability;

        //抽奖规则按概率从小到大排序
        Collections.sort(ruleList);
        //获取所在的随机数区段，返回值
        float startProbability = 0;
        for (CmLotteryRuleEntity rule : ruleList) {
            float endProbability = startProbability + rule.getProbability();
            if (currentRandom >= startProbability && currentRandom < endProbability) {
                return rule;
            }
            startProbability = endProbability;
        }
        return null;
    }

}
