package com.yem.wm.bc.change.from;

import java.util.*;

import com.yem.wm.bc.change.common.consts.RestrictedAttributeMap;
import com.yem.wm.bc.common.CommonUtils;
import com.yem.wm.bc.common.enums.EnableStatusEnum;
import com.yem.wm.bc.common.enums.StatusEnum;
import kd.bos.bill.OperationStatus;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.IDataEntityType;
import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.dataentity.serialization.DcBinder;
import kd.bos.dataentity.serialization.DcJsonSerializer;
import kd.bos.dataentity.serialization.ListDcxmlBinder;
import kd.bos.dataentity.serialization.SerializationUtils;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.designer.botp.EntityParseHelper;
import kd.bos.entity.*;
import kd.bos.entity.botp.CRPlugin;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.datamodel.events.ChangeData;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.entity.filter.FilterCondition;
import kd.bos.entity.property.BigIntProp;
import kd.bos.entity.property.LongProp;
import kd.bos.entity.tree.TreeNode;
import kd.bos.form.CloseCallBack;
import kd.bos.form.FormShowParameter;
import kd.bos.form.ShowType;
import kd.bos.form.control.AbstractGrid;
import kd.bos.form.control.Control;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.control.FilterGrid;
import kd.bos.form.control.events.*;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.events.ClosedCallBackEvent;
import kd.bos.form.events.HyperLinkClickEvent;
import kd.bos.form.events.HyperLinkClickListener;
import kd.bos.form.field.BasedataEdit;
import kd.bos.form.field.events.BeforeF7SelectEvent;
import kd.bos.form.field.events.BeforeF7SelectListener;
import kd.bos.form.operate.AbstractOperate;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.form.plugin.IFormPlugin;
import kd.bos.lang.Lang;
import kd.bos.list.ListShowParameter;
import kd.bos.metadata.dao.MetaCategory;
import kd.bos.metadata.dao.MetadataDao;
import kd.bos.metadata.entity.EntityItem;
import kd.bos.metadata.entity.EntityMetadata;
import kd.bos.metadata.entity.validation.ConditionValidation;
import kd.bos.metadata.treebuilder.FormTreeBuilder;
import kd.bos.metadata.treebuilder.PropTreeBuildOption;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.MetadataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import org.apache.commons.lang.ArrayUtils;

/**
 * @author 夜子
 * @ClassName ChangeModelPlugin
 * @description: 变更模板表单插件
 * @date 2023年07月07日
 * @version: 1.0
 */
public class ChangeModelPlugin extends AbstractFormPlugin implements
        BeforeF7SelectListener,
        ItemClickListener,
        HyperLinkClickListener,
        RowClickEventListener {

    @Override
    public void beforeBindData(EventObject e) {
        super.beforeBindData(e);
        this.setFilterGrid();
    }

    @Override
    public void afterBindData(EventObject e) {
        int validrowcount;
        super.afterBindData(e);
        this.initAreaConditionToFilterGrid();
        if (this.getModel().getValue("xbill") != null) {
            this.buildMetaContext((Object) ((DynamicObject) this.getModel().getValue("xbill")));
        }
        if ((validrowcount = this.getModel().getEntryEntity("validentity").getRowCount()) > 0) {
            IDataModel model = this.getModel();
            for (int i = 0; i < validrowcount; ++i) {
                String validjson = model.getValue("validconditionjson_tag", i).toString();
                if (StringUtils.isBlank((CharSequence) validjson))
                    continue;
                Map rule = (Map) SerializationUtils.fromJsonString((String) validjson, Map.class);
                model.setValue("isenable", (Object) ((Boolean) rule.get("Enabled")), i);
                if (rule.get("Description") instanceof Map) {
                    model.setValue("desc", ((Map) rule.get("Description")).get(Lang.get().toString()), i);
                    continue;
                }
                model.setValue("desc", (Object) rule.get("Description").toString(), i);
            }
            this.getModel().setDataChanged(false);
        }
        if (this.getModel().getValue("srcbill") != null) {
            Object srcBill = this.getModel().getValue("srcbill");
            String srcBillId = (String) ((DynamicObject) srcBill).getPkValue();
            List<String> entitymap = this.getRestrictedAttributeMap(srcBillId);
            DynamicObjectCollection doc = this.getModel().getEntryEntity("mappingentity");
            int i = 0;
            for (DynamicObject obj : doc) {
                String sourcefield = (String) obj.get("sourcefield");
                if (entitymap.contains(sourcefield)) {
                    this.getView().setEnable(Boolean.FALSE, i, "canenable");
                    this.getView().setEnable(Boolean.FALSE, i, "canwriteback");
                }
                ++i;
            }
        }
    }



    public void propertyChanged(PropertyChangedArgs e) {
        String fieldName = e.getProperty().getName();
        ChangeData[] valueSet = e.getChangeSet();
        for (ChangeData changeData : valueSet) {
            if (!CommonUtils.isRealChanged(changeData))
                continue;
            Object newValue = changeData.getNewValue();
            IDataModel model = this.getView().getModel();
            switch (fieldName) {
                case "xbill": {
                    this.getModel().deleteEntryData("mappingentity");
                    this.getModel().deleteEntryData("validentity");
                    int entryRowCount = model.getEntryRowCount("billtypeentity");
                    for (int j = 0; j < entryRowCount; ++j) {
                        DynamicObject srcBillType = (DynamicObject) model.getValue("srcbilltype", j);
                        if (srcBillType == null)
                            continue;
                        model.setValue("xbilltype", (Object) null, j);
                    }
                    if (newValue == null) {
                        return;
                    }
                    Object srcBill = model.getValue("srcbill");
                    if (CommonUtils.isNull((Object) srcBill)) {
                        this.getView()
                                .showTipNotification(ResManager.loadKDString((String) "选择变更单前，请先选择源单。",
                                        (String) "ChangeModelPlugin_0", (String) "yem-changemodel",
                                        (Object[]) new Object[0]));
                    }
                    this.createMappingEntity((String) ((DynamicObject) newValue).getPkValue());
                    this.buildMetaContext(newValue);
                    continue;
                }
                case "srcbill": {
                    model.setValue("xbill", (Object) null);
                    model.setValue("mul_name", (Object) "");
                    model.setValue("mul_areaconditiondesc", (Object) "");
                    model.setValue("areaconditionjson_tag", (Object) null);
                    this.getModel().deleteEntryData("pluginentity");
                    this.getModel().deleteEntryData("billtypeentity");
                    FilterGrid filterGrid = this.getView().getControl("areafilter");
                    FilterCondition condition = new FilterCondition();
                    filterGrid.SetValue(condition);
                    if (newValue == null) {
                        filterGrid.setEntityNumber(null);
                        filterGrid.setFilterColumns(Collections.emptyList());
                        this.getView().updateView("areafilter");
                        return;
                    }
                    String srcbill = (String) ((DynamicObject) newValue).getPkValue();
                    filterGrid.setEntityNumber(srcbill);
                    MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(srcbill);
                    String entityNumber = dataEntityType.getName();
                    if (!StringUtils.isNotBlank(entityNumber))
                        continue;
                    MainEntityType entityType = EntityMetadataCache.getDataEntityType(entityNumber);
                    EntityTypeUtil helper = new EntityTypeUtil();
                    List<Map<String, Object>> cols = helper.getFilterColumns(entityType, false);
                    filterGrid.setFilterColumns(cols);
                    filterGrid.setEntityNumber(entityNumber);
                    this.getView().updateView("areafilter");
                    continue ;
                }
                case "isenable": {
                    if (!(newValue instanceof Boolean)
                            || this.getModel().getValue("validconditionjson_tag", changeData.getRowIndex()) == null)
                        continue;
                    String validjson = (String) this.getModel().getValue("validconditionjson_tag",
                            changeData.getRowIndex());
                    Map rule = SerializationUtils.fromJsonString((String) validjson, Map.class);
                    rule.put("Enabled", newValue);
                    this.getModel().setValue("validconditionjson_tag",
                            (Object) SerializationUtils.toJsonString((Object) rule), changeData.getRowIndex());
                    break;
                }
            }
        }
    }

    @Override
    public void registerListener(EventObject e) {
        BasedataEdit srcBillTypeEdit;
        BasedataEdit xBillTypeEdit;
        EntryGrid validentryGrid;
        BasedataEdit xBillEdit = (BasedataEdit) this.getView().getControl("xbill");
        if (xBillEdit != null) {
            xBillEdit.addBeforeF7SelectListener((BeforeF7SelectListener) this);
        }
        if ((srcBillTypeEdit = (BasedataEdit) this.getView().getControl("srcbilltype")) != null) {
            srcBillTypeEdit.addBeforeF7SelectListener((BeforeF7SelectListener) this);
        }
        if ((xBillTypeEdit = (BasedataEdit) this.getView().getControl("xbilltype")) != null) {
            xBillTypeEdit.addBeforeF7SelectListener((BeforeF7SelectListener) this);
        }
        this.addClickListeners("sourcefieldname");
        this.addItemClickListeners("tbar_mappingentity", "tbar_plugin", "tbar_validcondition", "toobarap");
        EntryGrid entryGrid = (EntryGrid) this.getView().getControl("mappingentity");
        if (entryGrid != null) {
            entryGrid.addHyperClickListener((HyperLinkClickListener) this);
        }
        if ((validentryGrid = (EntryGrid) this.getView().getControl("validentity")) != null) {
            validentryGrid.addRowClickListener((RowClickEventListener) this);
        }
    }

    @Override
    public void click(EventObject evt) {
        super.click(evt);
        String key;
        Control c = (Control) evt.getSource();
        switch (key = c.getKey().toLowerCase()) {
            case "sourcefieldname" : {  //字段检验 - 源单字段
                this.openSrcFieldList();
            }
        }
    }

    @Override
    public void beforeItemClick(BeforeItemClickEvent evt) {
        String barItemKey = evt.getItemKey();
        switch (barItemKey ) {
            case "barenable" : //启用禁用检验
            case "bardisable" : {
                OperationStatus ostatus = this.getView().getFormShowParameter().getStatus();
                if (ostatus != OperationStatus.ADDNEW)
                    break;
                this.getView().showTipNotification(ResManager.loadKDString((String) "请先保存数据。",
                        (String) "ChangeModelPlugin_8", (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                evt.setCancel(true);
            }
        }
        super.beforeItemClick(evt);
    }

    @Override
    public void itemClick(ItemClickEvent evt) {
        String barItemKey = evt.getItemKey();
        AbstractGrid grid = (AbstractGrid) this.getView().getControl("validentity");  //校验条件实体
        int rowKey = grid.getEntryState().getFocusRow();
        switch (barItemKey) {
            case "btn_automatchfield" : {  //自动匹配
                this.autoMatchFields();
                break;
            }
            case "baraddplugin" : {  //注册插件 注册
                this.showAddPlugForm();
                break;
            }
            case "baraddjsplugin" : { //注册脚本
                this.showAddJSPlugForm();
                break;
            }
            case "barmodifyplugin" : { // 修改插件
                this.showModifyPlugForm();
                break;
            }
            case "btnadd" : { //单据类型新增
                if (this.getModel().getValue("xbill") == null) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "请先选择变更单。", (String) "ChangeModelPlugin_10",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    return;
                }
                FormShowParameter addValidRulePara = new FormShowParameter();
                addValidRulePara.getOpenStyle().setShowType(ShowType.Modal);
                addValidRulePara.setFormId("yem_validationedit");
                ArrayList<List<Map<String, Object>>> formContext = new ArrayList<List<Map<String, Object>>>();
                formContext.add(this.buildDesignContext((DynamicObject) this.getModel().getValue("xbill")));
                addValidRulePara.setCustomParam("MetaContext", formContext);
                addValidRulePara.setCloseCallBack(new CloseCallBack((IFormPlugin) this, "newValidCallBack"));
                this.getView().showForm(addValidRulePara);
                break;
            }
            case "btnedit" : { //校验条件实体 -修改
                if (this.getModel().getValue("xbill") == null) {
                    return;
                }
                FormShowParameter editValidRulePara = new FormShowParameter();
                editValidRulePara.getOpenStyle().setShowType(ShowType.Modal);
                editValidRulePara.setFormId("yem_validationedit");
                if (rowKey <= -1) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "请先选择一行。", (String) "ChangeModelPlugin_6",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    return;
                }
                if (rowKey >= 0) {
                    editValidRulePara.setCustomParam("Rule",
                            this.getModel().getValue("validconditionjson_tag", rowKey));
                }
                ArrayList<List<Map<String, Object>>> editFormContext = new ArrayList<List<Map<String, Object>>>();
                editFormContext.add(this.buildDesignContext((DynamicObject) this.getModel().getValue("xbill")));
                editValidRulePara.setCustomParam("MetaContext", editFormContext);
                editValidRulePara.setCloseCallBack(new CloseCallBack((IFormPlugin) this, "editValidCallBack"));
                this.getView().showForm(editValidRulePara);
            }
        }
    }

    @Override
    public void entryRowDoubleClick(RowClickEvent e) {
        RowClickEventListener.super.entryRowDoubleClick(e);
        EntryGrid entry = (EntryGrid) e.getSource();
        String entrykey = entry.getEntryKey();
        int row = e.getRow();
        switch (entrykey) { //validentity
            case "validentity" : {
                if (this.getModel().getValue("xbill") == null) {
                    return;
                }
                FormShowParameter editValidRulePara = new FormShowParameter();
                editValidRulePara.getOpenStyle().setShowType(ShowType.Modal);
                editValidRulePara.setFormId("yem_validationedit");
                if (row <= -1) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "请先选择一行。", (String) "ChangeModelPlugin_6",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    return;
                }
                if (row >= 0) {
                    editValidRulePara.setCustomParam("Rule", this.getModel().getValue("validconditionjson_tag", row));
                }
                ArrayList<List<Map<String, Object>>> editFormContext = new ArrayList<List<Map<String, Object>>>();
                editFormContext.add(this.buildDesignContext((DynamicObject) this.getModel().getValue("xbill")));
                editValidRulePara.setCustomParam("MetaContext", editFormContext);
                editValidRulePara.setCloseCallBack(new CloseCallBack((IFormPlugin) this, "editValidCallBack"));
                this.getView().showForm(editValidRulePara);
                break;
            }
        }
    }

    @Override
    public void beforeF7Select(BeforeF7SelectEvent e) {
        String key = e.getProperty().getName();
        IDataModel model = this.getModel();
        Object srcBill = model.getValue("srcbill");
        Object xBill = model.getValue("xbill");
        ListShowParameter showParameter = (ListShowParameter) e.getFormShowParameter();
        switch (key) {
            case "xbill" : { // 源单据 过滤
                QFilter qf2;
                if (CommonUtils.isNull((Object) srcBill)) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "选择变更单前，请先选择源单。", (String) "ChangeModelPlugin_0",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    e.setCancel(true);
                    return;
                }
                String srcBillId = MetadataDao.getIdByNumber((String) ((DynamicObject) srcBill).getPkValue().toString(),
                        (MetaCategory) MetaCategory.Entity);
                QFilter qf1 = new QFilter("inheritpath", "ftlike", (Object) srcBillId);
                DynamicObjectCollection dyos = QueryServiceHelper.query((String) "bos_formmeta", (String) "number",
                        (QFilter[]) new QFilter[]{
                                qf1.and(qf2 = new QFilter("istemplate", "=", (Object) Boolean.FALSE))});
                if (!CommonUtils.isNull((Object) dyos)) {
                    HashSet<String> ids = new HashSet<String>();
                    for (DynamicObject dyo : dyos) {
                        ids.add(dyo.getString("number"));
                    }
                    showParameter.getListFilterParameter().getQFilters().add(new QFilter("id", "in", ids));
                    break;
                }
                this.getView().showTipNotification(ResManager.loadKDString((String) "没有可用的变更单，请先选择正确的源单。",
                        (String) "ChangeModelPlugin_1", (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                e.setCancel(true);
                return;
            }
            case "srcbilltype" : { // 源单单据类型 过滤
                if (CommonUtils.isNull((Object) srcBill)) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "请先选择源单。", (String) "ChangeModelPlugin_9",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    e.setCancel(true);
                    return;
                }
                String srcBillIDTwo = (String) ((DynamicObject) srcBill).getPkValue();
                QFilter qFilter1 = new QFilter("status", "=", (Object) StatusEnum.AUDIT.getValue());
                QFilter qFilter2 = new QFilter("billformid", "=", (Object) srcBillIDTwo);
                QFilter qFilter3 = new QFilter("enable", "=", (Object) EnableStatusEnum.ENABLE.getValue());
                showParameter.getListFilterParameter()
                        .setQFilters(Arrays.asList(new QFilter[]{qFilter1, qFilter2, qFilter3}));
                break;
            }
            case "xbilltype" : { // 变更单单据类型 过滤
                if (CommonUtils.isNull((Object) xBill)) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "请先选择变更单。", (String) "ChangeModelPlugin_10",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    e.setCancel(true);
                    return;
                }
                String xBillID = (String) ((DynamicObject) xBill).getPkValue();
                QFilter qFilter4 = new QFilter("status", "=", (Object) StatusEnum.AUDIT.getValue());
                QFilter qFilter5 = new QFilter("billformid", "=", (Object) xBillID);
                QFilter qFilter6 = new QFilter("enable", "=", (Object) EnableStatusEnum.ENABLE.getValue());
                showParameter.getListFilterParameter()
                        .setQFilters(Arrays.asList(new QFilter[]{qFilter4, qFilter5, qFilter6}));
                break;
            }
        }
    }

    @Override
    public void closedCallBack(ClosedCallBackEvent e) {
        String actionId = e.getActionId();
        Object returnData = e.getReturnData();
        if (CommonUtils.isNull((Object) returnData)) {
            return;
        }
        switch (actionId) {
            case "sourcefieldcallback" : { // 源单表单关闭时间
                String fieldId = returnData.toString();
                int row = this.getModel().getEntryCurrentRowIndex("mappingentity");
                Object srcBill = this.getModel().getValue("srcbill");
                String srcBillId = (String) ((DynamicObject) srcBill).getPkValue();
                MainEntityType srcbillMainType = MetadataServiceHelper.getDataEntityType((String) srcBillId);
                String fieldCaption = EntityParseHelper.buildPropFullCaption((EntityType) srcbillMainType,
                        (String) fieldId);
                String[] sourceItems = fieldId.split("\\.");
                if (sourceItems.length > 2) {
                    this.getView().showTipNotification(
                            ResManager.loadKDString((String) "选择的属性层级不能超过3级。", (String) "ChangeModelPlugin_3",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]));
                    return;
                }
                if (sourceItems.length > 1) {
                    IDataEntityProperty findProperty = srcbillMainType.findProperty(sourceItems[0]);
                    String parentName = findProperty.getParent().getName();
                    if (!srcBillId.equals(parentName)) {
                        fieldId = parentName.concat(".").concat(sourceItems[0]).concat(".").concat(sourceItems[1]);
                    }
                } else {
                    IDataEntityProperty findProperty = srcbillMainType.findProperty(fieldId);
                    if (findProperty == null)
                        break;
                }
                this.getModel().setValue("sourcefield", (Object) fieldId, row);
                this.getModel().setValue("sourcefieldname", (Object) fieldCaption, row);
                break;
            }
            case "addplugincallback" : { //新增插件表单关闭
                if (!(returnData instanceof Map))
                    break;
                this.receiveNewPlug((Map) returnData);
                break;
            }
            case "modifyplugincallback" : {//修改插件表单关闭
                if (!(returnData instanceof Map))
                    break;
                this.receiveModifyPlug((Map) returnData);
                break;
            }
            case "newValidCallBack" : { //新增校验表单关闭
                if (!(returnData instanceof ConditionValidation))
                    break;
                ConditionValidation validnew = (ConditionValidation) returnData;
                validnew.setEnabled(true);
                int rowKey = this.getModel().createNewEntryRow("validentity");
                if (rowKey < 0)
                    break;
                this.getModel().setValue("desc", validnew.getDescription().getItem(Lang.get().toString()), rowKey);
                DcJsonSerializer ds = new DcJsonSerializer((DcBinder) new ListDcxmlBinder(false, new ArrayList()));
                ds.setIsLocaleValueFull(true);
                this.getModel().setValue("validconditionjson_tag",
                        (Object) ds.serializeToString((Object) validnew, (Object) null), rowKey);
                break;
            }
            case "editValidCallBack" : { //修改校验表单关闭
                if (!(returnData instanceof ConditionValidation))
                    break;
                ConditionValidation validedit = (ConditionValidation) returnData;
                AbstractGrid grid = (AbstractGrid) this.getView().getControl("validentity");
                int selrowkey = grid.getEntryState().getFocusRow();
                if (selrowkey < 0)
                    break;
                validedit.setEnabled(((Boolean) this.getModel().getValue("isenable")).booleanValue());
                this.getModel().setValue("desc", validedit.getDescription().getItem(Lang.get().toString()), selrowkey);
                DcJsonSerializer ds = new DcJsonSerializer((DcBinder) new ListDcxmlBinder(false, new ArrayList()));
                ds.setIsLocaleValueFull(true);
                this.getModel().setValue("validconditionjson_tag",
                        (Object) ds.serializeToString((Object) validedit, (Object) null), selrowkey);
            }
        }
    }

    /**
     * @MethodName openSrcFieldList
     * @Author  SC
     * @Description 打开 源单列表
     * @Date 14:36 2023/7/18
     * @Param
     **/
    private void openSrcFieldList() {
        int row = this.getModel().getEntryCurrentRowIndex("mappingentity");
        String convertType = (String) this.getModel().getValue("converttype", row);
        Object srcBill = this.getModel().getValue("srcbill");
        Object xBill = this.getModel().getValue("xbill");
        String targetFieldValue = (String) this.getModel().getValue("targetfield", row);
        if (CommonUtils.isNull((Object) srcBill) || CommonUtils.isNull((Object) targetFieldValue)) {
            this.getView().showTipNotification(ResManager.loadKDString((String) "请先选择源单、变更单和变更单字段。",
                    (String) "ChangeModelPlugin_4", (String) "yem-yc-changemodel", (Object[]) new Object[0]));
            return;
        }
        String srcBillId = (String) ((DynamicObject) srcBill).getPkValue();
        String xBillId = (String) ((DynamicObject) xBill).getPkValue();
        MainEntityType srcbillMainType = MetadataServiceHelper.getDataEntityType((String) srcBillId);
        MainEntityType xBillMainType = MetadataServiceHelper.getDataEntityType((String) xBillId);
        IDataEntityProperty targetProperty = xBillMainType.findProperty(targetFieldValue);
        TreeNode srcBillNode = new TreeNode();
        if (targetProperty instanceof BigIntProp) {
            PropTreeBuildOption optionid = new PropTreeBuildOption(null, BigIntProp.class);
            optionid.setIncludeParentEntity(true);
            optionid.setIncludeChildEntity(true);
            optionid.setIncludePKField(true);
            optionid.addMatchedClassTypes(LongProp.class);
            srcBillNode = FormTreeBuilder.buildDynamicPropertyTree((MainEntityType) srcbillMainType,
                    (PropTreeBuildOption) optionid);
        } else {
            PropTreeBuildOption option = new PropTreeBuildOption(null, targetProperty);
            option.setIncludeParentEntity(true);
            option.setIncludeChildEntity(true);
            option.setIncludePKField(true);
            srcBillNode = FormTreeBuilder.buildDynamicPropertyTree((MainEntityType) srcbillMainType,
                    (PropTreeBuildOption) option);
        }
        this.showSrcFieldForm(srcBillNode);
    }

    /**
     * @MethodName showSrcFieldForm
     * @Author  SC
     * @Description 打开 源单表单
     * @Date 14:37 2023/7/18
     * @Param [srcBillNode] [kd.bos.entity.tree.TreeNode]
     **/
    private void showSrcFieldForm(TreeNode srcBillNode) {
        FormShowParameter showParameter = new FormShowParameter();
        showParameter.setFormId("botp_selectfield");
        String nodesJson = SerializationUtils.toJsonString((Object) srcBillNode);
        showParameter.getCustomParams().put("treenodes", nodesJson);
        showParameter.setCloseCallBack(new CloseCallBack((IFormPlugin) this, "sourcefieldcallback"));
        showParameter.getOpenStyle().setShowType(ShowType.Modal);
        this.getView().showForm(showParameter);
    }

    /**
     * @MethodName autoMatchFields
     * @Author  SC
     * @Description 自动匹配字段
     * @Date 14:54 2023/7/18
     * @Param [] []
     **/
    public void autoMatchFields() {
        Object srcBill = this.getModel().getValue("srcbill");
        Object xBill = this.getModel().getValue("xbill");
        if (CommonUtils.isNull((Object) srcBill) || CommonUtils.isNull((Object) xBill)) {
            this.getView().showTipNotification(ResManager.loadKDString((String) "请先选择源单和变更单。",
                    (String) "ChangeModelPlugin_5", (String) "yem-yc-changemodel", (Object[]) new Object[0]));
            return;
        }
        String srcBillId = (String) ((DynamicObject) srcBill).getPkValue();
        String xBillId = (String) ((DynamicObject) xBill).getPkValue();
        MainEntityType srcbillMainType = MetadataServiceHelper.getDataEntityType((String) srcBillId);
        MainEntityType xBillMainType = MetadataServiceHelper.getDataEntityType((String) xBillId);
        int rowCount = this.getModel().getEntryRowCount("mappingentity");
        HashMap<String, Integer> delFieldMap = new HashMap<String, Integer>();
        HashSet<String> stayFieldSet = new HashSet<String>();
        for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
            String targetFieldKey = (String) this.getModel().getValue("targetfield", rowIndex);
            DynamicProperty targetField = (DynamicProperty) xBillMainType.findProperty(targetFieldKey);
            if (targetField == null) {
                delFieldMap.put(targetFieldKey, rowIndex);
                continue;
            }
            if ("validstatus".equalsIgnoreCase(targetFieldKey) || "valider".equalsIgnoreCase(targetFieldKey)
                    || "validdate".equalsIgnoreCase(targetFieldKey))
                continue;
            stayFieldSet.add(targetFieldKey);
            String targetFieldName = EntityParseHelper.buildPropFullCaption((IDataEntityProperty) targetField);
            this.getModel().setValue("targetfieldname", (Object) targetFieldName, rowIndex);
            String sourceOldFieldKey = (String) this.getModel().getValue("sourcefield", rowIndex);
            if (!CommonUtils.isNull((Object) sourceOldFieldKey)) {
                DynamicProperty sourceOldField = (DynamicProperty) srcbillMainType.findProperty(sourceOldFieldKey);
                if (sourceOldField == null)
                    continue;
                String sourceOldFieldNewName = EntityParseHelper
                        .buildPropFullCaption((IDataEntityProperty) sourceOldField);
                this.getModel().setValue("sourcefieldname", (Object) sourceOldFieldNewName, rowIndex);
                continue;
            }
            DynamicProperty sourceNewField = (DynamicProperty) srcbillMainType.findProperty(targetFieldKey);
            if (sourceNewField == null)
                continue;
            String sourceNewFieldName = EntityParseHelper.buildPropFullCaption((IDataEntityProperty) sourceNewField);
            this.getModel().setValue("sourcefield", (Object) sourceNewField.getName(), rowIndex);
            this.getModel().setValue("sourcefieldname", (Object) sourceNewFieldName, rowIndex);
        }
        this.buildDiffMappingEntity(xBillId, srcBillId, stayFieldSet, delFieldMap);
    }

    /**
     * @MethodName buildDiffMappingEntity
     * @Author  SC
     * @Description 生成字段映射实体
     * @Date 10:27 2023/7/31
     * @Param [xBillId, srcBillId, stayFieldSet, delFieldsMap] [java.lang.String, java.lang.String, java.util.Set<java.lang.String>, java.util.Map<java.lang.String,java.lang.Integer>]
     * @return void
     **/

    private void buildDiffMappingEntity(String xBillId, String srcBillId, Set<String> stayFieldSet,
                                        Map<String, Integer> delFieldsMap) {
        if (delFieldsMap != null && delFieldsMap.size() > 0) {
            int[] delrow = ArrayUtils.toPrimitive((Integer[]) delFieldsMap.values().toArray(new Integer[0]));
            this.getModel().deleteEntryRows("mappingentity", delrow);
            delFieldsMap.clear();
        }
        MainEntityType xBillEntity = MetadataServiceHelper.getDataEntityType((String) xBillId);
        MainEntityType srcbillMainType = MetadataServiceHelper.getDataEntityType((String) srcBillId);
        Map<String, IDataEntityProperty> fields = xBillEntity.getFields();
        for (Map.Entry field : fields.entrySet()) {
            String fieldKey = (String) field.getKey();
            if ("billtype".equalsIgnoreCase(fieldKey) || "billstatus".equalsIgnoreCase(fieldKey)
                    || "creator".equalsIgnoreCase(fieldKey) || "createtime".equalsIgnoreCase(fieldKey)
                    || "modifier".equalsIgnoreCase(fieldKey) || "modifytime".equalsIgnoreCase(fieldKey)
                    || "auditor".equalsIgnoreCase(fieldKey) || "auditdate".equalsIgnoreCase(fieldKey)
                    || "lastupdateuser".equalsIgnoreCase(fieldKey) || "lastupdatetime".equalsIgnoreCase(fieldKey)
                    || "validstatus".equalsIgnoreCase(fieldKey) || "valider".equalsIgnoreCase(fieldKey)
                    || "validdate".equalsIgnoreCase(fieldKey) || "sourcebillid".equalsIgnoreCase(fieldKey)
                    || "sourcebillentity".equalsIgnoreCase(fieldKey) || "yem_billtype".equalsIgnoreCase(fieldKey)
                    || stayFieldSet.contains(fieldKey))
                continue;
            int newRowIndex = this.getModel().createNewEntryRow("mappingentity");
            DynamicProperty findProperty = (DynamicProperty) xBillEntity.findProperty(fieldKey);
            String targetFieldName = EntityParseHelper.buildPropFullCaption((IDataEntityProperty) findProperty);
            this.getModel().setValue("targetfield", (Object) fieldKey, newRowIndex);
            this.getModel().setValue("targetfieldname", (Object) targetFieldName, newRowIndex);
            this.getModel().setValue("clearsourcefield", (Object) "clear", newRowIndex);
            DynamicProperty sourceField = (DynamicProperty) srcbillMainType.findProperty(fieldKey);
            if (sourceField == null)
                continue;
            String sourceFieldName = EntityParseHelper.buildPropFullCaption((IDataEntityProperty) sourceField);
            this.getModel().setValue("sourcefield", (Object) sourceField.getName(), newRowIndex);
            this.getModel().setValue("sourcefieldname", (Object) sourceFieldName, newRowIndex);
        }
        Map<String, EntityType> entityTypes = xBillEntity.getAllEntities();
        for (EntityType entityType : entityTypes.values()) {
            if (!(entityType instanceof EntryType) || entityType.getName().endsWith("_lk"))
                continue;
            Map<String, IDataEntityProperty> entryFields = entityType.getFields();
            for (Map.Entry entryField : entryFields.entrySet()) {
                String entryFieldKey = (String) entryField.getKey();
                if (stayFieldSet.contains(entryFieldKey))
                    continue;
                int newentryRowIndex = this.getModel().createNewEntryRow("mappingentity");
                this.getModel().setValue("targetfield", (Object) entryFieldKey, newentryRowIndex);
                DynamicProperty findEntryProperty = (DynamicProperty) xBillEntity.findProperty(entryFieldKey);
                String targetEntryFieldName = EntityParseHelper
                        .buildPropFullCaption((IDataEntityProperty) findEntryProperty);
                this.getModel().setValue("targetfieldname", (Object) targetEntryFieldName, newentryRowIndex);
                this.getModel().setValue("clearsourcefield", (Object) "clear", newentryRowIndex);
                DynamicProperty sourceEntryField = (DynamicProperty) srcbillMainType.findProperty(entryFieldKey);
                if (sourceEntryField == null)
                    continue;
                String sourceEntryFieldName = EntityParseHelper
                        .buildPropFullCaption((IDataEntityProperty) sourceEntryField);
                this.getModel().setValue("sourcefield", (Object) sourceEntryField.getName(), newentryRowIndex);
                this.getModel().setValue("sourcefieldname", (Object) sourceEntryFieldName, newentryRowIndex);
            }
        }
    }

    /**
     * @MethodName showAddPlugForm
     * @Author  SC
     * @Description 插件注册
     * @Date 10:23 2023/7/31
     * @Param
     **/
    private void showAddPlugForm() {
        FormShowParameter showParameter = new FormShowParameter();
        showParameter.setFormId("ide_registerplugin");
        showParameter.getOpenStyle().setShowType(ShowType.Modal);
        showParameter.setCloseCallBack(new CloseCallBack((IFormPlugin) this, "addplugincallback"));
        this.getView().showForm(showParameter);
    }

    /**
     * @MethodName showAddJSPlugForm
     * @Author  SC
     * @Description 脚本插件注册
     * @Date 10:23 2023/7/31
     **/
    private void showAddJSPlugForm() {
        this.getView().showTipNotification(ResManager.loadKDString((String) "暂时没有支持脚本插件，请留步...",
                (String) "ChangeModelPlugin_7", (String) "yem-yc-changemodel", (Object[]) new Object[0]));
    }

    /**
     * @MethodName showModifyPlugForm
     * @Author  SC
     * @Description 修改插件
     * @Date 10:24 2023/7/31
     **/
    private void showModifyPlugForm() {
        int row;
        IDataModel model = this.getView().getModel();
        String pluginJson = (String) model.getValue("pluginjson", row = model.getEntryCurrentRowIndex("pluginentity"));
        if (StringUtils.isBlank((CharSequence) pluginJson)) {
            return;
        }
        CRPlugin crPlugin = (CRPlugin) SerializationUtils.fromJsonString((String) pluginJson, CRPlugin.class);
        boolean enabled = (Boolean) model.getValue("pluginenable", row);
        crPlugin.setEnabled(enabled);
        if (crPlugin.getType() == 0) {
            FormShowParameter parameter = new FormShowParameter();
            parameter.setFormId("ide_registerplugin");
            Map<String, Object> crPluginMap = this.convertToParams(crPlugin);
            parameter.setCustomParam("rowKey", (Object) row);
            parameter.setCustomParam("plugin", crPluginMap);
            parameter.getOpenStyle().setShowType(ShowType.Modal);
            parameter.setCloseCallBack(new CloseCallBack((IFormPlugin) this, "modifyplugincallback"));
            this.getView().showForm(parameter);
        }
    }

    /**
     * @MethodName convertToParams
     * @Author  SC
     * @Description 修改插件参数
     * @Date 10:28 2023/7/31
     * @Param [crPlugin] [kd.bos.entity.botp.CRPlugin]
     * @return java.util.Map<java.lang.String, java.lang.Object>
     **/


    private Map<String, Object> convertToParams(CRPlugin crPlugin) {
        HashMap<String, Object> plugParams = new HashMap<String, Object>();
        plugParams.put("ClassName", crPlugin.getClassName());
        plugParams.put("Enabled", crPlugin.isEnabled());
        plugParams.put("Description", crPlugin.getDescription());
        return plugParams;
    }

    /**
     * @MethodName receiveNewPlug
     * @Author  SC
     * @Description 新增插件 返回值写入单据
     * @Date 10:29 2023/7/31
     * @Param [plugParams] [java.util.Map<java.lang.String,java.lang.Object>]
     * @return void
     **/
    private void receiveNewPlug(Map<String, Object> plugParams) {
        CRPlugin crPlugin = this.convertToPlugin(plugParams);
        String pluginJson = SerializationUtils.toJsonString((Object) crPlugin);
        IDataModel model = this.getView().getModel();
        int row = model.createNewEntryRow("pluginentity");
        model.setValue("pluginenable", (Object) crPlugin.isEnabled(), row);
        model.setValue("classname", (Object) crPlugin.getClassName(), row);
        model.setValue("pluginjson", (Object) pluginJson, row);
        model.setValue("plugintype", (Object) String.valueOf(crPlugin.getType()), row);
    }

    /**
     * @MethodName receiveModifyPlug
     * @Author  SC
     * @Description 修改插件返回关闭
     * @Date 10:31 2023/7/31
     * @Param [plugParams] [java.util.Map<java.lang.String,java.lang.Object>]
     * @return void
     **/
    private void receiveModifyPlug(Map<String, Object> plugParams) {
        if (plugParams != null) {
            CRPlugin crPlugin = this.convertToPlugin(plugParams);
            String pluginJson = SerializationUtils.toJsonString((Object) crPlugin);
            IDataModel model = this.getView().getModel();
            int row = model.getEntryCurrentRowIndex("pluginentity");
            model.setValue("pluginenable", (Object) crPlugin.isEnabled(), row);
            model.setValue("classname", (Object) crPlugin.getClassName(), row);
            model.setValue("pluginjson", (Object) pluginJson, row);
        }
    }

    /**
     * @MethodName convertToPlugin
     * @Author  SC
     * @Description 根据参数返回 插件类型
     * @Date 10:31 2023/7/31
     * @Param [plugParams] [java.util.Map<java.lang.String,java.lang.Object>]
     * @return kd.bos.entity.botp.CRPlugin
     **/
    private CRPlugin convertToPlugin(Map<String, Object> plugParams) {
        CRPlugin crPlugin = new CRPlugin();
        crPlugin.setClassName((String) plugParams.get("ClassName"));
        crPlugin.setEnabled(((Boolean) plugParams.get("Enabled")).booleanValue());
        crPlugin.setType(0);
        crPlugin.setDescription((String) plugParams.get("Description"));
        return crPlugin;
    }

    @Override
    public void hyperLinkClick(HyperLinkClickEvent e) {
        String fieldKey = e.getFieldName();
        int row = e.getRowIndex();
        switch (fieldKey) { //清除
            case "clearsourcefield" : {
                this.getModel().setValue("sourcefield", (Object) "", row);
                this.getModel().setValue("sourcefieldname", (Object) "", row);
            }
        }
    }

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        super.beforeDoOperation(args);
        String key = ((AbstractOperate) args.getSource()).getOperateKey();
        if ("save".equals(key)) {
            FilterGrid filterGrid = (FilterGrid) this.getView().getControl("areafilter");
            FilterCondition areaCondition = filterGrid.getFilterGridState().getFilterCondition();
            String areaConditionJsonStr = SerializationUtils.toJsonString((Object) areaCondition);
            this.getModel().setValue("areaconditionjson_tag", (Object) areaConditionJsonStr);
        }
    }

    public void setFilterGrid() {
        FilterGrid filterGrid = (FilterGrid) this.getView().getControl("areafilter");
        Object srcbillObj = this.getModel().getValue("srcbill");
        if (srcbillObj == null) {
            filterGrid.setEntityNumber(null);
            filterGrid.setFilterColumns(Collections.emptyList());
            return;
        }
        DynamicObject sourceBill = (DynamicObject) srcbillObj;
        String srcbill = (String) sourceBill.getPkValue();
        filterGrid.setEntityNumber(srcbill);
        MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType((String) srcbill);
        String entityNumber = dataEntityType.getName();
        if (StringUtils.isNotBlank((CharSequence) entityNumber)) {
            MainEntityType entityType = EntityMetadataCache.getDataEntityType((String) entityNumber);
            EntityTypeUtil helper = new EntityTypeUtil();
            List cols = helper.getFilterColumns((IDataEntityType) entityType, false);
            filterGrid.setFilterColumns(cols);
            filterGrid.setEntityNumber(entityNumber);
            this.getView().updateView("areafilter");
        }
    }

    private void initAreaConditionToFilterGrid() {
        String areaCondition = (String) this.getModel().getValue("areaconditionjson_tag");
        FilterCondition condition = null;
        condition = StringUtils.isBlank((CharSequence) areaCondition)
                ? new FilterCondition()
                : (FilterCondition) SerializationUtils.fromJsonString((String) areaCondition, FilterCondition.class);
        FilterGrid areaFilter = (FilterGrid) this.getControl("areafilter");
        areaFilter.SetValue(condition);
    }

    /**
     * @MethodName createMappingEntity
     * @Author  SC
     * @Description 创建字段映射分录
     * @Date 17:45 2023/7/7
     * @Param xBillId
     **/
    private void createMappingEntity(String xBillId) {
        MainEntityType xBillEntity = MetadataServiceHelper.getDataEntityType((String) xBillId);
        Map<String, IDataEntityProperty> fields = xBillEntity.getFields();
        Object srcBill = this.getModel().getValue("srcbill");
        String srcBillId = (String) ((DynamicObject) srcBill).getPkValue();
        List<String> entitymap = this.getRestrictedAttributeMap(srcBillId);
        int rowIndex = 0;
        for (Map.Entry field : fields.entrySet()) {
            String fieldKey = (String) field.getKey();
            if ("billtype".equalsIgnoreCase(fieldKey) || "billstatus".equalsIgnoreCase(fieldKey)
                    || "creator".equalsIgnoreCase(fieldKey) || "createtime".equalsIgnoreCase(fieldKey)
                    || "modifier".equalsIgnoreCase(fieldKey) || "modifytime".equalsIgnoreCase(fieldKey)
                    || "auditor".equalsIgnoreCase(fieldKey) || "auditdate".equalsIgnoreCase(fieldKey)
                    || "validstatus".equalsIgnoreCase(fieldKey) || "valider".equalsIgnoreCase(fieldKey)
                    || "validdate".equalsIgnoreCase(fieldKey) || "sourcebillid".equalsIgnoreCase(fieldKey)
                    || "sourcebillentity".equalsIgnoreCase(fieldKey) || "yem_billtype".equalsIgnoreCase(fieldKey))
                continue;
            rowIndex = this.getModel().createNewEntryRow("mappingentity");
            this.getModel().setValue("targetfield", (Object) fieldKey, rowIndex);
            DynamicProperty findProperty = (DynamicProperty) xBillEntity.findProperty(fieldKey);
            this.getModel().setValue("targetfieldname",
                    (Object) String.format(
                            ResManager.loadKDString((String) "单据头.%s", (String) "ChangeModelPlugin_2",
                                    (String) "yem-yc-changemodel", (Object[]) new Object[0]),
                            new Object[]{findProperty.getDisplayName()}),
                    rowIndex);
            this.getModel().setValue("clearsourcefield", (Object) "clear", rowIndex);
            if (!entitymap.contains(fieldKey))
                continue;
            this.getView().setEnable(Boolean.FALSE, rowIndex, "canenable");
            this.getView().setEnable(Boolean.FALSE, rowIndex, "canwriteback");
        }
        Map<String, EntityType> entityTypes = xBillEntity.getAllEntities();
        for (EntityType entityType : entityTypes.values()) {
            if (!(entityType instanceof EntryType) || entityType.getName().endsWith("_lk"))
                continue;
            fields = entityType.getFields();
            for (Map.Entry entity : fields.entrySet()) {
                String fieldKey = (String) entity.getKey();
                rowIndex = this.getModel().createNewEntryRow("mappingentity");
                this.getModel().setValue("targetfield", (Object) fieldKey, rowIndex);
                DynamicProperty findProperty = (DynamicProperty) xBillEntity.findProperty(fieldKey);
                this.getModel().setValue("targetfieldname",
                        (Object) ((Object) entityType.getDisplayName() + "." + (Object) findProperty.getDisplayName()),
                        rowIndex);
                this.getModel().setValue("clearsourcefield", (Object) "clear", rowIndex);
                if (!entitymap.contains(fieldKey))
                    continue;
                this.getView().setEnable(Boolean.FALSE, rowIndex, "canenable");
                this.getView().setEnable(Boolean.FALSE, rowIndex, "canwriteback");
            }
        }
    }

    public List<String> getRestrictedAttributeMap(String billtype) {
        Map<String, Object> filedmap = RestrictedAttributeMap.RESTRICTED_ATTRIBUTE_MAP;
        if (filedmap.get(billtype) != null) {
            String[] ra = ((String) filedmap.get(billtype)).split(",");
            return Arrays.asList(ra);
        }
        return new ArrayList<String>();
    }

    /**
     * @MethodName buildMetaContext
     * @Author  SC
     * @Description 构建 单据 元上下文
     * @Date 14:29 2023/7/18
     * @Param [entityBill] [java.lang.Object]
     * @return void
     **/
    private void buildMetaContext(Object entityBill) {
        if (entityBill instanceof DynamicObject) {
            ArrayList<List<Map<String, Object>>> formContext = new ArrayList<List<Map<String, Object>>>();
            formContext.add(this.buildDesignContext((DynamicObject) entityBill));
            this.getView().getFormShowParameter().getCustomParams().put("MetaContext", formContext);
        }
    }
    /**
     * @MethodName buildDesignContext
     * @Author  SC
     * @Description 获取上下文信息
     * @Date 10:40 2023/7/31
     * @Param [entityBill] [kd.bos.dataentity.entity.DynamicObject]
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     **/
    private List<Map<String, Object>> buildDesignContext(DynamicObject entityBill) {
        ArrayList<Map<String, Object>> metaItems = new ArrayList<Map<String, Object>>(10);
        String entityBillId = MetadataDao.getIdByNumber((String) entityBill.getPkValue().toString(),
                (MetaCategory) MetaCategory.Entity);
        EntityMetadata entityMetadata = (EntityMetadata) MetadataDao.readRuntimeMeta((String) entityBillId,
                (MetaCategory) MetaCategory.Entity);
        for (EntityItem item : entityMetadata.getItems()) {
            HashMap<String, Object> entityItem = new HashMap<String, Object>(16);
            entityItem.put("_Type_", item.getClass().getSimpleName());
            entityItem.put("Id", item.getId());
            entityItem.put("ParentId", item.getParentId());
            entityItem.put("Key", item.getKey());
            entityItem.put("Name", item.getName().toString());
            metaItems.add(entityItem);
        }
        return metaItems;
    }

}
