package com.liquidnet.service.platform.service.impl.adam.dm;

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.SensitizeUtil;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.vo.*;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service("adamRdmService")
public class DMRdmService {
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    RedisUtil redisUtil;

    public void setSwitch(String rk, int val) {
        redisUtil.set(rk, val);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | Switch config */

    public Integer getSwitch(String rk) {
        Integer i = (Integer) redisUtil.get(rk);
        return null == i ? 1 : i;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | Loader meta-fil */

    public List<String> getNknameList() {
        ArrayList<String> list = (ArrayList<String>) redisUtil.get(AdamRedisConst.INFO_LIBRARY_NKNAME);
        if (CollectionUtils.isEmpty(list)) {
            InputStream inputStream = null;
            InputStreamReader inputStreamReader = null;
            BufferedReader bufferedReader = null;
            try {
                inputStream = this.getClass().getClassLoader().getResourceAsStream("META-FIL/library_nickname.csv");
                inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                bufferedReader = new BufferedReader(inputStreamReader);

                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    int l = org.apache.commons.lang3.StringUtils.length(line);
                    if (l == 0) {
                        break;
                    }
                    if (l > 11) {
                        line = line.substring(0, 11);
                    }
                    list.add(line);
                }
            } catch (IOException e) {
                log.error("Read CSV[library_nickname.csv] failure.", e);
            } finally {
                try {
                    if (null != bufferedReader) bufferedReader.close();
                    if (null != inputStreamReader) inputStreamReader.close();
                    if (null != inputStream) inputStream.close();
                } catch (IOException e) {
                    log.error("Close stream failure.", e);
                }
            }

            if (!CollectionUtils.isEmpty(list)) redisUtil.set(AdamRedisConst.INFO_LIBRARY_NKNAME, list);
        }
        return list;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <Mobile｜OPENID, UID> */

    public boolean setUidByMobile(String mobile, String uid) {
        return redisUtil.set(AdamRedisConst.IDENTITY_MOBILE.concat(mobile), uid);
    }

    public String getUidByMobile(String mobile) {
        String key = AdamRedisConst.IDENTITY_MOBILE.concat(mobile);
        long s = System.currentTimeMillis();
        String val = (String) redisUtil.get(key);
        if (StringUtils.isEmpty(val)) {
            Query query = Query.query(Criteria.where("mobile").is(mobile).and("state").is(1));
            query.fields().include("uid");
            s = System.currentTimeMillis();
            AdamUserInfoVo vo = mongoTemplate.findOne(query, AdamUserInfoVo.class, AdamUserInfoVo.class.getSimpleName());
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);
            if (null != vo) {
                val = vo.getUid();
                redisUtil.set(key, vo.getUid());
            }
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return val;
    }

    public void delUidByMobile(String mobile) {
        redisUtil.del(AdamRedisConst.IDENTITY_MOBILE.concat(mobile));
    }

    public boolean setUidByPlatformOpenId(String platform, String openId, String uid) {
        return redisUtil.set(AdamRedisConst.IDENTITY_THIRD_PARTY + platform + ":" + openId, uid);
    }

    public String getUidByPlatformOpenId(String platform, String openId) {
        String key = AdamRedisConst.IDENTITY_THIRD_PARTY + platform + ":" + openId;
        long s = System.currentTimeMillis();
        String val = (String) redisUtil.get(key);
        if (StringUtils.isEmpty(val)) {
            Query query = Query.query(Criteria.where("openId").is(openId).and("platform").is(platform).and("state").is(1));
            query.fields().include("uid");
            s = System.currentTimeMillis();
            AdamThirdPartInfoVo vo = mongoTemplate.findOne(query, AdamThirdPartInfoVo.class, AdamThirdPartInfoVo.class.getSimpleName());
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);
            if (null != vo) {
                val = vo.getUid();
                redisUtil.set(key, vo.getUid());
            }
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return val;
    }

    public void delUidByPlatformOpenId(String platform, String openId) {
        redisUtil.del(AdamRedisConst.IDENTITY_THIRD_PARTY + platform + ":" + openId);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <UID, USER_INFO> */

    public boolean setUserInfoVoByUid(String uid, AdamUserInfoVo vo) {
        return redisUtil.set(AdamRedisConst.INFO_USER.concat(uid), vo);
    }

    public AdamUserInfoVo getUserInfoVoByUid(String uid) {
        String rk = AdamRedisConst.INFO_USER.concat(uid);
        long s = System.currentTimeMillis();
        AdamUserInfoVo vo = (AdamUserInfoVo) redisUtil.get(rk);
        if (null == vo) {
            s = System.currentTimeMillis();
            vo = mongoTemplate.findOne(Query.query(Criteria.where("uid").is(uid).and("state").is(1)),
                    AdamUserInfoVo.class, AdamUserInfoVo.class.getSimpleName());
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (null != vo) redisUtil.set(rk, vo);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    public void delUserInfoVoByUid(String uid) {
        redisUtil.del(AdamRedisConst.INFO_USER.concat(uid));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <UID, REAL_INFO> */

    public boolean setRealInfoVoByUid(String uid, AdamRealInfoVo vo) {
        return redisUtil.set(AdamRedisConst.INFO_REAL_NAME.concat(uid), vo);
    }

    public AdamRealInfoVo getRealInfoVoByUid(String uid) {
        String rk = AdamRedisConst.INFO_REAL_NAME.concat(uid);
        long s = System.currentTimeMillis();
        AdamRealInfoVo vo = (AdamRealInfoVo) redisUtil.get(rk);
        if (null == vo) {
            s = System.currentTimeMillis();
            vo = mongoTemplate.findOne(Query.query(Criteria.where("uid").is(uid).and("state").is(1)),
                    AdamRealInfoVo.class, AdamRealInfoVo.class.getSimpleName());
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (null != vo) redisUtil.set(rk, vo);
        }
        if (null != vo) {
            vo.setName(SensitizeUtil.chineseName(vo.getName()));
            vo.setIdCard(SensitizeUtil.custom(vo.getIdCard(), 3, 2));
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <ID_TYPE+ID_NO, ID_NAME> */

    public boolean setCertification(int idType, String idNo, String idName) {
        return redisUtil.set(AdamRedisConst.INFO_CERTIFICATION + idType + idNo, idName);
    }

    public boolean isCertification(int idType, String idNo, String idName) {
        String o = (String) redisUtil.get(AdamRedisConst.INFO_CERTIFICATION + idType + idNo);
        return !StringUtils.isEmpty(o) && o.equals(idName);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <UID, List<AdamThirdPartInfoVo>> */

    public boolean setThirdPartVoListByUid(String uid, List<AdamThirdPartInfoVo> voList) {
        return redisUtil.set(AdamRedisConst.INFO_THIRD_PARTY.concat(uid), voList);
    }

    public List<AdamThirdPartInfoVo> getThirdPartVoListByUid(String uid) {
        String rk = AdamRedisConst.INFO_THIRD_PARTY.concat(uid);
        long s = System.currentTimeMillis();
        List<AdamThirdPartInfoVo> thirdPartInfoVos = (List<AdamThirdPartInfoVo>) redisUtil.get(rk);
        if (CollectionUtils.isEmpty(thirdPartInfoVos)) {
            s = System.currentTimeMillis();
            thirdPartInfoVos = mongoTemplate.find(Query.query(Criteria.where("uid").is(uid).and("state").is(1)),
                    AdamThirdPartInfoVo.class, AdamThirdPartInfoVo.class.getSimpleName());
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (!CollectionUtils.isEmpty(thirdPartInfoVos)) redisUtil.set(rk, thirdPartInfoVos);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return thirdPartInfoVos;
    }

    public AdamThirdPartInfoVo getThirdPartVoByUidPlatform(String uid, String platform) {
        List<AdamThirdPartInfoVo> vos = this.getThirdPartVoListByUid(uid);
        if (!CollectionUtils.isEmpty(vos)) {
//            for (AdamThirdPartInfoVo r : vos)
//                if (platform.equals(r.getPlatform())) return r;
            Optional<AdamThirdPartInfoVo> any = vos.stream().filter(r -> r.getPlatform().equals(platform)).findAny();
            if (any.isPresent()) {
                return any.get();
            }
        }
        return null;
    }

    public void delThirdPartVoListByUid(String uid) {
        redisUtil.del(AdamRedisConst.INFO_THIRD_PARTY.concat(uid));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <UID, List<AdamEntersVo>> */

    public boolean setEntersVoByUid(String uid, List<AdamEntersVo> list) {
        return redisUtil.set(AdamRedisConst.INFO_ENTERS.concat(uid), list);
    }

    public List<AdamEntersVo> getEntersVoByUid(String uid) {
        String rk = AdamRedisConst.INFO_ENTERS.concat(uid);
        long s = System.currentTimeMillis();
        List<AdamEntersVo> vos = (List<AdamEntersVo>) redisUtil.get(rk);
        if (CollectionUtils.isEmpty(vos)) {
            s = System.currentTimeMillis();
            vos = mongoTemplate.find(
                    Query.query(Criteria.where("uid").is(uid).and("state").is(1)).with(Sort.by(Sort.Direction.DESC, "createdAt")),
                    AdamEntersVo.class, AdamEntersVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (!CollectionUtils.isEmpty(vos)) redisUtil.set(rk, vos);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vos;
    }

    public AdamEntersVo getEntersVoByUidEntersId(String uid, String entersId) {
        return this.getEntersVoByUid(uid).stream().filter(r -> r.getEntersId().equals(entersId)).findAny().orElse(null);
    }

    public List<AdamEntersVo> getEntersVoByUidEntersIds(String uid, String... entersIds) {
        List<String> entersIdList = Arrays.asList(entersIds);
        return this.getEntersVoByUid(uid).stream().filter(r -> entersIdList.contains(r.getEntersId())).collect(Collectors.toList());
    }

    public void delEntersVoByUid(String uid) {
        redisUtil.del(AdamRedisConst.INFO_ENTERS.concat(uid));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <UID, List<AdamAddressesVo>> */

    public boolean setAddressesVoByUid(String uid, List<AdamAddressesVo> list) {
        return redisUtil.set(AdamRedisConst.INFO_ADDRESSES.concat(uid), list);
    }

    public List<AdamAddressesVo> getAddressesVoByUid(String uid) {
        String rk = AdamRedisConst.INFO_ADDRESSES.concat(uid);
        long s = System.currentTimeMillis();
        List<AdamAddressesVo> vos = (List<AdamAddressesVo>) redisUtil.get(rk);
        if (CollectionUtils.isEmpty(vos)) {
            s = System.currentTimeMillis();
            vos = mongoTemplate.find(
                    Query.query(Criteria.where("uid").is(uid).and("state").is(1)).with(Sort.by(Sort.Direction.DESC, "createdAt")),
                    AdamAddressesVo.class, AdamAddressesVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (!CollectionUtils.isEmpty(vos)) redisUtil.set(rk, vos);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vos;
    }

    public AdamAddressesVo getAddressesVoByUidAddressesId(String uid, String addressesId) {
        return this.getAddressesVoByUid(uid).stream().filter(r -> r.getAddressesId().equals(addressesId)).findAny().orElse(null);
    }

    public void delAddressesVoByUid(String uid) {
        redisUtil.del(AdamRedisConst.INFO_ADDRESSES.concat(uid));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | List<购买会员黑名单UID> */

    public boolean setBlacklistForMember(List<String> uids) {
        return redisUtil.set(AdamRedisConst.BLK_LIST_MEMBER_UID, uids);
    }

    public List<String> getBlacklistForMember() {
        return (List<String>) redisUtil.get(AdamRedisConst.BLK_LIST_MEMBER_UID);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <UID, USER_MEMBER> */

    public boolean setUserMemberVoByUid(String uid, AdamUserMemberVo vo) {
        return redisUtil.set(AdamRedisConst.INFO_USER_MEMBER.concat(uid), vo);
    }

    public AdamUserMemberVo getUserMemberVoByUid(String uid) {
        String rk = AdamRedisConst.INFO_USER_MEMBER.concat(uid);
        long s = System.currentTimeMillis();
        AdamUserMemberVo vo = (AdamUserMemberVo) redisUtil.get(rk);
        if (null == vo) {
            s = System.currentTimeMillis();
            vo = mongoTemplate.findOne(Query.query(Criteria.where("uid").is(uid)), AdamUserMemberVo.class, AdamUserMemberVo.class.getSimpleName());
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (null != vo) redisUtil.set(rk, vo);
        }
        if (null != vo) {
            vo.setState(vo.getState() == 1 ? (vo.getExpiryAt().isAfter(LocalDateTime.now()) ? 1 : 2) : vo.getState());
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    public void delUserMemberVoByUid(String uid) {
        redisUtil.del(AdamRedisConst.INFO_USER_MEMBER.concat(uid));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <MEMBER_SIMPLE_INFO> */

    public AdamMemberSimpleVo getMemberSimpleVo() {
        AdamMemberSimpleVo vo = (AdamMemberSimpleVo) redisUtil.get(AdamRedisConst.INFO_MEMBER_SIMPLE);
        if (null == vo) {
            long s = System.currentTimeMillis();
            List<AdamMemberSimpleVo> vos = mongoTemplate.find(
                    Query.query(Criteria.where("state").is(1)).with(Sort.by(Sort.Direction.ASC, "memberId")),
                    AdamMemberSimpleVo.class, AdamMemberVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            vo = CollectionUtils.isEmpty(vos) ? null : vos.get(0);

            if (null != vo) redisUtil.set(AdamRedisConst.INFO_MEMBER_SIMPLE, vo);
        }
        return vo;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <MEMBER_ID, MEMBER_INFO> */

    public boolean setMemberVoByMemberId(String memberId, AdamMemberVo vo) {
        return redisUtil.set(AdamRedisConst.INFO_MEMBER_CATEGORY.concat(memberId), vo);
    }

    public AdamMemberVo getMemberVoByMemberId(String memberId) {
        String key = AdamRedisConst.INFO_MEMBER_CATEGORY.concat(memberId);
        long s = System.currentTimeMillis();
        AdamMemberVo vo = (AdamMemberVo) redisUtil.get(key);
        if (null == vo) {
            s = System.currentTimeMillis();
            vo = mongoTemplate.findOne(
                    Query.query(Criteria.where("memberId").is(memberId).and("state").is(1)),
                    AdamMemberVo.class, AdamMemberVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);
            if (null != vo) redisUtil.set(key, vo);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    public void delMemberVoByMemberId(String memberId) {
        redisUtil.del(AdamRedisConst.INFO_MEMBER_CATEGORY.concat(memberId));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <MEMBER_ID, List<AdamMemberPriceVo>> */

    public boolean setMemberPriceVoByMemberId(String memberId, List<AdamMemberPriceVo> vos) {
        return redisUtil.set(AdamRedisConst.INFO_MEMBER_PRICE.concat(memberId), vos);
    }

    public List<AdamMemberPriceVo> getMemberPriceVoByMemberId(String memberId) {
        String key = AdamRedisConst.INFO_MEMBER_PRICE.concat(memberId);
        long s = System.currentTimeMillis();
        List<AdamMemberPriceVo> vos = (List<AdamMemberPriceVo>) redisUtil.get(key);
        if (CollectionUtils.isEmpty(vos)) {
            s = System.currentTimeMillis();
            vos = mongoTemplate.find(
                    Query.query(Criteria.where("memberId").is(memberId).and("state").is(1)),
                    AdamMemberPriceVo.class, AdamMemberPriceVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (!CollectionUtils.isEmpty(vos)) redisUtil.set(key, vos);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vos;
    }

    public AdamMemberPriceVo getMemberPriceVoByPriceId(String memberId, String memberPriceId) {
        long s = System.currentTimeMillis();
        List<AdamMemberPriceVo> vos = this.getMemberPriceVoByMemberId(memberId);
        if (!CollectionUtils.isEmpty(vos)) {
//            for (AdamMemberPriceVo r : vos) {
//                if (memberPriceId.equals(r.getMemberPriceId())) {
//                    return r;
//                }
//            }
            Optional<AdamMemberPriceVo> any = vos.stream().filter(r -> r.getMemberPriceId().equals(memberPriceId)).findAny();
            if (any.isPresent()) {
                return any.get();
            }
        }
        return null;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <MEMBER_ID, List<AdamMemberRightsVo>> */

    public boolean setMemberRightsVoByMemberId(String memberId, List<AdamMemberRightsVo> vos) {
        return redisUtil.set(AdamRedisConst.INFO_MEMBER_RIGHTS.concat(memberId), vos);
    }

    public List<AdamMemberRightsVo> getMemberRightsVoByMemberId(String memberId) {
        List<AdamMemberRightsVo> vos = (List<AdamMemberRightsVo>) redisUtil.get(AdamRedisConst.INFO_MEMBER_RIGHTS.concat(memberId));
        if (CollectionUtils.isEmpty(vos)) {
            vos = Arrays.asList(AdamMemberRightsVo.getNew().setName("专属").setSort(1)
                            .setCover("https://img.zhengzai.tv/files/2020/08/28/5f490c4477d72.png"),
                    AdamMemberRightsVo.getNew().setName("优惠").setSort(2)
                            .setCover("https://img.zhengzai.tv/files/2020/08/28/5f490c685e7a8.png"),
                    AdamMemberRightsVo.getNew().setName("优先").setSort(3)
                            .setCover("https://img.zhengzai.tv/files/2020/08/28/5f490c726a750.png"),
                    AdamMemberRightsVo.getNew().setName("专属").setSort(4)
                            .setCover("https://img.zhengzai.tv/files/2020/08/28/5f490c5de2870.png")
            );

            redisUtil.set(AdamRedisConst.INFO_MEMBER_RIGHTS.concat(memberId), vos);
        }
        return vos;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | MEMBER_AGREEMENT */

    public String getMemberAgreement() {
        String val = (String) redisUtil.get(AdamRedisConst.INFO_MEMBER_AGREEMENT);
        if (StringUtils.isEmpty(val)) {
            val = "<p style=\"text-align: center;\"><span class=\"ql-size-large\">摩登天空登登登会员服务协议</span></p><p style=\"text-align: center;\"><br></p><p style=\"text-align: center;\">本版本更新时间：2021年1月26日&nbsp;</p><p style=\"text-align: right;\">&nbsp;</p><p style=\"text-align: justify;\">一 、接受协议</p><p style=\"text-align: justify;\">1.1一旦您注册成为摩登天空登登登会员用户，便表示您（以下简称“用户”）已经完全理解并同意接受本协议（以下简称“协议”）。</p><p style=\"text-align: justify;\">1.2在您接受本协议之后，本协议可能因国家政策、产品与/或服务以及履行本协议的环境发生变化而进行修改，一旦本协议内容发生变更的，本网站将在相应页面、站内信或以其他合理方式进行通知，请您仔细阅读。如您在本协议更新后继续使用摩登天空登登登会员服务，即表示您已充分阅读、理解并接受更新后的本协议并愿意接受更新后的协议约束。如果您不同意变更的内容，您可以选择停止使用摩登天空登登登会员服务。更新后的协议自发布之日起生效。</p><p style=\"text-align: justify;\">1.3若您是未成年人，请您在监护人监护、指导下阅读并决定是否同意本协议。未成年人行使和履行本协议项下的权利和义务视为已获得了监护人的认可。</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">二、服务内容</p><p style=\"text-align: justify;\">2.1摩登天空登登登会员是指完成了成为会员的所有程序，且在遵守本协议的前提下，在会员时长有效期内享受摩登天空提供的登登登会员服务的自然人。</p><p style=\"text-align: justify;\"><strong>2.2 摩登天空有权根据法律法规及政策变更，合作方要求以及自身运营策略变更对登登登会员服务内容（包括但不限于登登登会员权益细则，收费标准和收费方式）进行部分或全部变更。就前述变更，本网站将在相应页面、站内信或以其他合理方式进行发布，发布之后立即生效。如果您不同意变更的内容，您可以选择停止使用摩登天空登登登会员服务。</strong></p><p style=\"text-align: justify;\">2.3摩登天空登登登会员服务协议是《正在现场注册协议》以及《正在现场隐私权保护协议》的补充协议。</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">三、会员账号及权益</p><p style=\"text-align: justify;\">3.1在用户的登登登会员服务有效期内，用户在本网站所使用的账号即为用户的登登登会员账号。用户有责任维持自己所注册的账号和密码的安全，用户应对所有使用本人的密码及账号的活动负完全责任。用户同意：(a) 本人的密码或账号遭到未获授权的使用。或者发生其他任何安全问题时，请立即通知本网站，且（b）每次上网完毕都会把本人的账号关掉。<strong>如未能依前述规定行事，对于任何人利用该密码及账号所进行的任何行为，用户应负完全的责任。对于因此而产生的任何损失或损害，本网站无法也不承担任何责任。 根据有关法律法规，本网站在此郑重提请用户注意，任何经由我们的服务以上载、张贴、发送电子邮件或其他任何方式传送的资讯、资料、文字、软件、音乐、音讯、照片、图形、视讯、信息或其它资料（以下简称“内容”），无论系公开还是私下传送，均由内容提供者、上传者承担责任。本网站无法控制经由我们的服务传送之内容，因此不保证内容的正确性、完整性或品质。 如用户已预知使用我们的服务时，可能会接触到令人不适之内容，在任何情况下，本网站均不为此负责。包含但不限于任何内容之任何错误或遗漏，以及经由我们的服务及张贴、发送电子邮件或其它方式传送任何内容而衍生之任何损失或损害。本网站有权依法停止传输任何前述内容并采取相应行动，包含但不限于暂停用户使用我们的服务的全部或部分，保持有关记录，并向有关机关报备。</strong></p><p style=\"text-align: justify;\">3.2 登登登会员权益:</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;摩登天空登登登会员权益包括：</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.超过百场演出优先购票权、入场权及专属通道*</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.会员专属纪念品礼盒</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.会员独享限定款商品及音像制品的购买权利（专属商品上线）</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.超过百款商品的会员优惠价</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.会员专属的演出以及线上线下活动</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6.会员专属的视频音频节目</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7.想不到的惊喜</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8.免费观演以及免费商品的抽奖权利。</p><p>•&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>（具体享有会员权益的演出场次和商品以本网站指定为准）</strong></p><p style=\"text-align: justify;\"><strong>本网站可能会根据法律法规及政策变更、版权状态变化、自身运营策略对前述会员权益作出部分修改。</strong></p><p style=\"text-align: justify;\">3.3 登登登会员服务期限及延期：</p><p style=\"text-align: justify;\"><strong>用户的登登登会员服务的服务期限自用户成为登登登会员之时起算，以用户自行选择并支付相应会员费用对应的服务期限为准，用户可以通过登录本网站会员中心免费查询。该期限不因您未使用等情况而延长。当会员服务期限到期后，本网站将停止继续向您提供登登登会员服务；但如您开通自动续费服务且您在服务期限到期前续费成功的，会员服务期限将在原服务期限的基础上顺延。</strong></p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">四、隐私保护</p><p style=\"text-align: justify;\">4.1 本网站保证不对外公开或向第三方提供单个用户的注册资料及用户在使用网络服务时存储在本网站的非公开内容，但下列情况除外：</p><p style=\"text-align: justify;\">4.1.1事先获得用户的明确授权；</p><p style=\"text-align: justify;\">4.1.2根据有关的法律法规要求；</p><p style=\"text-align: justify;\">4.1.3按照相关政府主管部门的要求；</p><p style=\"text-align: justify;\">4.1.4为维护社会公众的利益；</p><p style=\"text-align: justify;\">4.1.5为维护本网站的合法权益；</p><p style=\"text-align: justify;\">4.1.6其他需要公开、编辑或透露个人信息的情况。</p><p style=\"text-align: justify;\"><strong>4.2 本网站可能会与第三方合作向用户提供相关的网络服务，在此情况下，如第三方同意承担与本网站同等的保护用户隐私的责任，则本网站有权将用户的注册资料等提供给该第三方。</strong></p><p style=\"text-align: justify;\"><strong>4.3 在不透露单个用户隐私资料的前提下，本网站有权对整个用户数据库进行分析并对用户数据库进行商业上的利用。</strong></p><p style=\"text-align: justify;\">&nbsp;</p><p>五、服务终止</p><p>本网站终止摩登天空登登登会员服务包括但不限于如下情况：</p><p>1. 用户自主提出的</p><p>2. 用户利用会员身份获得/购得的音乐节以及场馆演出类门票或商城商品，不得转让、代拍。如果私自转让或代拍，一经本网站发现，本网站有权取消该用户的会员资格且该用户利用会员身份进行转票/代拍所获得/购得的音乐节以及场馆演出类门票视为无效（本网站有权视具体情况要求该用户寄回或直接作废），同时清算该用户的使用权益并退回差价。会员权益计价按如下标准执行：</p><p>&nbsp;</p><p>1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;优先购票权、入场权及专属通道按照50元/次计价</p><p>2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会员专属纪念品礼盒按照100元计价</p><p>3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会员专属优惠商品的会员优惠价按照实际优惠价格计算</p><p>4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会员专属的演出以及线上线下活动，已经观看的按照50元/次计价</p><p>5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;抽取到会员免费观演以及免费商品的按照实际演出和商品的价格计算</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">l&nbsp;用户存在或本网站独立判断用户存在任何违反国家法律法规或监管政策的行为</p><p style=\"text-align: justify;\">l&nbsp;根据法律法规、政策规定、维护账号与系统安全等紧急情况以及不可抗力因素等其他本网站无法抗拒的情况</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">六、通知送达</p><p style=\"text-align: justify;\">6.1本网站对于摩登天空登登登用户所有的通知均可通过网页公告、电子邮件、手机短信或其他常规的信件传送等方式进行；该等通知于发送之日视为已送达收件人。</p><p style=\"text-align: justify;\">6.2用户对于本网站的通知应当通过本网站对外正式公布的通信地址、传真号码、电子邮件等联系信息进行送达。</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">七、责权限制</p><p style=\"text-align: justify;\">用户明确了解并同意，基于以下原因造成的包括但不限于利益、信誉、应用、数据损失或其它无形损失，本网站不承担任何直接、间接、附带、特别、衍生性或惩罚性赔偿责任（即使本网站事先已被告知发生此种赔偿之可能性亦然）： （i）我们的服务之使用或无法使用，（ii）为替换从或通过我们的服务购买或取得之任何商品、数据、信息、服务、收到的讯息，或缔结之交易而发生的成本，（iii）用户的传输数据遭到未获授权的存取或编造，（iv）任何第三方在我们的服务中所做之声明或行为；或（v）与我们的服务相关的其它事宜，但本协议有明确规定的除外。</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">八、法律管辖与适用</p><p style=\"text-align: justify;\">8.1 本服务协议的生效、履行、解释及争议的解决均适用于中华人民共和国法律。</p><p style=\"text-align: justify;\">8.2 如本协议内容或其执行发生任何争议，应尽量友好协商解决；协商不成时，您同意将争议提交至北京市朝阳区人民法院诉讼解决。双方同意，解决争议时，应以您同意的最新《摩登天空登登登会员服务协议》为准。</p><p style=\"text-align: justify;\">&nbsp;</p><p style=\"text-align: justify;\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;北京正在映画互联网科技有限公司</p><p style=\"text-align: justify;\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2021年1月26日</p><p style=\"text-align: justify;\">&nbsp;</p>";

            redisUtil.set(AdamRedisConst.INFO_MEMBER_AGREEMENT, val);
        }
        return val;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <ORDER_NO, MEMBER_ORDER_INFO> */

    public boolean setShotMemberOrderVoByOrderNo(String orderNo, AdamMemberOrderVo vo) {
        return redisUtil.set(AdamRedisConst.SHOT_MEMBER_ORDER + orderNo, vo);
    }

    public AdamMemberOrderVo getShotMemberOrderVoByOrderNo(String orderNo) {
        String key = AdamRedisConst.SHOT_MEMBER_ORDER + orderNo;
        long s = System.currentTimeMillis();
        AdamMemberOrderVo vo = (AdamMemberOrderVo) redisUtil.get(key);
        if (null == vo) {
            s = System.currentTimeMillis();
            vo = mongoTemplate.findOne(
                    Query.query(Criteria.where("orderNo").is(orderNo)),
                    AdamMemberOrderVo.class, AdamMemberOrderVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);

            if (null != vo) redisUtil.set(key, vo);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    public void delShotMemberOrderVoByOrderNo(String orderNo) {
        redisUtil.del(AdamRedisConst.SHOT_MEMBER_ORDER + orderNo);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | INCR_MEMBER_NO */

    public boolean setMaxMemberNo(int val) {
        return redisUtil.set(AdamRedisConst.INCR_MEMBER_NO, val);
    }

    public int incrMemberNo() {
        return (int) redisUtil.incr(AdamRedisConst.INCR_MEMBER_NO, 1);
    }

    public int getMaxMemberNo() {
        Object o = redisUtil.get(AdamRedisConst.INCR_MEMBER_NO);
        return null == o ? -1 : (int) o;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | <MEMBER_CODE, MEMBER_CODE_INFO> */

    public boolean setMemberCodeVoByCode(String memberCode, AdamMemberCodeVo vo) {
        return redisUtil.set(AdamRedisConst.INFO_MEMBER_CODE.concat(memberCode), vo);
    }

    public AdamMemberCodeVo getMemberCodeVoByCode(String memberCode) {
        String key = AdamRedisConst.INFO_MEMBER_CODE.concat(memberCode);
        long s = System.currentTimeMillis();
        AdamMemberCodeVo vo = (AdamMemberCodeVo) redisUtil.get(key);
        if (null == vo) {
            s = System.currentTimeMillis();
            vo = mongoTemplate.findOne(
                    Query.query(Criteria.where("code").is(memberCode)),
                    AdamMemberCodeVo.class, AdamMemberCodeVo.class.getSimpleName()
            );
            log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);
            if (null != vo && vo.getState() == 0) redisUtil.set(AdamRedisConst.INFO_MEMBER_CODE.concat(memberCode), vo);
        }
        log.debug("#RDM耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    public void delMemberCodeVoByCode(String memberCode) {
        redisUtil.del(AdamRedisConst.INFO_MEMBER_CODE.concat(memberCode));
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |  */

    /**
     * Temporarily connect Mongo
     */
    public AdamMemberCodeVo getMemberCodeVoByBuyOrderNo(String buyOrderNo) {
        Query query = Query.query(Criteria.where("buyOrderNo").is(buyOrderNo));
        query.fields().include("code").include("memberNo").include("state").include("type");
        long s = System.currentTimeMillis();
        AdamMemberCodeVo vo = mongoTemplate.findOne(
                query, AdamMemberCodeVo.class, AdamMemberCodeVo.class.getSimpleName()
        );
        log.debug("#MDB耗时:{}ms", System.currentTimeMillis() - s);
        return vo;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | TAGS:List<AdamTagVo> */

    public boolean setTagsForSex(List<AdamTagVo> voList) {
        return redisUtil.set(AdamRedisConst.INFO_TAGS_SEX, voList);
    }

    public List<AdamTagVo> getTagsForSex() {
        return (List<AdamTagVo>) redisUtil.get(AdamRedisConst.INFO_TAGS_SEX);
    }

    public boolean setTagsForMusic(List<AdamTagParentVo> voList) {
        return redisUtil.set(AdamRedisConst.INFO_TAGS_MUSIC, voList);
    }

    public List<AdamTagParentVo> getTagsForMusic() {
        return (List<AdamTagParentVo>) redisUtil.get(AdamRedisConst.INFO_TAGS_MUSIC);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |  */



    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |  */



    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |  */



    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |  */



    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |  */



    /* ========================================================== | Other micro-service data inquiry */

    public KylinPerformanceVo kylinPerformanceVo(String performancesId) {
        return (KylinPerformanceVo) redisUtil.get(KylinRedisConst.PERFORMANCES + performancesId);
    }
}
