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

import com.brilliance.mda.runtime.mda.util.MdaUtils;
import com.brilliance.isc.bo.Pta;
import com.brilliance.isc.common.cache.pta.PtaCacheService;
import com.brilliance.isc.common.component.PtsptaToolComponent;
import com.brilliance.isc.common.context.SpringEnvContext;
import com.brilliance.isc.common.vo.PtsptaVo;
import com.brilliance.isc.swift.objmtconvert.util.FormatUtils;
import com.brilliance.isc.swift.swifteditor.tag.message.MessageArea;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

public class TagLine implements MessageArea {
    private final int type = TAG;
    public List<TagCell> cellList = new ArrayList<TagCell>();
    public List<int[]> options = new ArrayList<int[]>();
    public MessageArea parent;
    public boolean onlyOne;
    String analyzeReg = null;
    private String pattern;
    private String value;
    private String tagName;
    private String status;
    private int maxCnt = 0;
    private int tno = 0;
    private String desp = "";
    private List<String> suffix = new ArrayList<String>();

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public void add(TagCell cell) {
        cellList.add(cell);
    }

    public void addOptions(int[] points) {
        options.add(points);
    }

    public void fillOption(int index, int point) {
        if (options.size() == 0) {
            //System.err.println("error pattern:" + this.getName() + "----" + this.getPattern());
            return;
        }
        options.get(index)[1] = point;
    }

    public void fillLastOption(int point) {
        if (options.size() == 0) {
            System.err.println("error pattern:" + this.getName() + "----" + this.getPattern());
            return;
        }
        options.get(options.size() - 1)[1] = point;
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

    public String getSourceValue() {
        return this.value;
    }

    /***
     * 返回组装后的swift域值
     * @return
     */
    public String getValue() {

        StringBuilder sb = new StringBuilder();
        this.toSwfMessage(sb);
        String val = sb.toString();
        if (val == null || val.isEmpty()) {
            //展报的时候有值
            return value;
        }
        return val;
    }

    public void setValue(String value) {
        if (value == null) {
            this.value = null;
            return;
        }
        if (this.value != null && this.value.equals(value))
            return;
        this.value = value;
        if (this.cellList.size() == 1) {
            this.cellList.get(0).setValue(value);
        } else {
            this.fillCellValue();
        }
    }

    /***
     * 返回组装后人类查看的域值
     * @return
     */
    public String getValueForHuman() {
        StringBuilder sb = new StringBuilder();
        this.toHumanMessage(sb);
        String val = sb.toString();

        if (val == null || val.isEmpty()) {
            //展报的时候有值
            return value;
        }

        return val.trim();
    }

    public String getCellValue(int position) {
        for (TagCell cell : this.cellList) {
            if (cell.cnt == position)
                return cell.value;
        }
        return null;
    }

    /***
     * 将栏位值填充到指定的栏位中去
     */
    private void fillCellValue() {
        Map<Integer, String> subValues = TagAnalyzer.analyze(this, value);
        if (subValues == null)
            return;
        for (Map.Entry<Integer, String> entry : subValues.entrySet()) {
            int cnt = entry.getKey();
            for (TagCell cell : cellList) {
                if (cell.cnt == cnt) {
                    cell.setValue(entry.getValue());
                    break;
                }
            }
        }
    }

    public TagLine clone() {
        TagLine cp = new TagLine();
        for (TagCell cell : cellList) {
            cp.add(cell.clone());
        }
        for (int[] option : options) {
            int[] cpopt = Arrays.copyOf(option, 2);
            cp.addOptions(cpopt);
        }
        cp.setValue(value);
        cp.setPattern(pattern);
        cp.setDesp(desp);
        cp.setMaxCnt(maxCnt);
        cp.setSuffix(this.suffix);
        cp.setTno(tno);
        cp.setName(this.getName());
        cp.setStatus(this.getStatus());
        cp.analyzeReg = this.analyzeReg;
        return cp;
    }

    public void toSwfMessage(StringBuilder sb) {
        boolean isEmpty = true;
        TagCell lastCell = null;
        List<TagCell> cloneCell = new ArrayList(this.cellList);
        for (int[] opt : options) {
            AtomicInteger cnt = new AtomicInteger();
            cloneCell.subList(opt[0], opt[1]).forEach(cell -> {
                if (cell != null && !"CONST".equals(cell.type) && cell.value != null) {
                    cnt.incrementAndGet();
                }
            });
            //区间都无值
            if (cnt.intValue() == 0) {
                IntStream.range(opt[0], opt[1]).forEach(i -> {
                    cloneCell.set(i, null);
                });
            }
        }
        for (TagCell cell : cloneCell) {
            if (cell == null) {
                continue;
            }
            if ("CONST".equals(cell.type)) {
                lastCell = cell;
                if ("CRLF".equals(cell.content)) {
                    sb.append("\r\n");
                } else {
                    sb.append(cell.content);
                }
            } else if (cell.value != null) {
                isEmpty = false;
                if ("d".equals(cell.type) || ("AMOUNT".equals(cell.content) && "FUNC".equals(cell.type))) {
                    if (cell.value.indexOf(".") > 0) {
                        sb.append(cell.value.replace(".", ","));
                    } else {
                        sb.append(cell.value + ",");
                    }
                } else {
                    if (lastCell != null && cell.value.startsWith(lastCell.content)) {
                        sb.append(cell.value.substring(lastCell.content.length()));
                    } else {
                        sb.append(cell.value);
                    }
                }
                lastCell = null;
            }
        }
        if (isEmpty) {
            sb.delete(0, sb.length());
        }
    }

    public void toHumanMessage(StringBuilder sb) {
        boolean isEmpty = true;
        TagCell lastCell = null;
        List<TagCell> cloneCell = new ArrayList(this.cellList);
        for (int[] opt : options) {
            AtomicInteger cnt = new AtomicInteger();
            List<TagCell> tagCells = cloneCell.subList(opt[0], opt[1]);
            int size = tagCells.size();
            tagCells.forEach(cell -> {
                if (cell != null) {
                    if (!"CONST".equals(cell.type) && cell.value != null) {
                        cnt.incrementAndGet();
                    } else if ("CONST".equals(cell.type) && size == 1) {
                        //单独一个常量，譬如回车换行，需要考虑前一个和后一个值是否存在，如果存在，则依然需要
                        int pre = opt[0] - 1;
                        int aft = opt[0] + 1;
                        if (pre > -1 && aft < this.cellList.size()) {
                            if (this.cellList.get(pre).value != null && this.cellList.get(aft).value != null) {
                                cnt.incrementAndGet();
                            }
                        }
                    }
                }
            });
            //区间都无值
            if (cnt.intValue() == 0) {
                IntStream.range(opt[0], opt[1]).forEach(i -> {
                    cloneCell.set(i, null);
                });
            }
        }
        boolean rmvSlash = false;
        for (int index = 0; index < cloneCell.size(); index++) {
            TagCell cell = cloneCell.get(index);
            if (cell == null) {
                continue;
            }
            if ("CONST".equals(cell.type)) {
                lastCell = cell;
                if ("CRLF".equals(cell.content)) {
                    sb.append("\r\n");
                } else if ("/".equals(cell.content) && rmvSlash) {
                    //不加斜杠了
                    rmvSlash = false;
                } else {
                    sb.append(cell.content);
                }
            } else if (cell.value != null) {
                isEmpty = false;
                if ("d".equals(cell.type) || ("AMOUNT".equals(cell.content) && "FUNC".equals(cell.type))) {
                    sb.append(FormatUtils.fmtAmount(new BigDecimal(cell.value), null));
                } else if ("SWIFTBIC".equals(cell.content) && "FUNC".equals(cell.type)) {
                    //提前到这里进行BIC转换，之前是统一在ActnoBicAdrTagXXX进行处理，但是遇到字段内容除了BIC的就不能处理啦
                    if (sb.length() > 0 && sb.charAt(0) == '/') {
                        sb.deleteCharAt(0);
                    }
                    sb.append(loadBICName(cell.value));
                } else if ("DC".equals(cell.content) && "FUNC".equals(cell.type)) {
                    //删除斜杠
                    sb.setLength(sb.length() - 1);
                    rmvSlash = true;
                    sb.append(cell.value);
                } else {
                    if (lastCell != null && cell.value.startsWith(lastCell.content)) {
                        sb.append(cell.value.substring(lastCell.content.length()));
                    } else {
                        sb.append(cell.value);
                    }
                }
                if ("FUNC".equals(cell.type) && cell.content.matches("AMOUNT|DATE2|CUR|DC")) {
                    sb.append("\t");
                }
                lastCell = null;
            }
        }
        if (isEmpty) {
            sb.delete(0, sb.length());
        }
    }

    public String loadBICName(String param) {
        if (MdaUtils.isEmpty(param)) {
            return "";
        }
        //逻辑终端地址 转换一下
        if (param.length() == 12) {
            param = param.substring(0, 8) + param.substring(9);
        }
        if (param.length() > 11) {
            return param;
        }
        PtaCacheService ptaCacheService = SpringEnvContext.getBean(PtaCacheService.class);
        Pta pta = ptaCacheService.selectByPtyextkeyAndUsg(param, "MAA");
        if (pta != null) {
            PtsptaToolComponent ptsptaToolComponent = SpringEnvContext.getBean(PtsptaToolComponent.class);
            PtsptaVo ptspta = ptsptaToolComponent.getPtsptaFromPtaINR(pta.getInr());
            return (param + " BIC identified as:\r\n" + ptspta.getAdrblk()).toUpperCase();
        } else {
            return param;
        }
    }

    public String getName() {
        return tagName;
    }

    public void setName(String name) {
        this.tagName = name;
    }

    public void addSubArea(MessageArea sub) {

    }

    public boolean isEnd() {
        return true;
    }

    public int getType() {
        return type;
    }

    /***
     * 返回解析字符串
     * @return
     */
    public String toAnalyzeReg() {
        StringBuilder sb = new StringBuilder();
        int cnt = 0;
        int hasOpen = 0;
        for (TagCell cell : cellList) {
            for (int[] opt : options) {
                if (cnt == opt[0]) {
                    sb.append('(');
                    hasOpen++;
//					break;
                } else if (cnt == opt[1]) {
                    sb.append(")?");
                    hasOpen--;
//					break;
                }
            }
            cnt++;
            sb.append(cell.toReg());
        }
        if (hasOpen > 0)
            sb.append(")?");
        return sb.toString();
    }

    //分段校验信息
    public Map<String, Object> toSegRegMap() {
//        List<String> valueList = new ArrayList<>();
//        if("32|33|34".contains(tagName.substring(0,2))){
//            if(tagName.contains("A")||tagName.contains("D")){
//                valueList.add("date");
//                valueList.add("currency");
//                valueList.add("amount");
//            }
//            if(tagName.contains("B")){
//                valueList.add("currency");
//                valueList.add("amount");
//            }
//            if(tagName.contains("K")){
//                valueList.add("dayMonth");
//                valueList.add("numberOfDaysMonths");
//                valueList.add("code");
//                valueList.add("currency");
//                valueList.add("amount");
//            }
//        }
//        if("60|62|64|65".contains(tagName.substring(0,2))){
//            valueList.add("dcMark");
//            valueList.add("date");
//            valueList.add("currency");
//            valueList.add("amount");
//        }
//        if(tagName.contains("90")){
//            valueList.add("number");
//            valueList.add("currency");
//            valueList.add("amount");
//        }
//        if(tagName.contains("24")){
//            valueList.add("code");
//            valueList.add("address");
//        }
//        if(tagName.contains("40")){
//            valueList.add("type");
//            valueList.add("code");
//        }
//        if(tagName.contains("41")){
//            if(tagName.contains("A")){
//                valueList.add("bic");
//                valueList.add("code");
//            }
//            if(tagName.contains("D")){
//                valueList.add("address");
//                valueList.add("code");
//            }
//        }
//        if (tagName.contains("25")){
//            if(tagName.contains("P")){
//                valueList.add("acctno");
//                valueList.add("bic");
//            }else {
//                valueList.add("acctno");
//            }
//        }
//        if(tagName.contains("50")){
//            if(tagName.contains("A")||tagName.contains("G")){
//                valueList.add("acctno");
//                valueList.add("bic");
//            }
//            if(tagName.contains("F")){
//                valueList.add("partyIdentifier");
//                valueList.add("address");
//            }
//            if(tagName.contains("K")){
//                valueList.add("acctno");
//                valueList.add("address");
//            }
//        }
//        if(tagName.contains("59")){
//            if("59".equals(tagName)){
//                valueList.add("acctno");
//                valueList.add("address");
//            }
//            if(tagName.contains("A")){
//                valueList.add("acctno");
//                valueList.add("bic");
//            }
//            if(tagName.contains("F")){
//                valueList.add("acctno");
//                valueList.add("address");
//            }
//        }
//        if("51|52|53|54|55|56|57|58|42".contains(tagName.substring(0,2))){
//            if(tagName.contains("A")){
//                valueList.add("info");
//                valueList.add("partyIdentifier");
//                valueList.add("bic");
//            }
//            if(tagName.contains("B")){
//                valueList.add("info");
//                valueList.add("partyIdentifier");
//                valueList.add("location");
//            }
//            if(tagName.contains("D")){
//                valueList.add("info");
//                valueList.add("partyIdentifier");
//                valueList.add("address");
//            }
//        }
//        if(tagName.contains("71")){
//            if(tagName.contains("N")){
//                valueList.add("code");
//                valueList.add("narrative");
//            }
//        }
        Map<String, Object> set = new HashMap<String, Object>();
//		int cnt = 0;
        int j = 0;
        for (int cnt = 0; cnt < this.cellList.size(); cnt++) {
            TagCell cell = this.cellList.get(cnt);
            if (cell.cnt < 0)
                continue;
            String key = "s" + cell.cnt;
            HashMap<String, Object> info = new HashMap<String, Object>();
            set.put(key, info);
            info.put("reg", cell.toReg(false, false));
            info.put("type", cell.type);
            info.put("content", cell.content);
            info.put("option", "M");
            info.put("fixed", cell.fixed);
            info.put("length", cell.length);
            info.put("line", cell.line);
//            if(valueList.size()>0){
//                info.put("area", valueList.get(j));
//                j++;
//            }
            for (int[] opt : options) {
                if (cnt >= opt[0] && cnt < opt[1]) {
                    info.put("option", "O");
                }
            }
        }
        return set;
    }

    public String getAnalyzeReg() {
        if (analyzeReg == null)
            analyzeReg = this.toAnalyzeReg();
        return analyzeReg;
    }

    public void setAnalyzeReg(String analyzeReg) {
        this.analyzeReg = analyzeReg;
    }

    public int getMaxCnt() {
        return maxCnt;
    }

    public void setMaxCnt(int maxCnt) {
        this.maxCnt = maxCnt;
    }

    public int getTno() {
        return tno;
    }

    public void setTno(int tno) {
        this.tno = tno;
    }

    public String getDesp() {
        return desp;
    }

    public void setDesp(String desp) {
        this.desp = desp;
    }

    public List<String> getSuffix() {
        return this.suffix;
    }

    public void setSuffix(List<String> tagSuffix) {
        this.suffix.clear();
        this.suffix.addAll(tagSuffix);
    }

    public Map<String, String> getIndexMap() {
        Map<String, String> indexMap = new HashMap<String, String>();
        for (TagCell cell : cellList) {
            if (cell.cnt > 0 && cell.value != null)
                indexMap.put("s" + cell.cnt, cell.value);
        }
        return indexMap;
    }

}
