package com.yem.wm.sys.formplugin.form;

import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.alibaba.fastjson.JSONObject;

import kd.bos.bill.AbstractBillPlugIn;
import kd.bos.bill.OperationStatus;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.entity.BillTypeControlInfo;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.EntityType;
import kd.bos.entity.EntryType;
import kd.bos.entity.LinkEntryType;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.form.CloseCallBack;
import kd.bos.form.FormShowParameter;
import kd.bos.form.IFormView;
import kd.bos.form.ShowType;
import kd.bos.form.control.Control;
import kd.bos.form.control.events.ItemClickEvent;
import kd.bos.form.events.ClosedCallBackEvent;
import kd.bos.form.field.BasedataEdit;
import kd.bos.form.field.ComboEdit;
import kd.bos.form.field.ComboItem;
import kd.bos.form.field.events.BeforeF7SelectEvent;
import kd.bos.form.field.events.BeforeF7SelectListener;
import kd.bos.lang.Lang;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BillTypeDifferentialHelper;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.scmc.sbs.common.util.F7Utils;
import kd.scmc.sbs.common.util.FormUtil;

/**
 * 创建新版本方案维护-表单插件
 * @description:
 * @author longh
 * @date 2021年11月8日 上午10:05:40
 */
public class NewVersionTplFormPlugIn extends AbstractBillPlugIn implements BeforeF7SelectListener {


    private static final String KEY_VCHECK = "yem_tpl_versioncheckrule";//版本变更【校验规则】单据标识
    private static final String KEY_CCHECK = "yem_tpl_versioncheckcols";//版本变更【校验字段】单据标识

    @Override
    public void afterLoadData(EventObject e) {
        super.afterLoadData(e);

    }

    @Override
    public void afterBindData(EventObject e) {
        super.afterBindData(e);
        DynamicObject entityObj = (DynamicObject) this.getModel().getValue("yem_changebill");
        if(entityObj != null) {
            String entityNumber = entityObj.getString("number");
            this.fillEntityCombo(entityNumber);
        }
    }

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        this.addClickListeners(new String[]{"yem_checkrule", "yem_checkcols"});
        this.addItemClickListeners(new String[]{"yem_tbtypes", "yem_advcontoolbarap1"});
        ((BasedataEdit) this.getControl("yem_requirebill")).addBeforeF7SelectListener(this);
        ((BasedataEdit) this.getControl("yem_changebill")).addBeforeF7SelectListener(this);
        ((BasedataEdit) this.getControl("yem_changebilltype")).addBeforeF7SelectListener(this);
    }

    @Override
    public void click(EventObject evt) {
        super.click(evt);
        String key = ((Control) evt.getSource()).getKey();
        switch (key) {
            case "yem_checkrule" :
                this.clickCheckRule(evt, key);
                break;
            case "yem_checkcols" :
                this.clickCheckCols(evt, key);
                break;
        }
    }

    private void clickCheckRule(EventObject evt, String key) {
        IFormView view = this.getView();
        IDataModel model = this.getModel();
        int rowIndex = model.getEntryCurrentRowIndex("yem_checkmap");
        DynamicObject entryRow = model.getEntryRowEntity("yem_checkmap", rowIndex);

        FormShowParameter showParameter = new FormShowParameter();
        showParameter.setStatus(OperationStatus.ADDNEW);
        showParameter.getOpenStyle().setShowType(ShowType.Modal);
        showParameter.setFormId(KEY_VCHECK);
        DynamicObject yem_changebill = FormUtil.getAndCheckF7Value(model, "yem_changebill");
        showParameter.setCustomParam("entityNumber", yem_changebill.getString("number"));
        showParameter.setCustomParam("data", entryRow);
        showParameter.setCloseCallBack(new CloseCallBack(this, KEY_VCHECK));
        view.showForm(showParameter);
    }

    private void clickCheckCols(EventObject evt, String key) {
        IFormView view = this.getView();
        IDataModel model = this.getModel();
        int rowIndex = model.getEntryCurrentRowIndex("yem_checkdelrow");
        DynamicObject entryRow = model.getEntryRowEntity("yem_checkdelrow", rowIndex);

        FormShowParameter showParameter = new FormShowParameter();
        showParameter.setStatus(OperationStatus.ADDNEW);
        showParameter.getOpenStyle().setShowType(ShowType.Modal);
        showParameter.setFormId(KEY_CCHECK);
        DynamicObject yem_changebill = FormUtil.getAndCheckF7Value(model, "yem_changebill");
        showParameter.setCustomParam("entityNumber", yem_changebill.getString("number"));
        showParameter.setCustomParam("data", entryRow);
        showParameter.setCloseCallBack(new CloseCallBack(this, KEY_CCHECK));
        view.showForm(showParameter);
    }

    @Override
    public void itemClick(ItemClickEvent evt) {
        super.itemClick(evt);
        String itemKey = evt.getItemKey();
        switch (itemKey) {
            case "yem_updatebt":
                this.initBilltypes();
                break;
            case "yem_updatecols":
                this.updateTreeCols();
                break;
            default:
                break;
        }
    }

    private void updateTreeCols() {
        IDataModel model = this.getModel();
        DynamicObject entityObj = model.getDataEntity().getDynamicObject("yem_changebill");
        if(entityObj != null) {
            String entityNumber = entityObj.getString("number");
            Map<String, BillTypeControlInfo> ctlInfos = BillTypeDifferentialHelper.getFullControlInfos(entityNumber);

            DynamicObjectCollection yem_colsmap = model.getEntryEntity("yem_colsmap");
            for (DynamicObject row : yem_colsmap) {
                String yem_billcolno = row.getString("yem_billcolno");
                if(ctlInfos.containsKey(yem_billcolno)) {
                    ctlInfos.remove(yem_billcolno);
                }
            }
            for (Entry<String, BillTypeControlInfo> ctlInfo : ctlInfos.entrySet()) {
                int rowIndex = this.getModel().createNewEntryRow("yem_colsmap");
                this.initColsTreePage(ctlInfo.getValue(), rowIndex);
            }
        }
    }

    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        super.propertyChanged(e);
        String name = e.getProperty().getName();
        switch (name) {
            case "yem_requirebill" :
                this.requireBillChanged(e, name);
                break;
            case "yem_changebill" :
                this.changeBillChanged(e, name);
                break;
        }
    }

    private void requireBillChanged(PropertyChangedArgs e, String name) {
        this.initBilltypes();
    }

    private void initBilltypes() {
        IDataModel model = this.getModel();
        model.deleteEntryData("yem_billtypes");

        DynamicObject yem_requirebill = (DynamicObject) model.getValue("yem_requirebill");
        if(yem_requirebill != null) {
            DynamicObject[] billtypes = BusinessDataServiceHelper.load("bos_billtype", "id",
                    new QFilter[] {new QFilter("status", QCP.equals, "C"),
                            new QFilter("enable", QCP.equals, "1"),
                            new QFilter("billformid", QCP.equals, yem_requirebill.getPkValue())});
            for (DynamicObject billtype : billtypes) {
                int index = model.createNewEntryRow("yem_billtypes");
                model.setValue("yem_srcbilltype", billtype, index);
            }
        }
    }

    private void changeBillChanged(PropertyChangedArgs e, String name) {
        IDataModel model = this.getModel();
        model.deleteEntryData("yem_colsmap");
        model.deleteEntryData("yem_checkmap");
        model.deleteEntryData("yem_checkdelrow");

        DynamicObject entityObj = model.getDataEntity().getDynamicObject(name);
        if(entityObj != null) {
            String entityNumber = entityObj.getString("number");
            this.initColsTreePages(entityNumber);
            this.fillEntityCombo(entityNumber);
            this.initCheckDelRowEntity(model, entityNumber);
        }
    }

    private void initColsTreePages(String entityNumber) {
        Map<String, BillTypeControlInfo> ctlInfos = BillTypeDifferentialHelper.getFullControlInfos(entityNumber);
        for (Entry<String, BillTypeControlInfo> ctlInfo : ctlInfos.entrySet()) {
            int rowIndex = this.getModel().createNewEntryRow("yem_colsmap");
            this.initColsTreePage(ctlInfo.getValue(), rowIndex);
        }
    }

    private void initColsTreePage(BillTypeControlInfo ctlInfo, int rowIndex) {
        IDataModel model = this.getModel();
        model.setValue("yem_billcolno", ctlInfo.getFieldKey(), rowIndex);
        model.setValue("yem_billcol", ctlInfo.getFieldName(), rowIndex);
    }

    @Override
    public void closedCallBack(ClosedCallBackEvent e) {
        super.closedCallBack(e);
        String key = e.getActionId();
        switch (key) {
            case KEY_VCHECK :
                this.callBack4CheckRule(e);
                break;
            case KEY_CCHECK :
                this.callBack4CheckCols(e);
                break;
        }
    }

    private void callBack4CheckRule(ClosedCallBackEvent e) {
        String actionId = e.getActionId();
        Object returnData = e.getReturnData();
        if(actionId != null && returnData != null) {
            IDataModel model = this.getModel();
            JSONObject jsonObj = (JSONObject) returnData;
            int rowIndex = model.getEntryCurrentRowIndex("yem_checkmap");
            model.setValue("yem_checkrule", jsonObj.getString("yem_desc"), rowIndex);
            model.setValue("yem_checkjson", jsonObj.toJSONString(), rowIndex);
        }
    }

    private void callBack4CheckCols(ClosedCallBackEvent e) {
        String actionId = e.getActionId();
        Object returnData = e.getReturnData();
        if(actionId != null && returnData != null) {
            IDataModel model = this.getModel();
            JSONObject jsonObj = (JSONObject) returnData;
            int rowIndex = model.getEntryCurrentRowIndex("yem_checkdelrow");
            model.setValue("yem_checkcols", jsonObj.getJSONArray("yem_col").toString(), rowIndex);
            model.setValue("yem_checkcolsjson", jsonObj.getJSONArray("yem_colno").toString(), rowIndex);
        }
    }

    @Override
    public void beforeF7Select(BeforeF7SelectEvent e) {
        String key = e.getProperty().getName();
        switch (key) {
            case "yem_requirebill" :
            case "yem_changebill" :
                this.beforeF7SelectBill(e);
                break;
            case "yem_changebilltype" :
                this.beforeF7BillType(e);
                break;
        }
    }

    private void beforeF7SelectBill(BeforeF7SelectEvent e) {
        QFilter fs = F7Utils.getMetaTypeFs(new String[]{"BillFormModel"});//, "BaseFormModel"
        F7Utils.addF7Filter(e, fs);
    }

    private void beforeF7BillType(BeforeF7SelectEvent e) {
        DynamicObject yem_changebill = (DynamicObject) this.getModel().getValue("yem_changebill");
        Object billformid = yem_changebill == null ? 0L : yem_changebill.getPkValue();
        QFilter fs = new QFilter("billformid", QCP.equals, billformid);
        F7Utils.addF7Filter(e, fs);
    }

    private void fillEntityCombo(String entityNumber) {
        MainEntityType mainType = EntityMetadataCache.getDataEntityType(entityNumber);
        List<ComboItem> entryItems = this.buildEntryComboItems(mainType);
        ComboEdit entryEditor = (ComboEdit) this.getView().getControl("yem_checkentity");
        entryEditor.setComboItems(entryItems);
        ComboEdit entryEditor1 = (ComboEdit) this.getView().getControl("yem_checkdelentity");
        entryEditor1.setComboItems(entryItems);
    }

    private List<ComboItem> buildEntryComboItems(MainEntityType mainType) {
        ArrayList<ComboItem> entryItems = new ArrayList<>();
        String currLCId = Lang.get().toString();
        ComboItem blankItem = new ComboItem();
        blankItem.setValue("");
        blankItem.setCaption(new LocaleString());
        entryItems.add(blankItem);
        if (mainType != null) {
            Map<String, EntityType> entitys = mainType.getAllEntities();
            ComboItem headItem = new ComboItem();
            headItem.setValue(mainType.getName());
            headItem.setCaption(new LocaleString(currLCId, "单据头"));
            entryItems.add(headItem);

            for (EntityType entity : entitys.values()) {
                if (!(entity instanceof LinkEntryType) && entity instanceof EntryType) {
                    ComboItem entryItem = new ComboItem();
                    entryItem.setValue(entity.getName());
                    entryItem.setCaption(entity.getDisplayName());
                    entryItems.add(entryItem);
                }
            }
        }

        return entryItems;
    }

    private void initCheckDelRowEntity(IDataModel model, String entityNumber) {
        MainEntityType mainType = EntityMetadataCache.getDataEntityType(entityNumber);
        if (mainType != null) {
            Map<String, EntityType> entitys = mainType.getAllEntities();
            for (EntityType entity : entitys.values()) {
                if (!(entity instanceof LinkEntryType) && entity instanceof EntryType) {
                    int index = model.createNewEntryRow("yem_checkdelrow");
                    model.setValue("yem_checkdelentity", entity.getName(), index);
                }
            }
        }
    }
}
