package com.supervision.util.freemark;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONUtil;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class StringTemplateConfig {

    private final Configuration configuration;
    private final StringTemplateLoader loader;

    private final Map<String, String> tempMap = new HashMap<>();


    private static class SingletonHolder {
        private static final StringTemplateConfig INSTANCE = new StringTemplateConfig();
    }

    private StringTemplateConfig() {
        configuration = new Configuration(Configuration.VERSION_2_3_30);
        loader = new StringTemplateLoader();
        configuration.setTemplateLoader(loader);
    }

    public static StringTemplateConfig getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public Template getTemplate(String name) throws IOException {
        if (!tempMap.containsKey(name)) {
            return null;
        }
        return this.configuration.getTemplate(name);
    }

    public void putTemplate(String name, String content){
        tempMap.put(name, content);
        this.loader.putTemplate(name, content);
    }

    public boolean removeTemplate(String name){
        if (tempMap.remove(name) != null){
            return this.loader.removeTemplate(name);
        }
        return true;
    }

    public <T extends List<Map<String, Object>>> String process(String content,  List<Map<String, Object>> data) throws IOException, TemplateException {
        Map<String, Object> dataModel = new HashMap<String, Object>(){};
        dataModel.put("dataList", data);
        return process(content, dataModel);

    }

    public <T extends Map<String, Object>> String process(String content,  Map<String, Object> dataModel) throws IOException, TemplateException {

        log.info("StringTemplateConfig.process:入参data:{} , content:{}",  JSONUtil.toJsonStr(dataModel),content);

        if (StrUtil.isEmpty(content)) {
            return null;
        }
        String name = contentToName(content);
        if (Objects.isNull(tempMap.get(name))) {
            this.putTemplate(name, content);
        }
        Template template = this.getTemplate(name);
        StringWriter out = new StringWriter();
        template.process(dataModel, out);
        log.info("StringTemplateConfig.process:计算结果:{}", out);
        return out.toString();

    }

    public String contentToName(String content){
        return MD5.create().digestHex16(content);
    }
}
