package com.sdtool.webcore.websocket;

import com.sdtool.common.api.LoginUserService;
import com.sdtool.common.api.SystemService;
import com.sdtool.common.entity.site.ERPMessageKind;
import com.sdtool.common.entity.site.ERPNoticeMessage;
import com.sdtool.common.entity.system.LoginUser;
import com.sweetfish.net.http.*;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;

/**
 * Created by jlutt on 2020-09-28
 *
 * @author jlutt
 */
@RestWebSocket(name = "aws", catalog = "ws", comment = "长链接服务", single = false, anyuser = true)
public class ERPWebSocket extends WebSocket<String, Object> {

    private class WebSocketUser {
        private long loginId;

        private long supplierCode;

        private String dataSourceId;

        public WebSocketUser() {
        }

        public WebSocketUser(String webUserId) {
            String[] splits = webUserId.split("_");
            this.loginId = Long.parseLong(splits[0]);
            this.supplierCode = Long.parseLong(splits[1]);
            this.dataSourceId = splits[2];
        }

        public long getLoginId() {
            return loginId;
        }

        public void setLoginId(long loginId) {
            this.loginId = loginId;
        }

        public long getSupplierCode() {
            return supplierCode;
        }

        public void setSupplierCode(long supplierCode) {
            this.supplierCode = supplierCode;
        }

        public String getDataSourceId() {
            return dataSourceId;
        }

        public void setDataSourceId(String dataSourceId) {
            this.dataSourceId = dataSourceId;
        }
    }

    @Resource
    public SystemService systemService;

    @Resource
    public LoginUserService loginUserService;

    private String socketSessionId;

    @Override
    protected CompletableFuture<String> onOpen(HttpRequest request) {
        getLogger().info(getRemoteAddr());
        try {
            long loginId = request.getLongParameter("loginId", 0L);
            long supplierCode = request.getLongParameter("supplierCode", 0L);
            String dataSourceId = request.getParameter("dataSourceId");

            if (loginId <= 0) {
                return send("{\"LoginFailMessage\":" + "\"登录失败未传入有效loginId\"" + "}").thenApply(x -> null);
            }

            if (supplierCode <= 0) {
                return send("{\"LoginFailMessage\":" + "\"登录失败未传入有效supplierCode\"" + "}").thenApply(x -> null);
            }

            if (StringUtils.isBlank(dataSourceId)) {
                return send("{\"LoginFailMessage\":" + "\"登录失败未传入有效dataSourceId\"" + "}").thenApply(x -> null);
            }

            LoginUser tmpUser = loginUserService.getRedisLoginUser(loginId, supplierCode);
            if (tmpUser == null) {
                return send("{\"LoginFailMessage\":" + "\"登录失败无效的用户\"" + "}").thenApply(x -> null);
            }

            socketSessionId = request.getSessionid(true);

            tmpUser.setLoginIpAddr(getRemoteAddr());
            systemService.writeOnlineUser(tmpUser, socketSessionId, dataSourceId, supplierCode);

            return super.onOpen(request);
        } catch (NumberFormatException e) {
            return send("{\"LoginFailMessage\":" + "\"登录失败无效的用户\"" + "}").thenApply(x -> null);
        }
    }

    /**
     * 关闭的回调方法，调用此方法时WebSocket已经被关闭
     *
     * @param code   结果码，非0表示非正常关闭
     * @param reason 关闭原因
     */
    @Override
    public CompletableFuture onClose(int code, String reason) {
        getLogger().info(getUserid() + ":" + getRemoteAddr() + " close");
        WebSocketUser socketUser = new WebSocketUser(getUserid());
        systemService.deleteOnlineUser(socketUser.getLoginId(), socketSessionId, socketUser.getDataSourceId(), socketUser.getSupplierCode());
        return null;

//        super.onClose(code, reason);
    }

    /**
     * 用户id，
     * 此处用户id由userId:supplierCode:dataSourceId组成，避免多数据源情况下id重复
     *
     * @param request http请求
     * @return
     */
    @Override
    protected CompletableFuture<String> createUserid(HttpRequest request) {
        long loginId = request.getLongParameter("loginId", 0L);
        long supplierCode = request.getLongParameter("supplierCode", 0L);
        String dataSourceId = request.getParameter("dataSourceId");

        if (loginId <= 0) {
            return null;
        }

        if (supplierCode <= 0) {
            return null;
        }

        if (StringUtils.isBlank(dataSourceId)) {
            return null;
        }

        LoginUser tmpUser = loginUserService.getRedisLoginUser(loginId, supplierCode);
        if (tmpUser == null) {
            return null;
        }

        return CompletableFuture.completedFuture(loginId + "_" + supplierCode + "_" + dataSourceId);
    }

    /**
     * WebSocket.broadcastMessage时的过滤条件
     *
     * @param wsrange 过滤条件
     * @return boolean
     */
    @Override
    protected boolean predicate(WebSocketRange wsrange) {
        return getUserid().endsWith(wsrange.getWskey());
    }

    @RestOnMessage(name = "restPing", comment = "心跳")
    public void restPing(String ping) {
//        getLogger().info(getRemoteAddr() + "ping");
        send(new ERPNoticeMessage(String.valueOf(ERPMessageKind.PONG), "PONG"));
    }

    @RestOnMessage(name = "restSubscribeMessage", comment = "消息订阅")
    public void restSubscribeMessage(String messageGroups) {

    }
}
