package com.brilliance.isc.swift.swifteditor.tag.message;

import com.brilliance.mda.runtime.mda.util.Inis;
import com.brilliance.isc.common.util.StringUtils;
import com.brilliance.isc.swift.swifteditor.tag.TagFormat;
import com.brilliance.isc.swift.swifteditor.tag.TagLine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MessageAnalyzer {
    public static final Pattern THIRD_PART = Pattern.compile("\\{(\\d+):([^}]+)\\}");
    private static Logger log = LoggerFactory.getLogger(MessageAnalyzer.class);
    /*
     * @param msg:报文字符串； 传递报文字符串，将其中的文首都解析出来。 对于ACK/NCK报文，后面会附带原报，会出现文首重复的情况，将附带的原报文首的KEY添加负号做为KEY，避免覆盖。
     * 如果后面附带了S等带字母的“文首”，则直接使用其Acsii码，作为KEY。
     */
    public static Map<Integer, String> anlyMsgHead(String msg) {
        Map<Integer, String> headSet = new HashMap<Integer, String>();
        String reg = "\\{[\\d|S]:";
        Matcher m = Pattern.compile(reg).matcher(msg);
        int lstEnd = -1;
        int lstHead = -1;
        while (m.find()) {
            //文首的前一个字符要么为0，要么为左括号
            if(m.start() !=0 && msg.charAt(m.start()-1)!='}') {
                continue;
            }
            if (lstEnd > 0 && lstHead > 0) {
                String val = msg.substring(lstEnd, m.start() - 1);
                if (!headSet.containsKey(lstHead)) {
                    headSet.put(lstHead, val);
                } else {
                    headSet.put(-lstHead, val);
                }
            }
            String g = m.group();
            char c = g.charAt(1);
            lstHead = c;
            if (c >= '0' && c <= '9') // 对于是数字的，则以数字做KEY，否则以Acsii码做主键
                lstHead -= '0';
            lstEnd = m.end();
        }
        if (lstEnd > 0 && lstHead > 0) // 将最后一个文首存入Map
        {
            int lstidx = msg.lastIndexOf('}');
            if (lstidx <= lstEnd)
                return headSet;
            if (!headSet.containsKey(lstHead))
                headSet.put(lstHead, msg.substring(lstEnd, lstidx));
            else
                headSet.put(-lstHead, msg.substring(lstEnd, lstidx));
        }
        return headSet;
    }

    /*
     * @param mt:对正文block 4中包含的栏位名称和栏位值切割，以换行符加“:”来切割
     */
    public static List<String[]> msgTxtAnly(String mt) {
        if (mt.startsWith(":"))
            mt = "\r\n" + mt;
        String[] tags = mt.split("[\\r\\n]{1,2}:(?=\\d{2}[A-Z]?:)");
        List<String[]> list = new ArrayList<String[]>();
        for (String tv : tags) {
            if (tv.trim().length() > 0) {
                int i = tv.indexOf(':');
                if (i > 0) {
                    String[] arr = new String[2];
                    arr[0] = tv.substring(0, i);
                    arr[1] = tv.substring(i + 1);
                    list.add(arr);
                }
            }
        }
        if (list.size() > 0) {
            String[] lstOne = list.get(list.size() - 1);
            String lstStr = lstOne[1].trim();
            int i = lstStr.lastIndexOf("\r\n");
            if (i < 0) {
                i = lstStr.lastIndexOf("\r");
            }
            if (i < 0) {
                i = lstStr.lastIndexOf("\n");
            }
            if (i > -1) {
                //清除末尾横线
                String lstLine = lstStr.substring(i).trim();
                if ("-".equals(lstLine))
                    lstOne[1] = lstStr.substring(0, i);

            }
        }
        return list;
    }

    /* 屏蔽不同的系统的换行符差异，获取换行符位置 */
    private static int getLinePos(String str) {
        if (str == null)
            return -1;
        int idxr = str.indexOf("\r");
        int idxn = str.indexOf("\n");
        if (idxr > -1 && idxn > -1)// \r\n连接在一起
        {
            return idxr < idxn ? idxr : idxn;
        } else {
            return idxr <= idxn ? idxn : idxr;// 单个\r或者\n的情况，返回较大的
        }
    }

    private static String convertTime(String dateStr){
       SimpleDateFormat sdf = new  SimpleDateFormat("yyMMddHHmm");
        SimpleDateFormat sdf2 = new  SimpleDateFormat("dd.MM.yyyy HH:mm");
        try {
            Date date  = sdf.parse(dateStr);
            return sdf2.format(date);
        } catch (Exception e) {
            return dateStr;
        }
    }

    public static Map<String, String> getSwfMsgInfoViaMsg(Map<Integer, String> heads) {
        Map<String, String> infMap = new HashMap<String, String>();

        String hd4 = heads.get(4);
        boolean isNACK = false; // 是否为ACK/NCK报文
        if (hd4 != null) {
            if (hd4.contains("{451:0}") || hd4.contains("{451:1}")) {
                isNACK = true;
                if (hd4.contains("{451:0}"))
                    infMap.put("mty", "ACK");
                else
                    infMap.put("mty", "NCK");
                // infMap.put("ehf",heads.get(-4) );
                int errIdx = hd4.indexOf("{405:");
                if (errIdx > -1) {
                    int idx2 = hd4.indexOf("}", errIdx);// 获取下一个括号
                    if (idx2 > -1)
                        infMap.put("errcod", hd4.substring(errIdx + 5, idx2));// 将错误码放进去
                }
            } else
            // 非ACK 或NCK报文
            {

            }
        }
        /* 处理报文或者附带的报文的文首和正文 */
        String hd2 = heads.containsKey(-2) ? heads.get(-2) : heads.get(2);
        String hd1 = heads.containsKey(-1) ? heads.get(-1) : heads.get(1);
        String hd3 = heads.containsKey(-3) ? heads.get(-3) : heads.get(3);
        hd4 = heads.containsKey(-4) ? heads.get(-4) : heads.get(4);
        String hd5 = heads.containsKey(-5) ? heads.get(-5) : heads.get(5);
        if (hd5 != null)
            infMap.put("trl", hd5);
        String msgTyp = null; // 报文类型，如果为NCK/ACK报文，则该类型值为附带的原文里面的类型
        String direct = null; // 报文收发方向
        if (hd2 != null) // 拆解2文首
        {
            // 如果2文首不为空,开始获取收发方向和报文类型
            if (hd2.length() >= 4) {
                direct = hd2.substring(0, 1);
                infMap.put("direct", direct);// 存储报文方向
                msgTyp = hd2.substring(1, 4);
                if ("I".equals(direct)) // 发出报文
                {
                    if (hd2.length() >= 16) {
                        String rcvbic = hd2.substring(4, 16); // 获取收报行
                        infMap.put("rcvbic", rcvbic);
                    }
                    if (hd2.length() >= 17)
                        infMap.put("prt", hd2.substring(16, 17));// 电报优先级
                    if (hd2.length() >= 18)
                        infMap.put("tns", hd2.substring(17, 18));
                    if (hd2.length() >= 21)
                        infMap.put("dyt", hd2.substring(18, 21));
                } else if ("O".equals(direct)) {
                    if (hd2.length() >= 26) {
                        String sndbic = hd2.substring(14, 26);
                        infMap.put("sndbic", sndbic); // 获取发报行
                        if (hd2.length() >= 36) {
                            infMap.put("sndtim",convertTime(hd2.substring(8, 14) + hd2.substring(4, 8)));
                            infMap.put("mir", hd2.substring(8, 14) + " " + hd2.substring(14, 36));// 获取MIR
                            if (hd2.length() == 47)
                                infMap.put("rcvtim",convertTime(hd2.substring(36, 46)));
                                infMap.put("prt", hd2.substring(46));// 电报优先级
                        }
                    }
                }
            }
        }
        if (hd1 != null) // 拆解1文首
        {
            if (hd1.length() >= 15) {
                String bnk1 = hd1.substring(3, 15);
                if ("O".equals(direct)) {
                    infMap.put("rcvbic", bnk1);
                } else if ("I".equals(direct)) {
                    infMap.put("sndbic", bnk1);
                }
                if (hd2 != null && hd2.length() >= 14) {
                    infMap.put("mor", hd2.substring(8, 14) + " " + hd1.substring(3));// 获取MOR
                }
            }
        }
        if (hd3 != null) {
            //取出所有第三部分的内容
            Matcher matcher = THIRD_PART.matcher(hd3);
            while (matcher.find()){
                String key = matcher.group(1);
                String val = matcher.group(2);
                infMap.put(key,val);
            }
            if (hd3.contains("{119:COV}")) {
                msgTyp = msgTyp + "COV";
            }
            if (hd3.contains("{FMT:")) {
                String fmt = hd3.substring(1, hd3.length() - 1);
                String args[] = fmt.split(":");
                infMap.put("fmttype", args[0]);
                infMap.put("fmtstd", args[1]);
                String strarry[] = hd3.split("\\}");
                for (String substr : strarry) {
                    substr = substr.substring(1);
                    String sp[] = substr.split(":");
                    if (sp.length == 2) {
                        infMap.put(sp[0], sp[1]);
                    } else {
                        infMap.put(sp[0], null);
                    }
                }
            }
            // else if(hd3.contains("{119:STP}"))
            // msgTyp = msgTyp + "+";
            Matcher m = Pattern.compile("\\{108:\\w+\\}").matcher(hd3);
            if (m.find()) {
                String gp = m.group();
                int idx = gp.indexOf(":");
                infMap.put("sndnum", gp.substring(idx + 1, gp.length() - 1)); /* 取发报流水号 */
            }
        }
        infMap.put("std", "MT");
        if (!isNACK)
            infMap.put("mty", msgTyp);// 报文类型已经添加，存入Map中
        else
            infMap.put("emty", msgTyp);// 获取附带的报文类型
        if (hd4 != null) // 处理4域，即正文
        {
            List<String[]> kv = msgTxtAnly(hd4);
            for (String[] strArr : kv) {
                if (strArr[1].trim().length() == 0)
                    continue;
                if (strArr[0].endsWith("20"))// 业务编号
                {
                    if (!infMap.containsKey("ref")) // 如果没有填入20栏，则将20栏填入，已填入则不进行覆盖。为nXX系列报文附带原报的情况
                    {
                        if (strArr[1].length() > 16)
                            infMap.put("ref", strArr[1].substring(0, 16).trim());
                        else
                            infMap.put("ref", strArr[1].trim());
                    }
                }
                if (strArr[0].endsWith("21"))// 相关编号
                {
                    if (!infMap.containsKey("tscref")) // 如果没有填入21栏，则将21栏填入，已填入则不进行覆盖。为nXX系列报文附带原报的情况
                    {
                        if (strArr[1].length() > 16)
                            infMap.put("tscref", strArr[1].substring(0, 16));
                        else
                            infMap.put("tscref", strArr[1]);
                    }
                }
                if (strArr[0].endsWith("22C"))// 300报文的COMMON REFFERENCE
                {

                }
                if (strArr[0].endsWith("32A"))// 金额币种起息日
                {
                    if (strArr[1].matches("\\d{6}[A-Z]{3}\\d{1,15},\\d*")) {
                        String valDat = strArr[1].substring(0, 6);
                        String cur = strArr[1].substring(6, 9);
                        String amt = strArr[1].substring(9);
                        infMap.put("vludat", valDat);
                        infMap.put("amt", amt.replace(",", "."));
                        infMap.put("cur", cur);
                    }
                }

                if (strArr[0].matches("62[FM]")) {
                    // 950/940对账单的币种金额起息日
                    if (strArr[1] != null && strArr[1].matches("[DC]\\d{6}[A-Z]{3}\\d{1,15},\\d*")) {
                        String valDat = strArr[1].substring(1, 7);
                        String cur = strArr[1].substring(7, 10);
                        String amt = strArr[1].substring(10).replace(",", ".");
                        infMap.put("vludat", valDat);
                        infMap.put("amt", amt.replace(",", "."));
                        infMap.put("cur", cur);
                    } else
                        return infMap;
                }
                if (strArr[0].matches("25")) // 获取940/950里面的账号
                {
                    String act = strArr[1];
                    infMap.put("act", act);
                }
                if ("O".equals(infMap.get("direct")) && strArr[0].matches("54A") && strArr[1] != null) {
                    String actbic = strArr[1];
                    int secondLine = getLinePos(actbic);
                    if (secondLine > -1) {
                        actbic = actbic.substring(secondLine);
                        actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
                    }
                    infMap.put("actbic", actbic);
                }
                if ("O".equals(infMap.get("direct")) && strArr[0].matches("53A") && strArr[1] != null) {
                    String actbic = strArr[1];
                    int secondLine = getLinePos(actbic);
                    if (secondLine > -1) {
                        actbic = actbic.substring(secondLine);
                        actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
                    }
                    infMap.put("t53bic", actbic);
                }
                if ("I".equals(direct) && strArr[0].matches("53A") && strArr[1] != null) {
                    String actbic = strArr[1];
                    int secondLine = getLinePos(actbic);
                    if (secondLine > -1) {
                        actbic = actbic.substring(secondLine);
                        actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
                    }
                    infMap.put("actbic", actbic);
                }
                if (strArr[0].matches("50[AK]") && strArr[1] != null) {
                    int index = getLinePos(strArr[1]);
                    if (index > -1 && strArr[1].startsWith("/"))
                        infMap.put("act", strArr[1].substring(1, index));
                    if (strArr[0].endsWith("K")) {
                        if (index > -1) {
                            String nam = strArr[1].substring(index).replaceAll("^[\\r\\n]{1,2}", "");
                            infMap.put("ordnamadr", nam);
                        } else {
                            infMap.put("ordnamadr", strArr[1]);
                        }
                    }
                }
                if (strArr[0].matches("59") && strArr[1] != null) {
                    int index = getLinePos(strArr[1]);
                    String nam = strArr[1];
                    if (index > -1 && strArr[1].startsWith("/")) {
                        String act = strArr[1].substring(1, index);// 取出前面的账号
                        infMap.put("act", act);// 填入59域的账号，收益人账号
                        infMap.put("benact", act);// 查询查复使用，需区分50域的账号
                        nam = strArr[1].substring(index).replaceAll("^[\\r\\n]{1,2}", "");
                    }
                    infMap.put("bennamadr", nam);
                }
                // 下面主要对MT300起作用
                if (strArr[0].endsWith("22C")) {
                    if (!infMap.containsKey("comref")) // 如果没有填入22C栏
                    {
                        if (strArr[1].length() > 16)
                            infMap.put("comref", strArr[1].substring(0, 16));
                        else
                            infMap.put("comref", strArr[1]);
                    }
                }
                if (strArr[0].endsWith("33B") && strArr[1].length() > 0) {
                    String cur = strArr[1].substring(0, 3);
                    String amt = strArr[1].substring(3);
                    infMap.put("sellamt", amt.replace(",", "."));
                    infMap.put("sellcur", cur);

                }

                // 这里主要是对MT320起作用
                if (strArr[0].endsWith("17R")) {
                    if (!infMap.containsKey("BorL"))
                        infMap.put("BorL", strArr[1]);
                }
                if (strArr[0].endsWith("34E")) {
                    String tagN = strArr[1].substring(0, 1);
                    String interest = "";
                    if ("N".equals(tagN))
                        interest = strArr[1].substring(4);
                    else
                        interest = strArr[1].substring(3);
                    infMap.put("interest", interest.replace(",", "."));
                }
                // 公共区域
                if (strArr[0].endsWith("30V")) {
                    if (!infMap.containsKey("m3xValDate"))
                        infMap.put("m3xValDate", strArr[1]);
                }

                if (strArr[0].endsWith("32B")) {
                    String cur = strArr[1].substring(0, 3);
                    String amt = strArr[1].substring(3);
                    infMap.put("buyamt", amt.replace(",", "."));
                    infMap.put("buycur", cur);

                }
            }
        }
        return infMap;
    }

    /*
     * @param msg：报文字符串 对报文信息的基本获取，如果是NCK/ACK报文则mty为NCK/ACK，如有附带报文，则附带的报文类型由emty记录
     */
    public static Map<String, String> getSwfMsgInfoViaMsg(String msg) {
        if (msg == null || msg.trim().length() == 0)
            return new HashMap<String, String>();
        Map<Integer, String> headers = anlyMsgHead(msg);
        return getSwfMsgInfoViaMsg(headers);
    }


    /***
     * 解析TD的格式报文
     * @param msg
     * @return
     */
    public static Map<String, String> getSwfMsgInfoViaTDMsg(String msg) {
        Map<String, String> bscInfo = new HashMap<String, String>();
        String reg = ":MT:(\\d{3})[\\r\\n]{1,2}:IO:(\\w{2,11})[\\r\\n]{1,2}:II:(\\w{2,11})[\\r\\n]{1,2}:MP:(\\w)";
        Matcher m = Pattern.compile(reg).matcher(msg);
        if (!m.find())
            return bscInfo;// 错误的格式
        //bscInfo.put("mty", m.group(1));
        bscInfo.put("sndbic", m.group(3));
        bscInfo.put("rcvbic", m.group(2));
        bscInfo.put("prt", m.group(4));

        int idx = msg.indexOf(":EOH:", m.end());
        String tdmsgHead = msg.substring(0, idx);
        int begIndex = m.end(4);
        reg = ":111:(\\d{3})(?=\\r|\\n)";
        String restStr = tdmsgHead.substring(begIndex);
        Matcher m2 = Pattern.compile(reg).matcher(restStr);
        if (m2.find()) {
            bscInfo.put("t111", m2.group(1).trim());
        }
        reg = ":121:([\\s\\S]+)(?=\\r|\\n)";
        m2 = Pattern.compile(reg).matcher(restStr);
        if (m2.find()) {
            bscInfo.put("t121", m2.group(1).trim());
        }

        bscInfo.put("tdmsgHead", tdmsgHead);//存头，方便前端组报
        //取111，121

        if (tdmsgHead.indexOf(":119:COV") > -1) {
            bscInfo.put("mty", m.group(1) + "COV");
        } else
            bscInfo.put("mty", m.group(1));


        msg = msg.substring(idx + ":EOH:".length());
        if (msg.endsWith("-"))
            msg = msg.substring(0, msg.length() - 1);
        Map<Integer, String> headers = new HashMap<Integer, String>();
        headers.put(4, msg);
        Map<String, String> infoMap = getSwfMsgInfoViaMsg(headers);
        infoMap.put("mty", bscInfo.get("mty"));
        bscInfo.putAll(infoMap);
        return bscInfo;
    }

    public static SWFMessage loadSwiftFile(String path) {
        return loadSwiftMessage(readFull(path));
    }

    public static SWFMessage loadSwiftMessage(String message) {
        SWFMessage swf;
        Map<Integer, String> headers;
        Map<String, String> bscInfo;
        List<String[]> tags;
        if (message.startsWith(":MT:"))   // TD内部报文
        {
            bscInfo = getSwfMsgInfoViaTDMsg(message);
            swf = MessageFormat.getSWFMessage(bscInfo.get("mty"));
            if (swf != null) {
                swf.setBscInfo(bscInfo);
                int index = message.indexOf(":EOH:") + ":EOH:".length();
                int lastIndex = message.lastIndexOf("-");
                if (lastIndex > 0)
                    message = message.substring(index, lastIndex).trim();
                else
                    message = message.substring(index);
                tags = msgTxtAnly(message);
                loadOldSwiftMessage(swf, tags);
            }
        } else {
            headers = anlyMsgHead(message);
            bscInfo = getSwfMsgInfoViaMsg(headers);
            swf = MessageFormat.getSWFMessage(bscInfo.get("mty"));
            if (swf != null) {
                swf.setHeaders(headers);
                swf.setBscInfo(bscInfo);
                tags = msgTxtAnly(headers.get(4));
                String tagsCombo = getTagsStr(tags);
                loadSwiftMessage(swf, tagsCombo, tags);
            }
        }
        return swf;
    }

    private static void loadOldSwiftMessage(MessageArea area, List<String[]> tags) {
        String tagsCombo = getTagsStr(tags);
        int result = loadSwiftMessage(area, tagsCombo, tags);
        if (result < 0) {
            List<MessageArea> fields = ((SWFMessage) area).getFields();
            Map<Integer, TagLine> flatModel = ((SWFMessage) area).getFlatModel();
            fields.clear();
            flatModel.clear();
            for (int i = 0; i < tags.size(); i++) {
                String[] tag = tags.get(i);
                TagLine tagLine = new TagLine();
                tagLine.setName(tag[0]);
                tagLine.setTno(i + 1);
                String desp = Inis.getIniStr("swtovr20.ini", "M" + ((SWFMessage) area).getMtType(), tag[0]);
                if (StringUtils.isEmpty(desp))
                    desp = Inis.getIniStr("swtsup20.ini", "SWIFT-FIOTAG", tag[0]);
                tagLine.setDesp(desp);
                tagLine.setValue(tag[1]);
                flatModel.put(i, tagLine);
                if (tag[0].matches("15[A-Z]")) {
                    SEQList seqList = new SEQList();
                    seqList.setLoaded(true);
                    SEQ seq = new SEQ();
                    seq.setName("Sequence " + tag[0].charAt(2));
                    tagLine.parent = seqList;
                    seq.addSubArea(tagLine);
                    seqList.addSubArea(seq);
                    area.addSubArea(seqList);
                } else {
                    if (fields.isEmpty()) {
                        area.addSubArea(tagLine);
                    } else {
                        MessageArea lastMessageArea = fields.get(fields.size() - 1);
                        if (lastMessageArea.getType() == MessageArea.TAG) {
                            area.addSubArea(tagLine);
                        } else if (lastMessageArea.getType() == MessageArea.SEQLIST) {
                            SEQList lastSEQList = (SEQList) lastMessageArea;
                            MessageArea seq = lastSEQList.getFields().get(0);
                            seq.addSubArea(tagLine);
                        }
                    }
                }
            }
        }
    }


    private static int loadSwiftMessage(MessageArea area, String tagsCombo, List<String[]> tags) {
        StringBuilder buf = new StringBuilder();
        generReg(area, buf);
        String reg = buf.toString();
        Matcher m = Pattern.compile(reg).matcher(tagsCombo);
        if (!m.find() || m.start() == m.end()){
            log.error("解析报文失败:栏位格式不符，reg={},tags={}",reg,tagsCombo);
            return -1; //栏位格式不符
        }
        List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
        for (MessageArea item : fieldList) {
            if (item.getType() == MessageArea.TAG) {
                //直接捕获对应分组
                TagLine tag = (TagLine) item;
                String grpName = "T" + tag.getTno();
                String value = m.group(grpName);
                if (value == null)
                    continue;
                String[] valArr = value.split(",");
                //tag.setName(valArr[0]);
                if (tag.getName().endsWith("a")) {
                    TagLine tag2 = TagFormat.getTagLine(valArr[0]);
                    tag.cellList = tag2.cellList;
                    tag.options = tag2.options;
                    tag.setName(valArr[0]);
                    tag.setPattern(tag2.getPattern());
                    tag.setAnalyzeReg(tag2.getAnalyzeReg());
                    tag.setMaxCnt(tag2.getMaxCnt());

//					  tag2.setDesp(tag.getDesp());
//					  tag2.setTno(tag.getTno());
//					  tag2.setName(valArr[0]);
//					  tag2.setStatus(tag.getStatus());
//					  tag2.getSuffix().addAll(tag.getSuffix());
//					  tag = tag2;
//					  fieldList.set(i, tag); //置换新的栏位
                }
                int idx = Integer.parseInt(valArr[1].substring(0, valArr[1].length() - 1));
                tag.setValue(tags.get(idx)[1]);//还要考虑值分解
            } else if (item.getType() == MessageArea.CYCLIST) {
                String grpName = String.valueOf("C" + item.getName());
                String value = m.group(grpName); //新的块级
                if (value == null || value.length() == 0)
                    continue;
                ((AbstractMessageArea) item).setLoaded(true);
                MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
                int offset = 0;
                do {
                    ((AbstractMessageArea) cp).setLoaded(true);
                    offset = loadSwiftMessage(cp, value, tags);
                    if (offset <= 0)
                        break;

                    if (offset >= value.length())
                        break;    //提前终止，避免不必要的空循环
                    cp = ((AbstractMessageArea) item).getPattern().clone();
                    item.addSubArea(cp);
                    value = value.substring(offset);
                }
                while (true);
            } else if (item.getType() == MessageArea.SEQLIST) {
                String grpName = "S" + item.getName();
                String value = m.group(grpName); //新的块级
                if (value == null || value.length() == 0)
                    continue;
                ((AbstractMessageArea) item).setLoaded(true);
                MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
                int offset = 0;
                do {
                    ((AbstractMessageArea) cp).setLoaded(true);
                    offset = loadSwiftMessage(cp, value, tags);
                    if (offset <= 0)
                        break;

                    if (offset >= value.length())
                        break;    //提前终止，避免不必要的空循环
                    cp = ((AbstractMessageArea) item).getPattern().clone();
                    item.addSubArea(cp);
                    value = value.substring(offset);
                }
                while (true);
            }
        }
        return m.end();
    }

    public static SWFMessage loadCheckSwiftMessage(String message) {
        Map<Integer, String> headers = null;

        Map<String, String> bscInfo = null;

        headers = anlyMsgHead(message);
        bscInfo = getSwfMsgInfoViaMsg(headers);

        //取出报文类型
        String mty = bscInfo.get("mty");
        // System.out.println("---------" + mty);
        // 取出了xlsx中的 对应mty 的 结构
        SWFMessage swf = MessageFormat.getSWFMessage(mty);


        swf.setHeaders(headers);
        swf.setBscInfo(bscInfo);
        // 这的tags有值
        List<String[]> tags = msgTxtAnly(headers.get(4));
        String tagsCombo = getTagsStr(tags);

        // sf2中的文件匹配
        loadCheckSwiftMessage(swf, tagsCombo, tags);

        swf.setTags(tags);
        return swf;
    }

    private static int loadCheckSwiftMessage(MessageArea area, String tagsCombo, List<String[]> tags) {
        StringBuilder buf = new StringBuilder();
        generReg(area, buf);
        String reg = buf.toString();
        Matcher m = Pattern.compile(reg).matcher(tagsCombo);

        if (!m.find() || m.start() == m.end()) {
            // 什么格式栏位不符  需要什么样的格式，现在的格式是什么样
            System.out.println("栏位格式不符  格式:" + reg);
            return -1; //栏位格式不符
        }

        List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
        for (int i = 0; i < fieldList.size(); i++) {
            MessageArea item = fieldList.get(i);
            if (item.getType() == MessageArea.TAG) {
                //直接捕获对应分组
                TagLine tag = (TagLine) item;
                String grpName = "T" + String.valueOf(tag.getTno());
                String value = m.group(grpName);
                if (value == null)
                    continue;
                String[] valArr = value.split(",");
                //tag.setName(valArr[0]);
                if (tag.getName().endsWith("a")) {
                    TagLine tag2 = TagFormat.getTagLine(valArr[0]);

                    tag.cellList = tag2.cellList;
                    tag.options = tag2.options;
                    tag.setName(valArr[0]);
                    tag.setPattern(tag2.getPattern());
                    tag.setAnalyzeReg(tag2.getAnalyzeReg());
                    tag.setMaxCnt(tag2.getMaxCnt());

//					  tag2.setDesp(tag.getDesp());
//					  tag2.setTno(tag.getTno());
//					  tag2.setName(valArr[0]);
//					  tag2.setStatus(tag.getStatus());
//					  tag2.getSuffix().addAll(tag.getSuffix());
//					  tag = tag2;
//					  fieldList.set(i, tag); //置换新的栏位
                }
                int idx = Integer.parseInt(valArr[1].substring(0, valArr[1].length() - 1));
                tag.setValue(tags.get(idx)[1]);//还要考虑值分解
            } else if (item.getType() == MessageArea.CYCLIST) {
                String grpName = String.valueOf("C" + item.getName());
                String value = m.group(grpName); //新的块级
                if (value == null || value.length() == 0)
                    continue;

                MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
                int offset = 0;
                do {
                    offset = loadSwiftMessage(cp, value, tags);
                    if (offset <= 0)
                        break;

                    if (offset >= value.length())
                        break;    //提前终止，避免不必要的空循环
                    cp = ((AbstractMessageArea) item).getPattern().clone();
                    item.addSubArea(cp);
                    value = value.substring(offset);
                }
                while (true);
            } else if (item.getType() == MessageArea.SEQLIST) {
                String grpName = String.valueOf("S" + item.getName());
                String value = m.group(grpName); //新的块级
                if (value == null || value.length() == 0)
                    continue;

                MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
                int offset = 0;
                do {
                    offset = loadSwiftMessage(cp, value, tags);
                    if (offset <= 0)
                        break;

                    if (offset >= value.length())
                        break;    //提前终止，避免不必要的空循环
                    cp = ((AbstractMessageArea) item).getPattern().clone();
                    item.addSubArea(cp);
                    value = value.substring(offset);
                }
                while (true);
            }
        }
        return m.end();
    }

    private static String getTagsStr(List<String[]> tags) {
        StringBuilder buf = new StringBuilder();
        int cnt = 0;
        for (String[] item : tags) {
            //System.out.println(item[0]+"-----"+item[1]);
            buf.append(item[0] + "," + cnt);
            cnt++;
            buf.append(";");
        }
        return buf.toString();
    }

    public static void generReg(MessageArea area, StringBuilder sb) {

        if (area.getType() == MessageArea.TAG) {
            TagLine tag = (TagLine) area;
            sb.append("(?<T" + tag.getTno() + ">");
            if (tag.getSuffix().size() != 0) {
                sb.append(tag.getName().substring(0, 2));
                sb.append('[');
                boolean hasOpt = false;
                for (String item : tag.getSuffix()) {
                    if (item.length() == 2)
                        hasOpt = true;
                    else
                        sb.append(item.charAt(2));
                }
                sb.append(']');
                if (hasOpt)
                    sb.append('?');

            } else
                sb.append(tag.getName());
            sb.append(",\\d{1,3};)");
            if ("O".equals(tag.getStatus()))
                sb.append('?');
            return;
        }
        String defaultReg = ((AbstractMessageArea) area).getAnlyReg();
        if (defaultReg != null) {
            sb.append(defaultReg);
            return;
        }

        if (area instanceof SWFMessage) {
            for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
                generReg(item, sb);
            }
        } else if (area.getType() == MessageArea.CYCLIST) {
            StringBuilder buf = new StringBuilder();
            buf.append('(');
            buf.append("?<C" + area.getName() + ">");
            buf.append('(');
            for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
                generReg(item, buf);
            }
            buf.append(")*"); //块级区域的可选
            buf.append(')');
            ((AbstractMessageArea) area).setAnlyReg(buf.toString());
            sb.append(buf);
        } else if (area.getType() == MessageArea.SEQLIST) {
            StringBuilder buf = new StringBuilder();
            buf.append('(');
            buf.append("?<S" + area.getName() + ">");
            buf.append('(');
            for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
                generReg(item, buf);
            }
            SEQList seqlst = (SEQList) area;
            if (seqlst.getCyc() > 0)
                buf.append(")+"); //块级区域的可选
            else
                buf.append(')');
            buf.append(')');
            if ("O".equals(seqlst.getOm()))
                buf.append('?');
            ((AbstractMessageArea) area).setAnlyReg(buf.toString());
            sb.append(buf);
        } else if (area.getType() == MessageArea.CYC || area.getType() == MessageArea.SEQ) {
            StringBuilder buf = new StringBuilder();
            for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
                generReg(item, buf);
            }
            ((AbstractMessageArea) area).setAnlyReg(buf.toString());
            sb.append(buf);
        }
    }

    public static String generReg(SWFMessage swf) {
        StringBuilder sb = new StringBuilder();
        generReg(swf, sb);
        return sb.toString();
    }


    public static String readFull(String path) {
        try {
            FileReader reader = new FileReader(path);
            char[] buf = new char[1024];
            try {
                StringBuilder sb = new StringBuilder();
                int len = -1;
                while ((len = reader.read(buf)) != -1) {
                    sb.append(buf, 0, len);
                }
                reader.close();
                return sb.toString();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
//		  SWFMessage swf =  MessageFormat.getSWFMessage("202COV");
//		  System.out.println(swf.toFormatJSON());
//		  MessageFormat.loadSWFMessage();

//        String path = "/Volumes/FUKAI/00034868.txt";
//        String msg = readFull(path);

        StringBuffer msg = new StringBuffer();

        // 103
        msg.append("{1:F01PSBCCNBJAXXX0000000000}{2:I103CIPSCNSHXXXXN}{3:{121:07a03b1e-e20c-4379-8dc1-8cd7c8fcafda}}{4:\n" +
                ":20:SendersReference\n" +
                ":13C:TimeIndication\n" +
                ":23B:BankOperationCode\n" +
                ":23E:InstructionCode\n" +
                ":26T:TransactionTypeCode\n" +
                ":32A:ValueDateCurrencyInterbankSettledAmount\n" +
                ":33B:CurrencyInstructedAmount\n" +
                ":36:ExchangeRate\n" +
                ":50B:/B/6226TEST0001\n" +
                "WHYHCNHBXXX\n" +
                ":51A:SendingInstitution\n" +
                ":52D:/D/1234-5678\n" +
                "WHYHCNHBXXX\n" +
                ":54A:/54a/5345-6756\n" +
                "WHYHCNHBXXX\n" +
                ":55A:/55a/1234-5678\n" +
                "WHYHCNHBXXX\n" +
                ":56A:/56a/5634-3534-7654-6543\n" +
                "WHYHCNHRXXX\n" +
                ":57A:/57a/3450-2432-4359-3535-5935-3523\n" +
                "WHYHCNHDXXX\n" +
                ":59A:/59a/6226TEST34530004\n" +
                "WHYHCNHHXXX\n" +
                ":70:RemittanceInformation\n" +
                ":71A:DetailsofCharges\n" +
                ":71F:SendersCharges\n" +
                ":71G:ReceiversCharges\n" +
                ":72:SendertoReceiverInformation\n" +
                ":77B:RegulatoryReporting\n" +
                "-}");

        // 202
//        msg.append("{1:F010000000000}{2:I202N}{3:{121:76539689-6e7d-40d7-83a1-ebe0ab14d964}}{4:\n" +
//                ":13C:/0001TEST/1234+5678\n" +
//                ":20:111\n" +
//                ":21:2222\n" +
//                ":32A:123456AAA321\n" +
//                ":52A:/2222-4321\n" +
//                "WHYHCNHBX01\n" +
//                ":53D:/1234-4321\n" +
//                "WJHGJGJ\n" +
//                ":54B:/3333-4321\n" +
//                "JHGJGJJHNBMN\n" +
//                ":56D:/4444-4321\n" +
//                "WJHGJGJ\n" +
//                ":57D:/7777-4321\n" +
//                "WJHGJGJ\n" +
//                ":58D:/8888-4321\n" +
//                "WJHGJGJ\n" +
//                ":72:/002TEST/12345\n" +
//                "/002TEST/5555\n" +
//                "-}");

        // 700
//        msg.append("{1:F01PSBCCNBJAXXX0000000000}{2:I700CIPSCNSHXXXXN}{4:\n" +
//                ":27:1/1\n" +
//                ":40A:1111\n" +
//                ":20:LC00001TEST\n" +
//                ":51A:/A/1234-5678\n" +
//                "WHYHCNHBXXX\n" +
//                "-}");


        SWFMessage swf = loadSwiftMessage(msg.toString());
//		  String value =((TagLine)swf.getFields().get(2)).getValue();
//		  System.out.println(value);
        // System.out.println(swf.toJSON());
        //System.out.println(value.matches(TagFormat.TagMap.get("79").toAnalyzeReg()));
    }

}
