package com.bcxin.ins.utils;

import freemarker.core.ParseException;
import freemarker.template.*;
import freemarker.template.Template;
import org.apache.velocity.*;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

import java.io.*;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

/**
 * Freemarker 工具类
 * @author hzp
 * @date 2018/06/20
 */
public class FreemarkerUtil {

    private static Logger logger =  LoggerFactory.getLogger(FreemarkerUtil.class);
    private static FreemarkerUtil fk;;
    private static Configuration cfg;
    private FreemarkerUtil() {
    }

    /**
     * 单例
     * @return
     * @throws Exception
     */
    public static FreemarkerUtil getInstance() throws Exception{
        //fileDir部署测试或生产用自动获取，本地用固定死的地址
//        String fileDir = "F:/D_pan/Program Files (x86)/JetBrains/workspase/blbtest/trunk/bcxin-ins-web/target/bcxin-ins-web/WEB-INF/views/template";
//        String fileDir = "F:\\D_pan\\Program Files (x86)\\JetBrains\\workspase\\blbtest\\trunk\\bcxin-ins-web\\target\\bcxin-ins-web\\WEB-INF\\views\\template";
        String fileDir = Thread.currentThread().getContextClassLoader().getResource("").getPath().replace("classes","views")+"/template";
        logger.info("----------服务器模板地址："+fileDir);
        return getInstance(Configuration.VERSION_2_3_28.toString(),fileDir);
    }
    public static FreemarkerUtil getInstance(String freemarkerVersionNo) throws Exception{
        return getInstance(freemarkerVersionNo,null);
    }
    /**
     * @param freemarkerVersionNo freemarker的版本号
     * @param templatePath 模版加载路径
     * @return
     */
    public static FreemarkerUtil getInstance(String freemarkerVersionNo, String templatePath) throws Exception{
        if (null == fk) {
            cfg = new Configuration(new Version(freemarkerVersionNo));
//            cfg.setClassForTemplateLoading(FreemarkerUtil.class, templatePath);
            cfg.setDirectoryForTemplateLoading(new File(templatePath));
            cfg.setEncoding(Locale.getDefault(), "UTF-8");
//            cfg.setDefaultEncoding("UTF-8");
            fk=new FreemarkerUtil();
        }
        return fk;
    }

    /**
     * @param templateName 根据模版名称加载对应模版
     * @return
     */
    private Template getTemplate(String templateName){
        try {
             Template template=cfg.getTemplate(templateName,"UTF-8");
             return template;
        } catch (TemplateNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedTemplateNameException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String generator(String template, Map<String, Object> map){
        // 设置velocity资源加载器
        String fileDir = Thread.currentThread().getContextClassLoader().getResource("").toString().replace("classes","views")+"/template";
        Properties prop = new Properties();
        VelocityEngine ve = new VelocityEngine();
//        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        prop.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, fileDir);
        Velocity.init(prop);
        //加载数据
        VelocityContext context = new VelocityContext(map);
        StringWriter sw = new StringWriter();
        org.apache.velocity.Template tpl = ve.getTemplate(template, "UTF-8");
        tpl.merge(context, sw);
        return sw.toString();
    }

    public static void main(String[] args) {
        String a = "F:\\D_pan\\Program Files (x86)\\JetBrains\\workspase\\blbtest\\trunk\\bcxin-ins-web\\target\\bcxin-ins-web\\WEB-INF\\views\\template";
        System.out.println(a);
    }

    /**
     * 输出到控制台
     * @param dataModel 数据模型
     * @param templateName 输出模版
     */
    public void printOut(Map<String, Object> dataModel,String templateName){
        try {
            this.getTemplate(templateName).process(dataModel, new PrintWriter(System.out));
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 转换后直接输入结果字符串
     * @param name
     * @param data
     * @return 结果字符串
     */
    public String transferMapToString(String name,Map<String,Object> data) {
        try(StringWriter out = new StringWriter();
            BufferedWriter writer = new BufferedWriter(out);){
            //通过一个文件输出流,就可以写到相应的文件中
            Template temp = this.getTemplate(name);
            temp.process(data, writer);
            return format(out.toString());
         }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }

    /**
     * @param templateName 模板名称
     * @param xml xml字符串
     * @return 结果字符串
     */
    public String transferXml(String templateName,String xml) {
        byte[] xb = null;
        try {
            xb = xml.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try(StringWriter out = new StringWriter();
            InputStream in = new ByteArrayInputStream(xb);){
            Map<String,Object> map=new HashMap<String,Object>();
            InputSource ins=new org.xml.sax.InputSource(in);
            map.put("data",freemarker.ext.dom.NodeModel.parse(ins));
            //通过一个文件输出流,就可以写到相应的文件中
            Template temp = this.getTemplate(templateName);
            temp.process(map, out);
            return format(out.getBuffer().toString());
        }catch (IOException e){
            e.printStackTrace();
        }catch (TemplateException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 转换并保存文件
     * @param dataModel 数据模型
     * @param templateName 输出模版
     * @param filePath  输出文件路径
     */
    public void transferMapToFile(Map<String, Object> dataModel,String templateName,String filePath){
        try(BufferedWriter bufWrite = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath),"UTF-8"));) {
            getTemplate(templateName).process(dataModel, bufWrite);
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 由于字符串带有看不见的BOM编码头，需要截取
     * @param result
     * @return
     */
    public String format(String result){
        if(null != result && !"".equals(result)){
            if(result.indexOf('<') != -1 && result.lastIndexOf('>') != -1 && result.lastIndexOf('>') > result.indexOf('<')) {
                int i=result.indexOf('<');
                int ii=result.lastIndexOf('>') + 1;
                result = result.substring(result.indexOf('<'), result.lastIndexOf('>') + 1);
            }
        }
        return result;
    }
}