/**
 * 请勿将俱乐部专享资源复制给其他人，保护知识产权即是保护我们所在的行业，进而保护我们自己的利益
 * 即便是公司的同事，也请尊重 JFinal 作者的努力与付出，不要复制给同事
 * <p>
 * 如果你尚未加入俱乐部，请立即删除该项目，或者现在加入俱乐部：http://jfinal.com/club
 * <p>
 * 俱乐部将提供 jfinal-club 项目文档与设计资源、专用 QQ 群，以及作者在俱乐部定期的分享与答疑，
 * 价值远比仅仅拥有 jfinal club 项目源代码要大得多
 * <p>
 * JFinal 俱乐部是五年以来首次寻求外部资源的尝试，以便于有资源创建更加
 * 高品质的产品与服务，为大家带来更大的价值，所以请大家多多支持，不要将
 * 首次的尝试扼杀在了摇篮之中
 */

package com.jfinal.club.my.like;

import com.jfinal.aop.Inject;
import com.jfinal.club.common.account.AccountService;
import com.jfinal.club.common.model.Account;
import com.jfinal.club.common.model.Doc;
import com.jfinal.club.common.model.Loveings;
import com.jfinal.club.common.model.Userct;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 个人空间、用户空间的粉丝数量旁边添加一个赞数量： 关注(19)  粉丝(999)  赞(9999)
 * <p>
 * 对于 reply list item 中的点赞按钮颜色可以淡些，鼠标放上去颜色深点
 * <p>
 * 点赞功能，每篇 article、reply 都可以被人点赞
 * project、project_like、share、share_like ...
 */
public class LikeService {

    @Inject
    LikeMessageLogService likeMessageLogSrv;

    @Inject
    AccountService accountSrv;

    @Inject
    Loveings loveingsdao = new Loveings().dao();

    @Inject
    Doc docdap = new Doc().dao();

    @Inject
    Userct userct = new Userct().dao();

    final String REF_TYPE_PROJECT = "doc";
    final String REF_TYPE_SHARE = "userct";
    final String REF_TYPE_FEEDBACK = "feedback";

    // 用户前端传入非法参数引发安全问题
    @SuppressWarnings("serial")
    private final Set<String> permissionTables = new HashSet<String>() {{
        add(REF_TYPE_PROJECT);
        add(REF_TYPE_SHARE);
        add(REF_TYPE_FEEDBACK);
    }};

    private void check(String refType) {
        if (!permissionTables.contains(refType)) {
            throw new IllegalArgumentException("refType 不正确");
        }
    }

    /**
     * 点赞
     *
     * @param myId    点赞的用户 id，即当前登录用户
     * @param refType 被点赞的表名
     * @param refId   被点赞的表名中的相应的 id 值
     * @param isAdd   1 为点赞，2 为取消点赞，null 需要判断是否已被点赞
     */
    public Ret like(int myId, String refType, int refId, int isAdd) {
        check(refType);
        if (isAdd == 1) {
            return save(myId, refType, refId);
        } else if (isAdd == 2) {
            return delete(myId, refType, refId);
        }
        return Ret.ok("msg", "点赞失败");
    }

    private Ret like(int myId, String refType, int refId) {
        if (isLike(myId, refType, refId)) {
            return delete(myId, refType, refId);
        } else {
            return save(myId, refType, refId);
        }
    }

    // 获取被点赞资源的创建者
    private Loveings getUserIdOfRef(int usersid, String refType, int refId) {
        return loveingsdao.findFirst("select * from loveings where type = '" + refType + "' and usersid = ? and objid= ? limit 1", usersid, refId);
    }

    /**
     * @return
     * @Author Cc
     * @Description //TODO 判断是否给自己点赞
     * @Date 2020/3/21
     * @Param
     **/
    private Boolean isUsersLoveing(int usersid, String refType, int refId) {
        Object o = Db.queryFirst("select * from " + refType + " where id = ? and usersid = ?", refId, usersid);
        if (o != null) {
            return true;
        } else {
            return false;
        }
    }

    Boolean isLoveings(int usersid, int ids, String refType) {
        Object o = Db.queryFirst("select * from loveings where type = ? and objid = ? and usersid = ? limit 1", refType, ids, usersid);
        if (o != null) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 点赞
     */
    private Ret save(final int myId, final String refType, final int refId) {
        final Loveings loveings = getUserIdOfRef(myId, refType, refId);
        int n = 0;
        if (loveings == null) {
            n = Db.update("insert into loveings(usersid, objid,type,likecount, addtime) value(?,?,?,?,?)", myId, refId, refType, 1, new Date());
        } else {
            if (isUsersLoveing(myId, refType, refId)) {
                return Ret.fail("msg", "不能给自己点赞");
            } else {
                n = Db.update("update loveings set likecount=likecount+1 where id=? limit 1", loveings.getId());
            }
        }
        if (n > 0) {
            n = Db.update("update " + refType + " set loveing=loveing+1 where id=? limit 1", refId);
        }
        return n > 0 ? Ret.ok() : Ret.fail("msg", "点赞失败");
    }

    /**
     * 取消点赞
     */
    private Ret delete(final int myId, final String refType, final int refId) {
        Loveings first = loveingsdao.findFirst("select * from loveings where usersid = ? and  objid = ? and type = ?", myId, refId, refType);
        int update = 0;
        if (first != null) {
            if (first.getLikecount() > 0) {
                update = Db.delete("delete from loveings where id= ? ", first.getId());
            }
            if (update > 0) {
                update = Db.update("update " + refType + " set loveing=loveing-1 where id=? limit 1", refId);
            }
        }
        return update > 0 ? Ret.ok() : Ret.fail("msg", "取消点赞失败");
    }

    /**
     * 对 refType + refId 指向的资源，是否已点赞
     */
    public boolean isLike(int accountId, String refType, int refId) {
        String sql = "select accountId from " + refType + "_like where accountId=? and refId=? limit 1";
        return Db.queryInt(sql, accountId, refId) != null;
    }

    /**
     * 设置 article detail 页面的点赞状态
     */
    @SuppressWarnings("rawtypes")
    public void setLikeStatus(Account loginAccount, String refType, Model refObj, Ret ret) {
        if (loginAccount != null) {
            boolean isLike = isLike(loginAccount.getId(), refType, refObj.getInt("id"));
            ret.set("isLikeActive", isLike ? "active" : "");
            ret.set("isLikeAdd", isLike ? "false" : "true");
        } else {
            ret.set("isLikeActive", "");
            ret.set("isLikeAdd", "true");
        }
        int likeCount = refObj.getInt("likeCount");
        ret.set("likeCount", likeCount > 0 ? likeCount : "");
    }

    /**
     * 删除被引用的资源时，要删除相关的点赞记录
     */
    private void deleteByRefDeleted(String refType, int refId) {
        Db.update("delete from " + refType + "_like where refId=?", refId);
    }

    /**
     * 删除 project 时，要删除相关的点赞记录
     */
    public void deleteByProjectDeleted(int refId) {
        deleteByRefDeleted(this.REF_TYPE_PROJECT, refId);
    }

    /**
     * 删除 share 时，要删除相关的点赞记录
     */
    public void deleteByShareDeleted(int refId) {
        deleteByRefDeleted(this.REF_TYPE_SHARE, refId);
    }

    /**
     * 删除 feedback 时，要删除相关的点赞记录
     */
    public void deleteByFeedbackDeleted(int refId) {
        deleteByRefDeleted(this.REF_TYPE_FEEDBACK, refId);
    }
}

