com.gongpingjia.carplay.service.impl.ActivityServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.gongpingjia.carplay.service.impl.ActivityServiceImpl.java

Source

package com.gongpingjia.carplay.service.impl;

import com.gongpingjia.carplay.common.chat.ChatThirdPartyService;
import com.gongpingjia.carplay.common.domain.ResponseDo;
import com.gongpingjia.carplay.common.exception.ApiException;
import com.gongpingjia.carplay.common.photo.PhotoService;
import com.gongpingjia.carplay.common.util.*;
import com.gongpingjia.carplay.dao.activity.ActivityDao;
import com.gongpingjia.carplay.dao.activity.AppointmentDao;
import com.gongpingjia.carplay.dao.activity.PushInfoDao;
import com.gongpingjia.carplay.dao.common.PhotoDao;
import com.gongpingjia.carplay.dao.history.InterestMessageDao;
import com.gongpingjia.carplay.dao.statistic.StatisticActivityMatchDao;
import com.gongpingjia.carplay.dao.user.SubscriberDao;
import com.gongpingjia.carplay.dao.user.UserDao;
import com.gongpingjia.carplay.entity.activity.Activity;
import com.gongpingjia.carplay.entity.activity.Appointment;
import com.gongpingjia.carplay.entity.activity.PushInfo;
import com.gongpingjia.carplay.entity.common.Address;
import com.gongpingjia.carplay.entity.common.Landmark;
import com.gongpingjia.carplay.entity.common.Photo;
import com.gongpingjia.carplay.entity.history.InterestMessage;
import com.gongpingjia.carplay.entity.statistic.StatisticActivityMatch;
import com.gongpingjia.carplay.entity.user.Subscriber;
import com.gongpingjia.carplay.entity.user.User;
import com.gongpingjia.carplay.service.ActivityService;
import com.gongpingjia.carplay.service.util.ActivityQueryParam;
import com.gongpingjia.carplay.service.util.DistanceUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.*;

/**
 * Created by heyongyu on 2015/9/22.
 */
@Service("activityService")
public class ActivityServiceImpl implements ActivityService {

    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(ActivityServiceImpl.class);

    @Autowired
    private ChatThirdPartyService chatThirdPartyService;

    @Autowired
    private ChatCommonService chatCommonService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private ActivityDao activityDao;

    @Autowired
    private AppointmentDao appointmentDao;

    @Autowired
    private SubscriberDao subscriberDao;

    @Autowired
    private InterestMessageDao interestMessageDao;

    @Autowired
    private PushInfoDao pushInfoDao;

    @Autowired
    private StatisticActivityMatchDao statisticActivityMatchDao;

    @Autowired
    @Qualifier("thirdPhotoManager")
    private PhotoService thirdPhotoManager;

    @Autowired
    private PhotoDao photoDao;

    /**
     *  
     *
     * @param userId
     * @param activity
     * @return
     * @throws ApiException
     */
    @Override
    public ResponseDo activityRegister(String userId, Activity activity) throws ApiException {
        LOG.debug("activityRegister");

        buildUserActivityCover(userId, activity);

        User user = userDao.findById(userId);

        Long current = DateUtil.getTime();

        saveUserActivity(userId, activity, current);

        saveInterestMessage(userId, activity, current);

        //????
        Map<String, Object> ext = new HashMap<>(1);
        ext.put("avatar", CommonUtil.getLocalPhotoServer() + user.getAvatar());
        String message = MessageFormat.format(
                PropertiesUtil.getProperty("dynamic.format.interest", "{0}{1}"), user.getNickname(),
                activity.getType());
        chatThirdPartyService.sendUserGroupMessage(chatCommonService.getChatToken(), Constants.EmchatAdmin.INTEREST,
                buildUserSubscribers(userId), message, ext);

        chatThirdPartyService.sendUserGroupMessage(chatCommonService.getChatToken(), Constants.EmchatAdmin.NEARBY,
                buildNearByUsers(user, activity.getActivityId()), message, ext);

        return ResponseDo.buildSuccessResponse(activity.getActivityId());
    }

    private void buildUserActivityCover(String userId, Activity activity) throws ApiException {
        if (StringUtils.isNotEmpty(activity.getCover())) {
            //??
            Photo photo = photoDao.findById(activity.getCover());
            if (photo == null) {
                LOG.warn("Input parameter cover is not exist, photoId:{}", activity.getCover());
                throw new ApiException("???");
            }

            if (!thirdPhotoManager.isExist(photo.getKey())) {
                LOG.warn("Input parameter cover is not exist");
                throw new ApiException("???");
            }
            activity.setCover(photo.getKey());
        } else {
            Photo photo = photoDao.getLatestAlbumPhoto(userId);
            if (photo != null) {
                //?????
                activity.setCover(photo.getKey());
            }
        }
    }

    private void saveInterestMessage(String userId, Activity activity, Long current) {
        InterestMessage oldMessage = interestMessageDao
                .findOne(Query.query(Criteria.where("relatedId").is(activity.getActivityId())));
        if (oldMessage == null) {
            LOG.debug("Old message is not exist, with activityId:{}", activity.getActivityId());
            InterestMessage interestMessage = new InterestMessage();
            interestMessage.setUserId(userId);
            interestMessage.setType(InterestMessage.USER_ACTIVITY);
            interestMessage.setRelatedId(activity.getActivityId());
            interestMessage.setCreateTime(current);
            interestMessageDao.save(interestMessage);
        } else {
            LOG.debug("Old message is exist, with activityId:{}, update create time", activity.getActivityId());
            interestMessageDao.update(Query.query(Criteria.where("relatedId").is(activity.getActivityId())),
                    Update.update("createTime", current));
        }
    }

    private void saveUserActivity(String userId, Activity activity, Long current) {
        Activity oldActivity = activityDao.findOne(Query
                .query(Criteria.where("userId").is(userId).and("deleteFlag").is(false).and("majorType")
                        .is(activity.getMajorType()).and("type").is(activity.getType()))
                .with(new Sort(new Sort.Order(Sort.Direction.DESC, "createTime"))));

        if (oldActivity == null) {
            LOG.debug("Old activity is not exist, create a new");
            //??
            activity.setActivityId(null);
            //ID
            activity.setUserId(userId);
            List<String> memberIds = new ArrayList<String>(1);
            //?
            memberIds.add(userId);
            activity.setMembers(memberIds);
            activity.setCreateTime(current);
            activity.setDeleteFlag(false);

            activityDao.save(activity);
        } else {
            LOG.debug("Old activity is exist, update activity info, activityId:{}", activity.getActivityId());
            //??
            Update update = new Update();
            update.set("pay", activity.getPay());
            update.set("destPoint", activity.getDestPoint());
            update.set("destination", activity.getDestination());
            update.set("estabPoint", activity.getEstabPoint());
            update.set("establish", activity.getEstablish());
            update.set("transfer", activity.isTransfer());
            update.set("createTime", current);
            update.set("applyIds", new ArrayList<>(0));
            update.set("cover", activity.getCover());
            activityDao.update(Query.query(Criteria.where("activityId").is(oldActivity.getActivityId())), update);

            activity.setActivityId(oldActivity.getActivityId());
        }
    }

    private List<String> buildNearByUsers(User user, String activityId) {
        LOG.debug("Send nearby user message, sendUser:{}", user.getUserId());
        PushInfo pushInfo = pushInfoDao.findOne(Query.query(Criteria.where("sendUserId").is(user.getUserId())));
        if (pushInfo != null) { //??
            LOG.info("User:{} has already send push once today", user.getUserId());
            return new ArrayList<>(0);
        }

        //??
        Double distance = Double.parseDouble(PropertiesUtil.getProperty("carplay.nearby.distance.limit", "6000")); //??
        Set<String> subUserIdSet = getSubscribeUsers(user);
        LOG.debug("Get nearby users");
        List<User> nearbyUserList = userDao.find(Query.query(Criteria.where("landmark")
                .near(new Point(user.getLandmark().getLongitude(), user.getLandmark().getLatitude()))
                .maxDistance(distance * 180 / DistanceUtil.EARTH_RADIUS).and("deleteFlag").is(false)));
        Map<String, User> userMap = new HashMap<>(nearbyUserList.size());
        for (User item : nearbyUserList) {
            if (item.getUserId().equals(user.getUserId())) {
                continue;//
            }
            if (subUserIdSet.contains(item.getUserId())) {
                continue;//??????
            }
            userMap.put(item.getUserId(), item);
        }

        return buildEmchatNames(user, nearbyUserList, userMap, activityId);
    }

    /**
     * @param user           ???
     * @param nearbyUserList
     * @param userMap
     * @return
     */
    private List<String> buildEmchatNames(User user, List<User> nearbyUserList, Map<String, User> userMap,
            String activityId) {
        LOG.debug("Get already pushed message users");
        Long current = DateUtil.getTime();

        Integer pushLimit = Integer.parseInt(PropertiesUtil.getProperty("carplay.nearby.push.limit", "3"));// ???
        Set<String> pushedUsers = pushInfoDao.groupByReceivedUsers(userMap.keySet(), pushLimit); // ???

        Integer userLimit = Integer.parseInt(PropertiesUtil.getProperty("carplay.nearby.users.limit", "3"));//?
        List<String> emchatNames = new ArrayList<>(userLimit);//ID
        int count = 0;
        for (User item : nearbyUserList) {
            if (count >= userLimit) {
                break; //???
            }
            if (!userMap.containsKey(item.getUserId())) {
                continue;//??userMap
            }
            if (pushedUsers.contains(item.getUserId())) {
                continue; //?????
            }
            PushInfo info = new PushInfo();
            info.setSendUserId(user.getUserId());
            info.setReceivedUserId(item.getUserId());
            info.setCreateTime(current);
            info.setActivityId(activityId);
            pushInfoDao.save(info);

            emchatNames.add(item.getEmchatName());
            count++;
        }
        LOG.debug("Finished build push users");
        return emchatNames;
    }

    private Set<String> getSubscribeUsers(User user) {
        LOG.debug("Get subscribed users");
        List<Subscriber> subscriberList = subscriberDao
                .find(Query.query(Criteria.where("toUser").is(user.getUserId())));
        Set<String> subUserIdSet = new HashSet<>(subscriberList.size());
        for (Subscriber item : subscriberList) {
            subUserIdSet.add(item.getFromUser());
        }
        return subUserIdSet;
    }

    /**
     * ?Id
     *
     * @param userId Id
     * @return Id
     */
    private List<String> buildUserSubscribers(String userId) {
        //??
        List<Subscriber> subscribers = subscriberDao.find(Query.query(Criteria.where("toUser").is(userId)));
        List<String> userIds = new ArrayList<>(subscribers.size());
        for (Subscriber subscriber : subscribers) {
            userIds.add(subscriber.getFromUser());
        }

        List<User> users = userDao.find(Query.query(Criteria.where("userId").in(userIds)));
        List<String> emchatNames = new ArrayList<>(users.size());
        for (User user : users) {
            emchatNames.add(user.getEmchatName());
        }
        return emchatNames;
    }

    @Override
    public ResponseDo getActivityInfo(String userId, String activityId, Landmark landmark) throws ApiException {
        LOG.debug("getActivityInfo");

        Criteria criteria = Criteria.where("activityId").is(activityId);
        criteria.and("deleteFlag").is(false);
        Activity activity = activityDao.findOne(Query.query(criteria));
        if (null == activity) {
            LOG.warn("activity not exist");
            throw new ApiException("id ?");
        }
        User organizer = userDao.findById(activity.getUserId());
        if (null == organizer) {
            LOG.error("the activity {} cannot found the organizer user {}", activityId, userId);
            throw new ApiException("? User");
        }
        Map<String, Object> map = organizer.buildCommonUserMap();
        User.appendCover(map, userDao.getCover(activity.getCover(), organizer.getUserId()));
        activity.setOrganizer(map);
        if (landmark.getLatitude() != null && landmark.getLongitude() != null) {
            activity.setDistance(DistanceUtil.getDistance(landmark, activity.getEstabPoint()));
        }
        return ResponseDo.buildSuccessResponse(activity);
    }

    @Override
    public ResponseDo sendAppointment(String activityId, String userId, Appointment appointment)
            throws ApiException {
        Activity activity = activityDao.findOne(Query.query(Criteria.where("activityId").is(activityId)));
        if (activity == null) {
            LOG.warn("No activity exist : {}", activityId);
            throw new ApiException("");
        }

        List<String> members = activity.getMembers();
        for (String member : members) {
            if (member.equals(userId)) {
                LOG.warn("Already be a member");
                throw new ApiException("????");
            }
        }

        Appointment appointmentData = appointmentDao.findOne(Query.query(Criteria.where("activityId").is(activityId)
                .and("applyUserId").is(userId).and("status").is(Constants.AppointmentStatus.APPLYING)));
        if (appointmentData != null) {
            LOG.warn("already applying for this activity");
            throw new ApiException("??");
        }

        User user = userDao.findById(userId);

        Long current = DateUtil.getTime();
        appointment.setActivityId(activity.getActivityId());
        appointment.setApplyUserId(userId);
        appointment.setInvitedUserId(activity.getUserId());
        appointment.setCreateTime(current);
        appointment.setStatus(Constants.AppointmentStatus.APPLYING);
        appointment.setModifyTime(current);
        appointment.setActivityCategory(Constants.ActivityCatalog.COMMON);
        //appointment destination activity destination  destPoint   estabPoint
        //appointment  estabPoint  applyUserId ? landmark
        appointment.setDestPoint(activity.getEstabPoint());
        appointment.setDestination(activity.getDestination());
        appointment.setEstabPoint(user.getLandmark());
        appointment.setDistance(DistanceUtil.getDistance(appointment.getEstabPoint(), appointment.getDestPoint()));
        appointmentDao.save(appointment);

        //?ID
        Update update = new Update();
        update.addToSet("applyIds", userId);
        activityDao.update(activityId, update);

        //????
        User organizer = userDao.findById(activity.getUserId());
        User applier = userDao.findById(userId);
        String message = MessageFormat.format(
                PropertiesUtil.getProperty("dynamic.format.activity.invite", "{0}{1}"),
                applier.getNickname(), activity.getType());
        chatThirdPartyService.sendUserGroupMessage(chatCommonService.getChatToken(),
                Constants.EmchatAdmin.ACTIVITY_STATE, organizer.getEmchatName(), message);

        return ResponseDo.buildSuccessResponse();
    }

    /**
     * 
     *
     * @param appointmentId
     * @param userId
     * @param acceptFlag
     * @return
     * @throws ApiException
     */
    @Override
    public ResponseDo processAppointment(String appointmentId, String userId, boolean acceptFlag)
            throws ApiException {
        LOG.debug("applyJoinActivity, appointmentId:{}, accept:{}", appointmentId, acceptFlag);
        Appointment appointment = checkAppointment(appointmentId, userId);

        //        Activity activity = checkAppointmentActivity(appointment);
        //?
        User applyUser = userDao.findById(appointment.getApplyUserId());
        if (applyUser == null) {
            LOG.warn("Apply user is not exist");
            throw new ApiException("?");
        }

        int status = Constants.AppointmentStatus.ACCEPT;
        if (!acceptFlag) {
            //???
            status = Constants.AppointmentStatus.REJECT;
        }
        appointmentDao.update(appointmentId, Update.update("status", status).set("modifyTime", DateUtil.getTime()));

        //        //??
        //        //
        //        try {
        //            chatThirdPartyService.addUserToChatGroup(emchatTokenService.getToken(), activity.getEmchatGroupId(), applyUser.getEmchatName());
        //        } catch (ApiException e) {
        //            LOG.warn(e.getMessage(), e);
        //            //
        //            throw new ApiException("?");
        //        }

        //        //activity members ;
        //        Update activityUpdate = new Update();
        //        activityUpdate.addToSet("members", appointment.getApplyUserId());
        //        activityDao.update(activity.getActivityId(), activityUpdate);

        User user = userDao.findById(userId);

        //????,????
        if (acceptFlag) {
            String message = MessageFormat.format(
                    PropertiesUtil.getProperty("dynamic.format.activity.state", "{0}{1}{2}"),
                    user.getNickname(), "?", appointment.getType());
            chatThirdPartyService.sendUserGroupMessage(chatCommonService.getChatToken(),
                    Constants.EmchatAdmin.ACTIVITY_STATE, applyUser.getEmchatName(), message);
        }

        return ResponseDo.buildSuccessResponse();
    }

    /**
     * ?
     *
     * @param appointment
     * @return
     * @throws ApiException
     */
    private Activity checkAppointmentActivity(Appointment appointment) throws ApiException {
        //?
        Activity activity = activityDao.findById(appointment.getActivityId());
        if (activity == null) {
            LOG.warn("activity not exist");
            throw new ApiException("?");
        }

        for (String memberId : activity.getMembers()) {
            if (memberId.equals(appointment.getApplyUserId())) {
                LOG.warn("user has in the activity");
                throw new ApiException("??");
            }
        }

        return activity;
    }

    /**
     * appointmentuser????
     *
     * @param appointmentId
     * @param userId
     * @return
     * @throws ApiException
     */
    private Appointment checkAppointment(String appointmentId, String userId) throws ApiException {
        //appointment ?
        Appointment appointment = appointmentDao.findById(appointmentId);
        if (appointment == null) {
            LOG.warn("appoint not exist");
            throw new ApiException("?");
        }

        if (!userId.equals(appointment.getInvitedUserId())) {
            LOG.warn("appoint not belong this user");
            throw new ApiException("?");
        }

        if (Constants.AppointmentStatus.APPLYING != appointment.getStatus()) {
            LOG.warn("appoint is applying");
            throw new ApiException("?");
        }

        return appointment;
    }

    /**
     * activityListUser????
     *
     * @param activityList
     * @throws ApiException
     */
    private void initOrganizer(List<Activity> activityList, List<String> subscribeIds) throws ApiException {
        Set<String> userIdSet = new HashSet<>(activityList.size());
        for (Activity activity : activityList) {
            userIdSet.add(activity.getUserId());
        }
        List<User> users = userDao.findByIds(userIdSet);
        Map<String, User> userMap = new HashMap<>(users.size(), 1);
        for (User user : users) {
            userMap.put(user.getUserId(), user);
        }
        for (Activity activity : activityList) {
            User organizer = userMap.get(activity.getUserId());
            if (null == organizer) {
                throw new ApiException("?? ActivityOrganizer");
            }
            Map<String, Object> map = organizer.buildCommonUserMap();
            map.put("subscribeFlag", subscribeIds.contains(organizer.getUserId()));
            activity.setOrganizer(map);
        }
    }

    /**
     *
     * ???
     *
     *
     */

    /**
     * ???   
     * <p/>
     * criteria:
     * city    estabPoint.city
     * phone ? phone user  ? userId   activity
     * fromDate  toDate           createTime
     * pay  -1 ??               ? AA
     * type -1            type ? type
     * transfer  -1       true  false
     *
     * @param json
     * @return
     * @throws ApiException
     */
    @Override
    public ResponseDo getUserActivityList(JSONObject json, String userId) throws ApiException {
        //TODO?
        int draw = json.getInt("draw");
        int start = json.getInt("start");
        int length = json.getInt("length");

        JSONObject resultJson = new JSONObject();

        Query query = new Query();
        Criteria criteria = new Criteria();

        String startTimeStr = json.getString("fromTime");
        String endTimeStr = json.getString("toTime");
        if (StringUtils.isNotEmpty(startTimeStr) && StringUtils.isNotEmpty(endTimeStr)) {
            long startTime = TypeConverUtil.convertToLong("fromTime", startTimeStr, true);
            long endTime = TypeConverUtil.convertToLong("toTime", endTimeStr, true) + 24 * 60 * 60 * 1000;
            criteria.and("createTime").gte(startTime).lte(endTime);
        }

        String phone = json.getString("phone");
        if (StringUtils.isNotEmpty(phone)) {
            User user = userDao.findOne(Query.query(Criteria.where("phone").is(phone)));
            if (null == user || StringUtils.isEmpty(user.getUserId())) {
                throw new ApiException("???");
            }
            criteria.and("userId").is(user.getUserId());
        }

        criteria.and("deleteFlag").is(false);

        String province = json.getString("province");
        if (StringUtils.isNotEmpty(province)) {
            criteria.and("destination.province").is(province);
        }

        String city = json.getString("city");
        if (StringUtils.isNotEmpty(city)) {
            criteria.and("destination.city").is(city);
        }

        String majorType = json.getString("majorType");
        if (StringUtils.isNotEmpty(majorType)) {
            criteria.and("majorType").is(majorType);
        }

        String type = json.getString("type");
        if (StringUtils.isNotEmpty(type) && !StringUtils.equals(type, "-1")) {
            criteria.and("type").is(type);
        }

        String pay = json.getString("pay");
        if (StringUtils.isNotEmpty(pay) && !StringUtils.equals(pay, "-1")) {
            criteria.and("pay").is(pay);
        }

        String transferStr = json.getString("transfer");
        if (StringUtils.isNotEmpty(transferStr) && !StringUtils.equals(transferStr, "-1")) {
            criteria.and("transfer").is(TypeConverUtil.convertToBoolean("transfer", transferStr, true));
        }

        query.addCriteria(criteria);

        long totalNum = activityDao.count(query);

        query.with(new Sort(new Sort.Order(Sort.Direction.DESC, "createTime")));
        query.skip(start).limit(length);
        List<Activity> activityList = activityDao.find(query);

        resultJson.put("draw", draw);
        resultJson.put("recordsFiltered", totalNum);
        resultJson.put("recordsTotal", totalNum);

        if (null == activityList || activityList.isEmpty()) {
            return ResponseDo.buildSuccessResponse(resultJson);
        }

        Set<String> userIdSet = new HashSet<>(activityList.size());
        for (Activity activity : activityList) {
            userIdSet.add(activity.getUserId());
        }

        List<User> userList = userDao.findByIds(userIdSet);

        Map<String, User> userMap = new HashMap<>(userList.size());
        if (null == userList || userList.isEmpty()) {
            throw new ApiException(" ??");
        }
        for (User user : userList) {
            userMap.put(user.getUserId(), user);
        }

        JSONArray jsonArray = new JSONArray();
        for (Activity activity : activityList) {
            JSONObject item = new JSONObject();
            item.put("activityId", activity.getActivityId());
            item.put("nickname", userMap.get(activity.getUserId()).getNickname());
            item.put("phone", userMap.get(activity.getUserId()).getPhone());
            item.put("establish", activity.getEstablish());
            item.put("destination", activity.getDestination());
            item.put("type", activity.getType());
            item.put("pay", activity.getPay());
            item.put("transfer", activity.isTransfer());
            item.put("createTime", activity.getCreateTime());
            item.put("cover", userDao.getCover(activity.getCover(), activity.getUserId()));

            jsonArray.add(item);
        }
        resultJson.put("activityList", jsonArray);

        return ResponseDo.buildSuccessResponse(resultJson);
    }

    @Override
    public ResponseDo updateUserActivity(JSONObject json, String activityId) throws ApiException {

        Update update = new Update();
        try {

            if (json.containsKey("destination") && StringUtils.isNotEmpty(json.getString("destination"))) {
                update.set("destination", JSONObject.toBean(json.getJSONObject("establish"), Address.class));
            }
            if (json.containsKey("destPoint") && StringUtils.isNotEmpty(json.getString("destination"))) {
                update.set("destPoint", JSONObject.toBean(json.getJSONObject("destPoint"), Landmark.class));
            }
            update.set("establish", JSONObject.toBean(json.getJSONObject("establish"), Address.class));
            update.set("estabPoint", JSONObject.toBean(json.getJSONObject("estabPoint"), Landmark.class));
            update.set("majorType", json.getString("majorType"));
            update.set("type", json.getString("type"));
            update.set("pay", json.getString("pay"));
            update.set("transfer", json.getBoolean("transfer"));
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            throw new ApiException("?");
        }
        Activity toFind = activityDao.findById(activityId);
        if (null == toFind) {
            throw new ApiException("id?");
        }
        activityDao.update(activityId, update);
        return ResponseDo.buildSuccessResponse();

    }

    @Override
    public ResponseDo viewUserActivity(String activityId) throws ApiException {
        Activity activity = activityDao.findById(activityId);
        if (null == activity) {
            throw new ApiException("?");
        }
        User organizer = userDao.findById(activity.getUserId());
        if (null == organizer || StringUtils.isEmpty(organizer.getUserId())) {
            throw new ApiException("");
        }
        activity.setOrganizer(organizer.buildCommonUserMap());

        Criteria criteria = new Criteria();
        criteria.and("activityId").is(activity.getActivityId());
        Query query = Query.query(criteria);
        query.with(new Sort(new Sort.Order(Sort.Direction.DESC, "createTime")));
        List<Appointment> appointmentList = appointmentDao.find(query);
        if (null != appointmentList && !appointmentList.isEmpty()) {
            activity.setAppointmentList(appointmentList);
        }
        return ResponseDo.buildSuccessResponse(activity);
    }

    @Override
    public ResponseDo deleteUserActivities(Collection ids) throws ApiException {
        if (null == ids || ids.isEmpty()) {
            throw new ApiException("");
        }
        List<Activity> byIds = activityDao.findByIds(ids);
        if (null == byIds || ids.isEmpty()) {
            throw new ApiException("id??");
        }
        if (byIds.size() != ids.size()) {
            throw new ApiException("id??");
        }
        activityDao.update(Query.query(Criteria.where("_id").in(ids)), Update.update("deleteFlag", true));
        return ResponseDo.buildSuccessResponse();
    }

    /**
     * ??
     *
     * @param param ?
     * @return
     */
    @Override
    public ResponseDo getNearByActivityList(HttpServletRequest request, ActivityQueryParam param) {
        LOG.info("Query parameters:{}", param.toString());

        //?
        List<Activity> activityList = activityDao.find(Query.query(param.buildCommonQueryParam()));

        if (activityList.isEmpty()) {
            LOG.warn("No activity result found from database");
            return ResponseDo.buildSuccessResponse(activityList);
        }

        Map<String, User> userMap = buildUserMap(activityList);

        //?   id
        List<Activity> activities = rebuildActivities(param, activityList, userMap);

        //?
        sortActivityList(userMap, activities);

        if (activities.size() < param.getIgnore()) {
            LOG.warn("No data exist after ignore:{}", param.getIgnore());
            return ResponseDo.buildSuccessResponse(new ArrayList<>(0));
        }

        List<Activity> remainActivities = activities.subList(param.getIgnore(), activities.size());
        if (remainActivities.size() > param.getLimit()) {
            remainActivities = remainActivities.subList(0, param.getLimit());
        }

        LOG.debug("Query user subscriber info");
        Map<String, Subscriber> subscriberMap = initSubscriberMap(param.getUserId());
        Set<String> subscriberSet = subscriberMap.keySet();

        //Activity ?
        return ResponseDo
                .buildSuccessResponse(buildResponse(param.getUserId(), userMap, remainActivities, subscriberSet));
    }

    private void sortActivityList(Map<String, User> userMap, List<Activity> activities) {
        //???
        Collections.sort(activities);

        for (Activity item : activities) {
            User user = userMap.get(item.getUserId());

            //?????????, ???0.1,???0.2,???0.4,0.8,1.6...
            if (user.getMatchTimes() > 0) {
                item.setSortFactor(item.getSortFactor() - 0.1 * Math.pow(2, user.getMatchTimes() - 1));
            }
            user.setMatchTimes(user.getMatchTimes() + 1);
        }

        Collections.sort(activities);
    }

    private void initAndSaveStatisticActivityReMatch(HttpServletRequest request, ActivityQueryParam param,
            String eventType) {
        StatisticActivityMatch statisticActivityMatch = new StatisticActivityMatch();

        statisticActivityMatch.setType(param.getType());
        statisticActivityMatch.setMajorType(param.getMajorType());
        statisticActivityMatch.setPay(param.getPay());
        Address address = new Address();
        address.setProvince(param.getProvince());
        address.setCity(param.getCity());
        address.setDistrict(param.getDistrict());
        statisticActivityMatch.setDestination(address);

        Landmark landmark = new Landmark();
        landmark.setLongitude(param.getLongitude());
        landmark.setLatitude(param.getLatitude());
        statisticActivityMatch.setDestPoint(landmark);

        statisticActivityMatch.setTransfer(param.getTransfer());
        statisticActivityMatch.setUserId(param.getUserId());
        statisticActivityMatch.setIp(IPFetchUtil.getIPAddress(request));

        statisticActivityMatch.setEvent(eventType);
        statisticActivityMatch.setCount(1);

        Date currentTime = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentTime);
        statisticActivityMatch.setCreateTime(currentTime.getTime());
        statisticActivityMatch.setYear(calendar.get(Calendar.YEAR));
        statisticActivityMatch.setMonth(calendar.get(Calendar.MONTH) + 1);
        statisticActivityMatch.setDay(calendar.get(Calendar.DAY_OF_MONTH) + 1);
        statisticActivityMatch.setHour(calendar.get(Calendar.HOUR));
        statisticActivityMatch.setMinute(calendar.get(Calendar.MINUTE));
        statisticActivityMatchDao.save(statisticActivityMatch);
    }

    private boolean isApplied(String userId, List<String> applyIds) {
        if (StringUtils.isEmpty(userId)) {
            return false;
        }

        if (null == applyIds || applyIds.isEmpty()) {
            return false;
        }

        boolean applyFlag = false;
        for (String id : applyIds) {
            if (StringUtils.equals(id, userId)) {
                applyFlag = true;
            }
        }
        return applyFlag;
    }

    private List<Map<String, Object>> buildResponse(String userId, Map<String, User> userMap,
            List<Activity> remainActivities, Set<String> subscriberSet) {
        List<Map<String, Object>> result = new ArrayList<>(remainActivities.size());
        for (Activity item : remainActivities) {
            Map<String, Object> map = new HashMap<>();
            map.put("activityId", item.getActivityId());
            map.put("transfer", item.isTransfer());
            map.put("distance", item.getDistance());
            map.put("applyFlag", isApplied(userId, item.getApplyIds()));
            User user = userMap.get(item.getUserId());
            Map<String, Object> organizer = new HashMap<>(9, 1);
            if (user != null) {
                organizer = user.buildCommonUserMap();
                User.appendCover(organizer, userDao.getCover(item.getCover(), user.getUserId()));
                organizer.put("userId", user.getUserId());
            }
            map.put("organizer", organizer);
            map.put("pay", item.getPay());
            map.put("majorType", item.getMajorType());
            map.put("type", item.getType());
            map.put("destination", item.getDestination());
            result.add(map);
        }
        return result;
    }

    /**
     * ????
     *
     * @param param
     * @param activityList
     * @param userMap
     * @return
     */
    private List<Activity> rebuildActivities(ActivityQueryParam param, List<Activity> activityList,
            Map<String, User> userMap) {
        Map<String, Appointment> appointmentActivityMap = buildUserAppointmentActivityIds(param);

        LOG.debug("Filter user by idle status and compute weight");
        Long current = DateUtil.getTime();
        List<Activity> activities = new ArrayList<>(activityList.size());
        for (Activity item : activityList) {
            if (StringUtils.isNotEmpty(param.getUserId())) {
                //Id?
                //?????
                Appointment appointment = appointmentActivityMap.get(item.getActivityId());
                if (appointment != null && appointment.getCreateTime() > item.getCreateTime()) {
                    //????????
                    continue;
                }
            }

            User user = userMap.get(item.getUserId());
            if (param.isCommonQuery()) {
                if (StringUtils.isNotEmpty(param.getGender())) {
                    if (!StringUtils.equals(param.getGender(), user.getGender())) {
                        //???
                        continue;
                    }
                }
            }
            if (user != null && user.getIdle()) {
                //????
                item.setSortFactor(computeWeight(param, current, item, user));
                activities.add(item);
            }
        }
        return activities;
    }

    /**
     * ??
     *
     * @param param
     * @return
     */
    private Map<String, Appointment> buildUserAppointmentActivityIds(ActivityQueryParam param) {
        LOG.debug("Check user is already appointment or not, filter the activity");
        List<Appointment> appointmentList = new ArrayList<>(0);
        if (StringUtils.isNotEmpty(param.getUserId())) {
            appointmentList = appointmentDao.find(Query.query(
                    Criteria.where("applyUserId").is(param.getUserId()).and("deleteFlag").is(false).and("status")
                            .in(Constants.AppointmentStatus.ACCEPT, Constants.AppointmentStatus.REJECT)));
        }

        Map<String, Appointment> activityAppointmentMap = new HashMap<>();
        for (Appointment item : appointmentList) {
            //??
            Appointment appointment = activityAppointmentMap.get(item.getActivityId());
            if (appointment == null) {
                //map
                activityAppointmentMap.put(item.getActivityId(), item);
                continue;
            }

            if (item.getCreateTime() > appointment.getCreateTime()) {
                //??
                activityAppointmentMap.put(item.getActivityId(), item);
            }
        }
        return activityAppointmentMap;
    }

    /**
     * ??
     *
     * @param param   ????
     * @param current ?
     * @param item    
     * @param user    ?
     * @return ??
     */
    private double computeWeight(ActivityQueryParam param, Long current, Activity item, User user) {
        //???
        //        item.setDistance(DistanceUtil.getDistance(param.getLongitude(), param.getLatitude(), item.getEstabPoint().getLongitude(), item.getEstabPoint().getLatitude()));
        item.setDistance(DistanceUtil.getDistance(new Landmark(param.getLongitude(), param.getLatitude()),
                item.getEstabPoint()));

        double sortFactor = 0.2 * (1 - item.getDistance() / param.getMaxDistance());

        sortFactor += 0.1 * (1 - (current - item.getCreateTime()) / param.getMaxTimeLimit());

        //???
        if (Constants.AuthStatus.ACCEPT.equals(user.getLicenseAuthStatus())) {
            sortFactor += 0.15;
        }
        //????
        if (Constants.AuthStatus.ACCEPT.equals(user.getPhotoAuthStatus())) {
            sortFactor += 0.25;
        }
        //TODO ???

        //??
        if (item.getDestination() != null) {
            Address address = item.getDestination();
            if (address.getProvince() != null && address.getDistrict() != null) {
                sortFactor += 0.15;
            }
        }
        //???
        sortFactor += 0.05;

        return sortFactor;
    }

    private Map<String, User> buildUserMap(List<Activity> activityList) {
        LOG.debug("Query users by activity list");
        Map<String, User> userMap = new HashMap<>(activityList.size(), 1);
        for (Activity item : activityList) {
            userMap.put(item.getUserId(), null);
        }

        List<User> users = userDao.findByIds(userMap.keySet());
        for (User item : users) {
            userMap.put(item.getUserId(), item);
        }

        return userMap;
    }

    private Map<String, Subscriber> initSubscriberMap(String userId) {
        List<Subscriber> subscribers = new ArrayList<>(0);
        if (!StringUtils.isEmpty(userId)) {
            subscribers = subscriberDao.find(Query.query(Criteria.where("fromUser").is(userId)));
        }

        Map<String, Subscriber> subscriberMap = new HashMap<>(subscribers.size(), 1);
        for (Subscriber item : subscribers) {
            subscriberMap.put(item.getToUser(), item);
        }
        return subscriberMap;
    }

    /**
     * ??
     *
     * @param param ?
     * @return
     */
    public ResponseDo getRandomActivities(ActivityQueryParam param) {
        LOG.info("Query random activities parameters:{}", param.toString());

        int counts = 0;
        List<Activity> activities = new ArrayList<>(0);
        do {
            //?4?
            if (counts >= 4) {
                break;
            }
            if (counts > 0) {
                //?10?
                param.setMaxDistance(param.getMaxDistance() * 10);
            }
            //?
            List<Activity> activityList = activityDao.find(Query.query(param.buildExpandQueryParam()));
            Map<String, User> userMap = buildUserMap(activityList);

            //?   id
            activities = rebuildActivities(param, activityList, userMap);
            counts++;
        } while (activities.size() < param.getLimit());

        if (activities.size() > param.getLimit()) {
            activities = activities.subList(0, param.getLimit());
        }

        Map<String, User> userMap = buildUserMap(activities);

        LOG.debug("Begin build response");
        return ResponseDo.buildSuccessResponse(
                buildResponse(param.getUserId(), userMap, activities, new HashSet<String>(0)));
    }

    @Override
    public ResponseDo getNearByActivityCount(ActivityQueryParam param) {
        LOG.info("Query parameters:{}", param.toString());
        Map<String, Object> data = new HashMap<>(1);
        //?
        List<Activity> activityList = activityDao.find(Query.query(param.buildCommonQueryParam()));
        if (activityList.isEmpty()) {
            //
            LOG.info("No result find, begin expand query");
            data.put("count", 0);
            return ResponseDo.buildSuccessResponse(data);
        }

        Map<String, User> userMap = buildUserMap(activityList);

        //?   id
        List<Activity> activities = rebuildActivities(param, activityList, userMap);

        data.put("count", activities.size());
        //Activity ?
        return ResponseDo.buildSuccessResponse(data);
    }

    @Override
    public ResponseDo getActivityPushInfos(HttpServletRequest request, String userId, Integer limit,
            Integer ignore) {
        LOG.debug("Query user pushInfo, userId:{}", userId);
        List<PushInfo> pushInfoList = pushInfoDao
                .find(Query.query(Criteria.where("receivedUserId").is(userId).and("deleteFlag").is(false))
                        .limit(limit).skip(ignore));

        Set<String> activityIds = new HashSet<>(pushInfoList.size(), 1);
        for (PushInfo item : pushInfoList) {
            activityIds.add(item.getActivityId());
        }
        LOG.debug("Query user subscriber info");
        Map<String, Subscriber> subscriberMap = initSubscriberMap(userId);
        Set<String> subscriberSet = subscriberMap.keySet();

        List<Activity> activityList = activityDao
                .find(Query.query(Criteria.where("activityId").in(activityIds).and("deleteFlag").is(false))
                        .with(new Sort(new Sort.Order(Sort.Direction.DESC, "createTime"))));
        Map<String, User> userMap = buildUserMap(activityList);

        User user = userDao.findById(userId);
        for (Activity item : activityList) {
            User organizer = userMap.get(item.getUserId());
            item.setDistance(DistanceUtil.getDistance(user.getLandmark(), organizer.getLandmark()));
        }

        LOG.debug("Finished query data, begin build response");
        return ResponseDo.buildSuccessResponse(buildResponse(userId, userMap, activityList, subscriberSet));
    }

    @Override
    public ResponseDo registerUserActivity(String phone, String userId, Activity activity) throws ApiException {
        LOG.debug("activityRegister");

        User user = userDao.findUserByPhone(phone);
        //        if (user == null) {
        //            throw new ApiException("?");
        //        }

        if (user == null) {
            user = userDao.findById(userId);
        }

        Long current = DateUtil.getTime();

        saveUserActivity(user.getUserId(), activity, current);

        saveInterestMessage(user.getUserId(), activity, current);

        //????
        Map<String, Object> ext = new HashMap<>(1);
        ext.put("avatar", CommonUtil.getLocalPhotoServer() + user.getAvatar());
        String message = MessageFormat.format(
                PropertiesUtil.getProperty("dynamic.format.interest", "{0}{1}"), user.getNickname(),
                activity.getType());
        chatThirdPartyService.sendUserGroupMessage(chatCommonService.getChatToken(), Constants.EmchatAdmin.INTEREST,
                buildUserSubscribers(user.getUserId()), message, ext);

        chatThirdPartyService.sendUserGroupMessage(chatCommonService.getChatToken(), Constants.EmchatAdmin.NEARBY,
                buildNearByUsers(user, activity.getActivityId()), message, ext);

        return ResponseDo.buildSuccessResponse();
    }
}