package cn.com.tenlion.freemarker.util;

import cn.com.tenlion.freemarker.pojo.dtos.templateconfig.TemplateConfigDTO;
import cn.com.tenlion.freemarker.pojo.dtos.templaterecord.TemplateRecordDTO;
import cn.com.tenlion.freemarker.pojo.vos.templaterecord.TemplateRecordVO;
import cn.com.tenlion.freemarker.service.templateconfig.ITemplateConfigService;
import cn.com.tenlion.freemarker.service.templaterecord.ITemplateRecordService;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import ink.wgink.properties.ServerProperties;
import ink.wgink.util.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

/**
 * 生成静态模板文件工具类
 */
@Component
public class TemplateBuilderUtil {

    private static TemplateBuilderUtil templateUtil = TemplateUtilBuilder.templateUtil;

    @Autowired
    private ServerProperties systemProperties;

    private static ServerProperties  systemStitacProperties;

    /**
     * 模板文件控制器
     */
    private static Configuration cfg;

    @Autowired
    private ITemplateRecordService iTemplateRecordService;

    private static ITemplateRecordService  iTemplateRecordStaticService;

    @PostConstruct
    public void init() {
        iTemplateRecordStaticService = this.iTemplateRecordService;
        systemStitacProperties =  this.systemProperties;
    }

    /**
     * 所有模板文件的存储
     */
    private static Map<String, TemplateConfigDTO> templateMap = new HashMap<String, TemplateConfigDTO>();

    static {
        cfg = new Configuration(Configuration.VERSION_2_3_23);
        try {
            // 设置默认编码
            cfg.setDefaultEncoding("UTF-8");
            // 错误信息输出到控制台
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 模板加入和更新
     * @param templateCode 模板编码
     */
    public void removeTemplate(String templateCode) {
        templateMap.remove(templateCode);
    }

    /**
     * 模板加入和更新
     * @param templateCode 模板编码
     * @param templateConfigDTO 模板对象
     */
    public void pushTemplate(String templateCode, TemplateConfigDTO templateConfigDTO) {
        StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
        stringTemplateLoader.putTemplate(templateCode, templateConfigDTO.getTemplateContent());
        templateConfigDTO.setStringTemplateLoader(stringTemplateLoader);
        templateMap.put(templateCode, templateConfigDTO);
    }

    /**
     *  静态模板文件生成
     * @throws Exception
     */
    public TemplateRecordVO createFile(TemplateCreateData templateCreateData) throws Exception {
        TemplateConfigDTO templateConfigDTO = templateMap.get(templateCreateData.getTemplateCode());
        if (templateConfigDTO == null || templateConfigDTO.getStringTemplateLoader() == null) {
            throw new Exception("该模板不存在");
        }
        if(StringUtils.isEmpty(templateCreateData.getBusinessId())) {
            throw new Exception("业务ID不能为空");
        }
        // 2020年10月27日16:07:50 崔宝铖
        templateCreateData.getTemplateDataMap().put("TEMPLATE", templateConfigDTO);
        templateCreateData.getTemplateDataMap().put("SYSTEM_URL", systemStitacProperties.getUrl());
        templateCreateData.getTemplateDataMap().put("SYSTEM_TITLE", systemStitacProperties.getSystemTitle());
        templateCreateData.getTemplateDataMap().put("SYSTEM_PORT", systemStitacProperties.getPort());
        templateCreateData.getTemplateDataMap().put("NGINX_URL", templateConfigDTO.getTemplateUrl());
        // 查询是否是首次生成
        TemplateRecordDTO templateRecordDTO = iTemplateRecordStaticService.getTemplateRecordById(templateCreateData.getBusinessId());
        // 创建模板存储文件夹
        String outFilePath = StringUtils.isEmpty(templateCreateData.getOutFilePath()) ? (DateUtil.getYear() + File.separator + DateUtil.getMonth() + File.separator + DateUtil.getToday() + File.separator ) : templateCreateData.getOutFilePath();
        String outFileName = StringUtils.isEmpty(templateCreateData.getOutFileName()) ? templateCreateData.getBusinessId() +  templateConfigDTO.getTemplateFileType() : templateCreateData.getOutFileName();
        // 如果不创建新文件生成, 则使用旧的路径
        if(templateRecordDTO != null && !templateCreateData.getCreateNewFile()) {
            // 查询旧文件是否存在
            String templateRecordPath = templateRecordDTO.getTemplateRecordPath();
            File oldFile = new File(templateRecordPath);
            // 如果存在, 则使用旧文件的路径
            if(oldFile.exists()) {
                // 如果根路径改变了, 则直接拼接根路径
                String oldUrl = templateRecordDTO.getTemplateRecordUrl().replaceAll("/", Matcher.quoteReplacement(File.separator));
                String oldRoot = templateRecordDTO.getTemplateRecordPath().substring(0, templateRecordDTO.getTemplateRecordPath().indexOf(oldUrl));
                // 根路径没变
                if(oldRoot.equals(templateConfigDTO.getTemplateRootPath())) {
                    String deleteNamePath = templateRecordPath.substring(0, templateRecordPath.lastIndexOf(File.separator) + 1 );
                    outFilePath = deleteNamePath.replace(templateConfigDTO.getTemplateRootPath(), "");
                }else{
                    // 更路经变了, 只改变根路径, 不改变时间路径
                    String oldDays = oldUrl.substring(0, oldUrl.lastIndexOf(File.separator) + 1);
                    outFilePath = StringUtils.isEmpty(templateCreateData.getOutFilePath()) ? (oldDays) : templateCreateData.getOutFilePath();
                }
            }
        }
        cfg.setTemplateLoader(templateConfigDTO.getStringTemplateLoader());
        Template temp = cfg.getTemplate(templateCreateData.getTemplateCode(),"utf-8");
        File file = new File(templateConfigDTO.getTemplateRootPath() + outFilePath);
        if(!file.exists()) {
            file.mkdirs();
        }
        // 输出模板结果文件
        String fileName = templateConfigDTO.getTemplateRootPath() + outFilePath + outFileName;
        File saveFile = new File(fileName);
        // 如果文件已经存在则删除
        if(saveFile.exists()) {
            saveFile.delete();
        }
        Writer out = new FileWriter(saveFile);
        temp.process(templateCreateData.getTemplateDataMap(), out);
        out.flush();
        out.close();
        /**
         * 做生成模板记录
         */
        TemplateRecordVO recordVo = new TemplateRecordVO();
        recordVo.setBusinessContent(templateCreateData.getBusinessContent());
        recordVo.setTemplateRecordId(templateCreateData.getBusinessId());
        recordVo.setTemplateId(templateConfigDTO.getTemplateConfigId());
        recordVo.setTemplateRecordBuilderTime(DateUtil.getTime());
        recordVo.setTemplateRecordPath(fileName);
        recordVo.setTemplateRecordUrl(outFilePath.replaceAll(Matcher.quoteReplacement(File.separator), "/") + outFileName);
        String recordUrlNginx = templateConfigDTO.getTemplateUrl();
        // 当前服务器接口访问
        if("2".equals(templateConfigDTO.getTemplateMode())) {
            recordUrlNginx = systemStitacProperties.getUrl() + recordUrlNginx + templateCreateData.getBusinessId();
        // 其他服务器地址访问
        }else{
            recordUrlNginx = recordUrlNginx + outFilePath.replaceAll(Matcher.quoteReplacement(File.separator), "/") + outFileName;
        }
        recordVo.setTemplateRecordUrlNginx(recordUrlNginx);
        iTemplateRecordStaticService.saveTemplateRecord(recordVo);
        return recordVo;
    }

    public static void main(String[] args) throws Exception {
        Map<String,Object> root = new HashMap<String,Object>();
        root.put("action"  ,"deny"  );
        root.put("protocol" ,"udp"  );
        root.put("source_ip_address"  ,"192.168.56.123"  );
        root.put("source_wildcard"  ,"0.0.0.255"  );
        root.put("destination_ip_address"  ,"192.168.56.123"  );
        root.put("destination_wildcard"  ,"0.0.0.255"  );
        root.put("operator"  ,"gt"  );
        root.put("destination_port"  ,"128"  );
    }

    private TemplateBuilderUtil() {}


    public static TemplateBuilderUtil getInstance() {
        return templateUtil;
    }

    private static class TemplateUtilBuilder {
        public static final TemplateBuilderUtil templateUtil = new TemplateBuilderUtil();
    }

}
