package com.yem.wm.es.salesorder.dynamic;

import com.yem.em.utils.BigDecimalUtils;
import com.yem.wm.es.shippingdetails.util.PaymentControlUtil;
import com.yem.wm.utils.YEM;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.form.FormShowParameter;
import kd.bos.form.IFormView;
import kd.bos.form.control.Button;
import kd.bos.form.control.Control;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.sdk.plugin.Plugin;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 下达跟单任务 表单插件
 */
public class ShippingPlanEdit extends AbstractFormPlugin implements Plugin
{

    @Override
    public void afterCreateNewData(EventObject e)
    {
        super.afterCreateNewData(e);
        IDataModel model = this.getModel();
        FormShowParameter showParameter = this.getView().getFormShowParameter();
        Map<String, Object> cusMap = showParameter.getCustomParams();
        long billId = cusMap.containsKey("billId") ? (long) cusMap.get("billId") : 0L;
        if (0L != billId) {
            DynamicObject bill = BusinessDataServiceHelper.loadSingle(billId, "yem_es_salesorder");
            bill = BusinessDataServiceHelper.loadSingle(bill.getPkValue(), "yem_es_salesorder");

            DynamicObjectCollection yem_shippingplan_entry = bill.getDynamicObjectCollection("yem_shippingplan_entry");
            //获取外销合同信息
            model.setValue("yem_nameplatetypegd", bill.getString("yem_nameplatetype"));
            model.setValue("yem_nameplatelogogd", bill.getDynamicObject("yem_nameplatelogo"));
            model.setValue("yem_nameplateqtygd", bill.getBigDecimal("yem_nameplateqty"));
            int yem_lotno = yem_shippingplan_entry.size() + 1;
            model.setValue("yem_lotno", "0" + yem_lotno);
            BigDecimal yem_exrate = bill.getBigDecimal("yem_exrate");
//            model.setValue("yem_acshipdate1", bill.getString("yem_acshipdate1"));

            DynamicObjectCollection yem_es_materialinfo_s = bill.getDynamicObjectCollection("yem_es_materialinfo");
            for (int i = 0; i < yem_es_materialinfo_s.size(); i++) {
                DynamicObject yem_es_materialinfo = yem_es_materialinfo_s.get(i);
                String yem_lineclosstate = yem_es_materialinfo.getString("yem_lineclosstate");//A 正常  B关闭
                if (yem_lineclosstate.equals("B")) {
                    continue;
                }
                BigDecimal yem_qty = yem_es_materialinfo.getBigDecimal("yem_qty");
                BigDecimal yem_orderqty = yem_es_materialinfo.getBigDecimal("yem_orderqty");
                int rowIndex = model.createNewEntryRow("yem_es_materialinfo");
                model.setValue("yem_unorderqty", BigDecimalUtils.sub(yem_qty, yem_orderqty, 10), rowIndex);
                model.setValue("yem_planqty", BigDecimalUtils.sub(yem_qty, yem_orderqty, 10), rowIndex);
                model.setValue("yem_orderallocation", yem_es_materialinfo.get("yem_orderallocation"), rowIndex);
                model.setValue("yem_orderallocationen", yem_es_materialinfo.get("yem_orderallocationen"), rowIndex);
                model.setValue("yem_materialclass", yem_es_materialinfo.get("yem_materialclass"), rowIndex);
                model.setValue("yem_businesssort", yem_es_materialinfo.get("yem_businesssort"), rowIndex);
                model.setValue("yem_productmodel", yem_es_materialinfo.get("yem_productmodel"), rowIndex);
                model.setValue("yem_ifreformg", yem_es_materialinfo.get("yem_ifreformg"), rowIndex);
                model.setValue("yem_reformdesg", yem_es_materialinfo.get("yem_reformdesg"), rowIndex);
                model.setValue("yem_ifsupportg", yem_es_materialinfo.get("yem_ifsupportg"), rowIndex);
                model.setValue("yem_combofield8", yem_es_materialinfo.get("yem_combofield8"), rowIndex);
                model.setValue("yem_materiel", yem_es_materialinfo.get("yem_materiel"), rowIndex);
                model.setValue("yem_resourcenog", yem_es_materialinfo.get("yem_resourcenog"), rowIndex);
                model.setValue("yem_materialname", yem_es_materialinfo.get("yem_materialname"), rowIndex);
                model.setValue("yem_materialenname", yem_es_materialinfo.get("yem_materialenname"), rowIndex);
                model.setValue("yem_specification", yem_es_materialinfo.get("yem_specification"), rowIndex);
                model.setValue("yem_unit", yem_es_materialinfo.get("yem_unit"), rowIndex);
                model.setValue("yem_qty", yem_es_materialinfo.get("yem_qty"), rowIndex);
                model.setValue("yem_baseunit", yem_es_materialinfo.get("yem_baseunit"), rowIndex);
                model.setValue("yem_baseqty", yem_es_materialinfo.get("yem_baseqty"), rowIndex);
                model.setValue("yem_isgift", yem_es_materialinfo.get("yem_ifgift"), rowIndex);
                model.setValue("yem_remarks", yem_es_materialinfo.get("yem_remarks"), rowIndex);
                model.setValue("yem_srcentryid", yem_es_materialinfo.get("id"), rowIndex);
                model.setValue("yem_price", yem_es_materialinfo.get("yem_sapricepriceclause"), rowIndex);
                BigDecimal yem_price = yem_es_materialinfo.getBigDecimal("yem_sapricepriceclause");
                BigDecimal yem_amount = BigDecimalUtils.multiply(yem_qty, yem_price, 2);
                model.setValue("yem_amount", yem_amount, rowIndex);
                model.setValue("yem_amountloc", BigDecimalUtils.multiply(yem_amount, yem_exrate, 2), rowIndex);
            }
            thisqty();
            this.getView().updateView("yem_thisqty");
        }
    }

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

    @Override
    public void registerListener(EventObject e)
    {
        super.registerListener(e);
        Button btnok = this.getView().getControl("btnok");
        if (null != btnok) {
            this.addClickListeners(new String[]{"btnok"});
        }
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs e)
    {
        super.afterDoOperation(e);
    }

    @Override
    public void propertyChanged(PropertyChangedArgs e)
    {
        super.propertyChanged(e);
        IDataModel model = this.getModel();
        String name = e.getProperty().getName();
        if (name.equals("yem_planqty")) {
            thisqty();
            this.getView().updateView("yem_thisqty");
        }

        // 铭牌类型
        // 普通铭牌	P
        // 特殊铭牌	T
        if ("yem_nameplatetypegd".equals(name)) {
            String value = (String) model.getValue("yem_nameplatetypegd");
            if ("P".equals(value)) {
                DynamicObject single = BusinessDataServiceHelper.loadSingle("yem_bd_nameplatelogo", new QFilter[]{new QFilter("number", "=", "55036C00004300")});
                model.setValue("yem_nameplatelogogd", single);
            } else {
                model.setValue("yem_nameplatelogogd", null);
            }
        }
    }

    @Override
    public void click(EventObject evt)
    {
        super.click(evt);
        Control source = (Control) evt.getSource();
        String key = source.getKey();
        IDataModel model = this.getModel();
        IFormView view = this.getView();
        if ("btnok".equals(key)) {

            if (!orderConfirm()) return;
            StringBuilder sb = new StringBuilder();
            DynamicObjectCollection yemEsMaterialinfo = this.getModel().getEntryEntity("yem_es_materialinfo");
            if (!yemEsMaterialinfo.isEmpty()){
                BigDecimal bigDecimal = BigDecimal.ZERO;
                BigDecimal yemNameplateqtygd = new BigDecimal((int)this.getModel().getValue("yem_nameplateqtygd"));
                for (DynamicObject dynamicObject : yemEsMaterialinfo) {
                    String yemBusinesssort = dynamicObject.getString("yem_businesssort");
                    BigDecimal yemPlanqty = dynamicObject.getBigDecimal("yem_planqty");
                    if ("Z".equals(yemBusinesssort)){
                        bigDecimal = bigDecimal.add(yemPlanqty);
                    }
                }
                if (bigDecimal.compareTo(yemNameplateqtygd)>0){
                    sb.append("铭牌数量不允许低于本次整机下单数量，请检查！！！").append("\r\n");
                }
            }

            IFormView parentView = view.getParentView();
            IDataModel parentViewModel = parentView.getModel();
            String type = ((DynamicObject)parentViewModel.getValue("yem_billtype")).getString("number");
            if ("yem_es_salesorder_ZJ".equals(type) || "yem_es_salesorder_nmzj".equals(type)) {
                String nameplatetypegd = (String) model.getValue("yem_nameplatetypegd");//铭牌类型
                if (YEM.isEmpty(nameplatetypegd)) {
                    sb.append("整机合同下达跟单任务，铭牌类型必填，请检查！！").append("\r\n");
                }
                DynamicObject nameplatelogogd = (DynamicObject) model.getValue("yem_nameplatelogogd");//铭牌标识
                if (YEM.isEmpty(nameplatelogogd)) {
                    sb.append("整机合同下达跟单任务，铭牌标识必填，请检查！！").append("\r\n");
                }
            }

            if (sb.length() > 0) {
                view.showMessage(sb.toString());
                return;
            }

            Map map = new HashMap();
            Date yem_acshipdate1 = (Date) this.getView().getModel().getValue("yem_acshipdate1");
            if (yem_acshipdate1 == null) {
                this.getView().showMessage("请填写【预计需求入库时间】！");
                return;
            }
            String yem_nameplatetypegd = (String) this.getView().getModel().getValue("yem_nameplatetypegd");
            map.put("yem_nameplatetypegd", yem_nameplatetypegd);
            DynamicObject yem_nameplatelogo = (DynamicObject) this.getView().getModel().getValue("yem_nameplatelogogd");
            if (yem_nameplatelogo != null) {
                map.put("yem_nameplatelogogd", yem_nameplatelogo);
            }
            map.put("yem_nameplateqtygd", (int) this.getView().getModel().getValue("yem_nameplateqtygd"));
            map.put("yem_lotno", (String) this.getView().getModel().getValue("yem_lotno"));
            map.put("yem_thisqty", (int) this.getView().getModel().getValue("yem_thisqty"));
            map.put("yem_placemark", (String) this.getView().getModel().getValue("yem_placemark"));
            map.put("yem_acshipdate1", (Date) this.getView().getModel().getValue("yem_acshipdate1"));

            DynamicObjectCollection yem_es_materialinfo_s = model.getEntryEntity("yem_es_materialinfo");
            for (int i = 0; i < yem_es_materialinfo_s.size(); i++) {
                List values = new ArrayList();
//                List Botpvalues = new ArrayList();
                DynamicObject yem_es_materialinfo = yem_es_materialinfo_s.get(i);
                String yem_businesssort = yem_es_materialinfo.getString("yem_businesssort");//业务分类
                if (map.containsKey("H")) {
                    values = (List) map.get("H");
                }
                if (map.containsKey(yem_businesssort)) {
                    values = (List) map.get(yem_businesssort);
                }
                BigDecimal yem_unorderqty = yem_es_materialinfo.getBigDecimal("yem_unorderqty");//剩余未下单数量
                BigDecimal yem_planqty = yem_es_materialinfo.getBigDecimal("yem_planqty");//本次下单数量
                if (yem_planqty.compareTo(BigDecimal.ZERO) == 0) {
                    continue;
                }
                if (yem_unorderqty.compareTo(yem_planqty) < 0) {
                    view.showMessage("商品明细第" + (i + 1) + "行，本次下单数量合计大于剩余未下单数量，请检查！");
                    return;
                }
                Map value = new HashMap();
                value.put("yem_orderallocation", yem_es_materialinfo.get("yem_orderallocation"));
                value.put("yem_orderallocationen", yem_es_materialinfo.get("yem_orderallocationen"));
                value.put("yem_materialclass", yem_es_materialinfo.get("yem_materialclass"));
                value.put("yem_businesssort", yem_es_materialinfo.get("yem_businesssort"));
                value.put("yem_productmodel", yem_es_materialinfo.get("yem_productmodel"));
                value.put("yem_ifreformg", yem_es_materialinfo.get("yem_ifreformg"));
                value.put("yem_reformdesg", yem_es_materialinfo.get("yem_reformdesg"));
                value.put("yem_ifsupportg", yem_es_materialinfo.get("yem_ifsupportg"));
                value.put("yem_combofield8", yem_es_materialinfo.get("yem_combofield8"));
                value.put("yem_materiel", yem_es_materialinfo.get("yem_materiel"));
                value.put("yem_resourcenog", yem_es_materialinfo.get("yem_resourcenog"));
                value.put("yem_materialname", yem_es_materialinfo.get("yem_materialname"));
                value.put("yem_materialenname", yem_es_materialinfo.get("yem_materialenname"));
                value.put("yem_specification", yem_es_materialinfo.get("yem_specification"));
                value.put("yem_needqty", yem_es_materialinfo.get("yem_needqty"));
                value.put("yem_unit", yem_es_materialinfo.get("yem_unit"));
                value.put("yem_planqty", yem_es_materialinfo.get("yem_planqty"));
//                value.put("yem_remarks1", yem_es_materialinfo.get("yem_remarks1"));
                value.put("yem_baseunit", yem_es_materialinfo.get("yem_baseunit"));
                value.put("yem_baseqty", yem_es_materialinfo.get("yem_baseqty"));
                value.put("yem_isgift", yem_es_materialinfo.get("yem_isgift"));
                value.put("yem_remarks", yem_es_materialinfo.get("yem_remarks"));
                value.put("yem_srcentryid", yem_es_materialinfo.get("yem_srcentryid"));
                value.put("yem_price", yem_es_materialinfo.get("yem_price"));
                value.put("yem_amount", yem_es_materialinfo.get("yem_amount"));
                value.put("yem_amountloc", yem_es_materialinfo.get("yem_amountloc"));

                values.add(value);
                map.put(yem_businesssort, values);
                map.put("H", values);
            }
            if (map.size() == 0) {
                view.showMessage("本次下单数量全部为空，请检查！");
                return;
            }
            this.getView().returnDataToParent(map);
//            this.getView().showMessage("下单成功!");
            this.getView().close();
        }
    }

    /**
     * 款项控制校验
     *
     * @return
     */
    private boolean paymentControlVerification()
    {
        IFormView view = this.getView();
        IDataModel model = this.getModel();
        IFormView parentView = view.getParentView();
        IDataModel parentViewModel = parentView.getModel();
        DynamicObject parentDataEntity = parentViewModel.getDataEntity(true);
        DynamicObject dataEntity = model.getDataEntity(true);
        // 当前下单的金额
        DynamicObjectCollection formEntry = dataEntity.getDynamicObjectCollection("yem_es_materialinfo");
        BigDecimal currentOrderAmount = BigDecimal.ZERO;
        for (DynamicObject dynamicObject : formEntry) {
            currentOrderAmount = currentOrderAmount.add(dynamicObject.getBigDecimal("yem_planqty").multiply(dynamicObject.getBigDecimal("yem_price")));
        }
        // 历史已下单金额
        BigDecimal historyOrderAmount = BigDecimal.ZERO;
        long id = (long) parentDataEntity.getPkValue();
        QFilter hFilter = new QFilter("yem_sourcebillid", QCP.equals, id);
        // 下单审批
        DynamicObject[] placeexamines = BusinessDataServiceHelper.load("yem_placeexamine", "id, billno, yem_amount", hFilter.toArray());
        for (DynamicObject placeexamine : placeexamines) {
            historyOrderAmount = historyOrderAmount.add(placeexamine.getBigDecimal("yem_amount"));
        }
        // 当前合同认款金额
        BigDecimal currentContractClaimAmount = BigDecimal.ZERO;
        QFilter qFilter = new QFilter("yem_receiptdetail.yem_claimdetail.yem_salcontractno", QCP.equals, id);
        qFilter.and(new QFilter("billstatus", QCP.equals, "C"));
        qFilter.and(new QFilter("yem_financeaffirm", QCP.equals, "B"));
        DynamicObject[] gatherings = BusinessDataServiceHelper.load("yem_gathering", "id, billno", qFilter.toArray());
        for (DynamicObject gathering : gatherings) {
            gathering = BusinessDataServiceHelper.loadSingle(gathering.getPkValue(), "yem_gathering");
            DynamicObjectCollection collection = gathering.getDynamicObjectCollection("yem_receiptdetail");
            for (DynamicObject dynamicObject : collection) {
                DynamicObjectCollection subCollection = dynamicObject.getDynamicObjectCollection("yem_claimdetail");
                for (DynamicObject subObject : subCollection) {
                    DynamicObject salcontractno = subObject.getDynamicObject("yem_salcontractno");
                    if (salcontractno == null) continue;
                    long salcontractid = salcontractno.getLong("id");
                    if (salcontractid == id) {
                        String moneynature = subObject.getString("yem_moneynature");
                        if (YEM.isEmpty(moneynature)) continue;
                        if ("D".equals(moneynature)) {
                            BigDecimal claimamt = subObject.getBigDecimal("yem_salcontractclaamt");
                            currentContractClaimAmount = currentContractClaimAmount.add(claimamt);
                        }
                    }
                }
            }
        }
        BigDecimal procPreRapRate = PaymentControlUtil.getProcPreRapRate(parentDataEntity);

        // 本次下单金额 * 预收比例
        BigDecimal thisAdvance = PaymentControlUtil.getAdvancePayment(currentOrderAmount, procPreRapRate);
        // 历史下单金额 * 预收比例
        BigDecimal historyAdvance = PaymentControlUtil.getAdvancePayment(historyOrderAmount, procPreRapRate);

        // (当前下单的金额+历史已下单金额)  是否小于等于(当前合同认款金额)（误差0.1之内）
        if (thisAdvance.add(historyAdvance).setScale(2, RoundingMode.HALF_UP).compareTo(currentContractClaimAmount.add(new BigDecimal("0.1"))) <= 0) {
            return true;
        }

        view.showErrorNotification(String.format("当前下单的应收金额【%s】 + 历史已下单应收金额【%s】 大于当前合同下单预收款认领金额【%s】，不允许下单，请确认！！", thisAdvance.setScale(2, RoundingMode.HALF_UP), historyAdvance.setScale(2, RoundingMode.HALF_UP), currentContractClaimAmount.setScale(2, RoundingMode.HALF_UP)));
        return false;
    }

    public void thisqty()
    {
        DynamicObject dataEntity = this.getModel().getDataEntity(true);
        DynamicObjectCollection entity = dataEntity.getDynamicObjectCollection("yem_es_materialinfo");//商品
        BigDecimal thisqty = BigDecimal.ZERO;
        for (int i = 0; i < entity.size(); i++) {
            DynamicObject materialinfo = entity.get(i);
            thisqty = thisqty.add(materialinfo.getBigDecimal("yem_planqty"));
        }
        dataEntity.set("yem_thisqty", thisqty);
    }

    /**
     * 下达跟单任务校验
     */
    private boolean orderConfirm()
    {
        IFormView view = this.getView();
        IDataModel parentModel = view.getParentView().getModel();
        DynamicObjectCollection entryEntity = parentModel.getEntryEntity("yem_es_salescontrac_s");
        DynamicObject parentDataEntity = parentModel.getDataEntity();
        IDataModel model = this.getModel();
        DynamicObject dataEntity = model.getDataEntity(true);
        // 结算方式为信用证是，如果有信用证收证，可以下单；没有判断是否有储备申请，有储备申请可以下单，没有储备申请不能下单
        for (DynamicObject object : entryEntity) {
            String rapstyle = object.getDynamicObject("yem_rapstyle").getString("number");

            if ("L/C".equals(rapstyle) || "JSFS08".equals(rapstyle)) {
                // 结算方式等于信用证时:
//                String lcnumber = object.getString("yem_lcnumber");
//
//                if (YEM.isNotEmpty(lcnumber)) {
//                    return true;
//                } else {
//                    view.showErrorNotification("当前单据不存在信用证收证，禁止下单！");
//                    return false;
//                }
                return true;
            }
        }

        // 有信用证不管预收

        // 结算方式不等于信用证时:
        Set<Boolean> set = new HashSet<>();

        for (DynamicObject dynamicObject : entryEntity) {
            // 是否合同预收
            boolean isprepayment = "A".equals(dynamicObject.getString("yem_isprepayment"));
            set.add(isprepayment);
        }

        // 收款计划-是否合同预收只要有一条为是:
        if (set.contains(Boolean.TRUE)) {

            // 是否有储备申请
            if (hasReserveApplication(parentDataEntity)) {

                // 商品明细
                DynamicObjectCollection parentEsMaterialinfo = parentModel.getEntryEntity("yem_es_materialinfo");

                StringBuilder sb = new StringBuilder();
                List<DynamicObject> list = new ArrayList<>(parentEsMaterialinfo);
                DynamicObjectCollection esMaterialinfo = dataEntity.getDynamicObjectCollection("yem_es_materialinfo");
                Map<Long, Integer> reserveRequestEntries = loadReserveRequestEntries(parentDataEntity);
                for (DynamicObject dynamicObject : esMaterialinfo) {
                    int index = esMaterialinfo.indexOf(dynamicObject);
                    // 本次下单数量
                    BigDecimal thisqty = dynamicObject.getBigDecimal("yem_planqty");
                    DynamicObject parentDyObj = list.get(index);
                    long entryId = (long) parentDyObj.getPkValue();
                    // 已下单数量
                    BigDecimal orderqty = parentDyObj.getBigDecimal("yem_orderqty");
                    BigDecimal order = thisqty.add(orderqty);
                    if (reserveRequestEntries.containsKey(entryId)) {
                        Integer integer = reserveRequestEntries.get(entryId);
                        if (order.compareTo(new BigDecimal(integer)) > 0) {
                            sb.append("商品明细第 ").append(index + 1).append(String.format(" 行，本次下单数量 [ %s ] + 历史已下单数量 [ %s ] 大于储备申请数量 [ %s ]，请检查！", thisqty.setScale(2, RoundingMode.HALF_UP), orderqty.setScale(2, RoundingMode.HALF_UP), integer)).append("\n");
                        }
                    }
                }

                if (sb.length() > 0) {
                    if (paymentControlVerification()) {
                        // 款项是否收齐
                        return true;
                    } else {
                        view.showErrorNotification(sb.toString());
                    }
                } else {
                    return true;
                }
            } else if (paymentControlVerification()) {
                // 款项是否收齐
                return true;
            }
//            else

//            {
//                view.showErrorNotification("当前单据款项未收齐，禁止下单！");
//                return false;
//            }
        }

        // 收款计划-是否合同预收全部为否：判断是否下推储备申请或者双签合同，只要满足一个，就允许下单
        return !set.contains(Boolean.TRUE);
    }

    private boolean hasReserveApplication(DynamicObject dataEntity)
    {
        long id = dataEntity.getLong("id");
        QFilter qFilter = new QFilter("yem_sourcebillid", QCP.equals, id);
        DynamicObject[] load = BusinessDataServiceHelper.load("yem_es_storageapply", "id", new QFilter[]{qFilter});
        return load.length > 0;
    }

    private Map<Long, Integer> loadReserveRequestEntries(DynamicObject dataEntity)
    {
        Map<Long, Integer> map = new HashMap<>();
        long id = dataEntity.getLong("id");
        QFilter qFilter = new QFilter("yem_sourcebillid", QCP.equals, id);
        DynamicObject[] load = BusinessDataServiceHelper.load("yem_es_storageapply", "id, billno, yem_es_materialinfo, yem_es_materialinfo.yem_sourceentryid, yem_es_materialinfo.yem_qty", new QFilter[]{qFilter});
        for (DynamicObject dynamicObject : load) {
            DynamicObjectCollection esMaterialinfo = dynamicObject.getDynamicObjectCollection("yem_es_materialinfo");
            for (DynamicObject object : esMaterialinfo) {
                long sourceentryid = object.getLong("yem_sourceentryid");
                BigDecimal qty = object.getBigDecimal("yem_qty");
                if (map.containsKey(sourceentryid)) {
                    Integer integer = map.get(sourceentryid);
                    map.put(sourceentryid, integer + qty.intValue());
                } else {
                    map.put(sourceentryid, qty.intValue());
                }
            }
        }
        return map;
    }
}