package com.wuban.tron.explore.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wuban.tron.explore.constant.Constant;
import com.wuban.tron.explore.domain.*;
import com.wuban.tron.explore.entity.Contract;
import com.wuban.tron.explore.service.BaseCommonService;
import com.wuban.tron.explore.service.TronService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  <core>波场区块服务接口实现类</core>
 *
 * @author sky
 * @date 2020/11/02
 */
@Service
@Slf4j
public class TronServiceImpl extends BaseCommonService implements TronService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public TronResponseData getBlockByNum(Long blockNum) {
        String str = this.analysisBlock(GET_BLOCK_BYNUM, blockNum);
        if (StringUtils.isEmpty(str)) {
            stringRedisTemplate.opsForList().leftPush(Constant.BLOCK_NUM_LIST_KEY, blockNum.toString());
            log.warn("区块高度blockNum:{}抓取失败，重新放置到队列{}中.", blockNum, Constant.BLOCK_NUM_LIST_KEY);
            return null;
        }

        return JSONObject.parseObject(str, TronResponseData.class);
    }

    @Override
    public TronResponseArrayData getBlockByLatestNum(Integer num) {
        String str = this.analysisBlock(GET_BLOCK_BYLATESTNUM, num);
        if (StringUtils.isEmpty(str)) {
            return null;
        }

        return JSONObject.parseObject(str, TronResponseArrayData.class);
    }

    private String analysisBlock(String interfaceName, Object param) {
        Map<String, Object> map = new HashMap<>(1);
        map.put("num", param);

        Request request = this.builderPost(interfaceName, map);
        String str = this.execute(request);
        return str;
    }

    /**
     * 根据地址获取账户信息
     *
     * @param address 账户地址
     */
    @Override
    public TronAccount getAccount(String address) {
        Map<String, Object> map = new HashMap<>(1);
        map.put("address", address);

        Request request = this.builderPost(GET_ACCOUNT, map);
        String str = this.execute(request);
        if (StringUtils.isEmpty(str)) {
            this.stringRedisTemplate.opsForSet().add(Constant.ADDRESS_KEY, address);
            log.warn("账户余额address:{}抓取失败，重新放置到队列{}中.", address, Constant.ADDRESS_KEY);
            return null;
        }

        return JSONObject.parseObject(str, TronAccount.class);
    }

    @Override
    public List<TronTransEvent> getContractEvent(String address) {
        Request request = this.builderGet(CONTRACT_EVENT + address);
        String str = this.execute(request);
        if (StringUtils.isEmpty(str)) {
            return null;
        }

        //System.out.println("处理前：》》》》》"+str);
        String ret = clearData(str);
        //System.out.println("处理后：》》》》》"+ret);
        return JSONArray.parseArray(ret, TronTransEvent.class);
    }

    @Override
    public Contract getContract(String address) {
        Map<String, Object> map = new HashMap<>(1);
        map.put("value", address);

        Request request = this.builderPost(GET_CONTRACT, map);
        String str = this.execute(request);
        if (StringUtils.isEmpty(str)) {
            return null;
        }

        return JSONObject.parseObject(str, Contract.class);
    }

    /**
     * 数据清洗
     *
     * 清洗前：
     *        "1":"2",
     *        "2":"0x67c62732f1f6086a98310aa5c83163977394f92e",
     *        "3":"0x4f948b55157ed879a2b6863c22a4e31d28ceebb7",
     *        "4":"300000000",
     *        "5":"285000000",
     *        "6":"15000000",
     * 清洗后：
     *        "_$1":"2",
     *        "_$2":"0x67c62732f1f6086a98310aa5c83163977394f92e",
     *        "_$3":"0x4f948b55157ed879a2b6863c22a4e31d28ceebb7",
     *        "_$4":"300000000",
     *        "_$5":"285000000",
     *        "_$6":"15000000",
     * @param data
     * @return
     */
    private String clearData(String data) {
        int range = 10;
        String ret = data;
        String regex = "\":";
        for (int i = 0; i < range; i++) {
            String tmp = i+regex;
            ret = ret.replaceAll(tmp, "_\\$"+i+"\":");
        }

        return ret;
    }


}
