package cn.cecep.talroad.util;

import cn.cecep.talroad.domain.BasParam;
import cn.cecep.talroad.domain.PcFactory;
import cn.cecep.talroad.enums.EnStatTimeType;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * excel工具类
 */
public class CsvUtils
{
    /** CSV列分隔符 */
    private static final String CSV_COL_SEPARATOR = ",";
    /** CSV行分隔符 */
    private static final String CSV_ROW_SEPARATOR = "\r\n";

    /** CSV内容缓存 */
    private StringBuilder sb = new StringBuilder();
    /** 各列的显示用名称及字段名 */
    private String[] colNames, colFields;

    /** 报警类型（用于报警数据） */
    private String alertType = null;
    /** 是否需要特殊处理alertValue字段-转为百分比（用于报警数据） */
    private boolean alertValueToPer = false;


    //region ======== 私有方法 ========

    /** 根据类的属性名获取其对象的属性值
     * @param obj   对象
     * @param field - 属性名
     * @return
     */
    private String getFieldValue(Object obj, String field) {
        Method javaMethod;
        Object value;
        String fieldCase;        //首字母大写

        if (StringUtils.isEmpty(field))
            fieldCase = "";
        else if (field.length() == 1)
            fieldCase = field.toUpperCase();
        else
            fieldCase = field.substring(0, 1).toUpperCase() + field.substring(1);
        try {
            javaMethod = obj.getClass().getMethod("get" + fieldCase, new Class[]{});
            value = javaMethod.invoke(obj);
                //针对报警的特殊处理
            if( !StringUtils.isEmpty(alertType) )
            {
                if ("alertValue".equals(field) && alertValueToPer)
                {
                    if(value == null)
                        return null;
                    return (new BigDecimal(value.toString())).multiply(BigDecimal.valueOf(100)).setScale(1, RoundingMode.HALF_UP).toPlainString() + "%";
                }
                if ("beginTime".equals(field))
                {
                    if(value == null)
                        return null;
                    return ((LocalDateTime)value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                }
            }
            return (value == null) ? null : value.toString();
        } catch (Exception e) {
            return null;
        }
    }

    /** 填写一个单元格的内容 */
    private void fillOneCell(int idxCell, Object val)
    {
        String valStr;

        if(val == null)
            valStr = "";
        else
            valStr = String.valueOf(val);
        if(idxCell > 0)
            sb.append(CSV_COL_SEPARATOR);
        valStr = valStr.replaceAll("\"","\"\"");
        if( valStr.contains(CSV_COL_SEPARATOR) )
        {
            sb.append("\"");
            sb.append(valStr);
            sb.append("\"");
        }
        else
            sb.append(valStr);
    }

    /** 手工添加行结束符 */
    private void fillRowTail()
    {
        sb.append(CSV_ROW_SEPARATOR);
    }

    /** 填写一行的内容 */
    private void fillOneRow(Object po)
    {
        int idxCell;

        idxCell = 0;
        for (String item : colFields)
            fillOneCell(idxCell++, getFieldValue(po,item));
        sb.append(CSV_ROW_SEPARATOR);
    }

    //endregion

    //======== 公共方法 ================================================================

    /** 当查询出错时，导出出错信息为Excel文件 */
    public StringBuilder exportError(String errorMsg)
    {
        fillOneCell(0, "导出出错："+errorMsg);
        for(int colIdx=1; colIdx<colNames.length; colIdx++)
            fillOneCell(colIdx, "");
        fillRowTail();
        return sb;
    }

    /** 获得缓存内容 */
    public StringBuilder getBuf()
    {
        return sb;
    }

    /** 获得缓存内容(字节数组格式，GBK编码) */
    public byte[] getBufInBytes()
    {
        return sb.toString().getBytes(Charset.forName("GBK"));
    }

    /** 清除缓存内容 */
    public void clearBuf()
    {
        sb.delete(0, sb.length());
    }


    /** 初始化CSV(设备DCS数据)-生成各列名及标题行等 */
    public StringBuilder initMonDevData(String timeType, PcFactory facPo, List<BasParam> lstParamPo)
    {
        int colIdx;

        //==== 1.生成列属性
            //固定的头和尾列
        colNames = new String[3+lstParamPo.size()+1];       //3=设备编号、名称、时间；1=附加参数
        colFields = new String[3+lstParamPo.size()+1];      //3=设备编号、名称、时间；1=附加参数
        colNames[0] = "设备编号";
        colNames[1] = "设备名称";
        colNames[2] = "时间";
        colNames[colNames.length-1] = "附加值";
        colFields[0] = "deviceId";
        colFields[1] = "name";
        colFields[2] = "dataTime";
        colFields[colFields.length-1] = "addiParam";
            //动态的中间数据列
        colIdx = 3;
        for (BasParam paramPo : lstParamPo)
        {
            if(EnStatTimeType.REAL.id().equals(timeType))
                colNames[colIdx] = paramPo.getName() + "[" + paramPo.getUnitReal() + "]";
            else
                colNames[colIdx] = paramPo.getName() + "[" + paramPo.getUnitStat() + "]";
            colFields[colIdx] = paramPo.getParamCodeSvc();
            colIdx ++;
        }

        //==== 2.创建工厂信息行
        if(facPo != null)
        {
            fillOneCell(0, "企业名称：" + facPo.getFactoryName());
            for(colIdx=1; colIdx<colNames.length; colIdx++)
                fillOneCell(colIdx, "");
            fillRowTail();
            fillOneCell(0, "信用代码：" + facPo.getUscCode());
            for(colIdx=1; colIdx<colNames.length; colIdx++)
                fillOneCell(colIdx, "");
            fillRowTail();
            fillOneCell(0, "数据说明：");
            for(colIdx=1; colIdx<colNames.length; colIdx++)
                fillOneCell(colIdx, "");
            fillRowTail();
        }

        //==== 3.创建标题(含单位)行
        colIdx = 0;
        for (String item : colNames)
            fillOneCell(colIdx++, item);
        fillRowTail();

        //==== 4.创建参数编码行
        fillOneCell(0, "");
        fillOneCell(1, "");
        fillOneCell(2, "");
        colIdx = 3;
        for (BasParam paramPo : lstParamPo)
            fillOneCell(colIdx++, "["+paramPo.getParamCodeSvc()+"]");
        fillRowTail();

        return sb;
    }

    /** 生成CSV(设备DCS数据)-数据行 */
    public StringBuilder exportMonDevData(List<Object> lstIn)
    {
        for (Object item : lstIn)
            fillOneRow(item);
        return sb;
    }


}
