package cn.ibizlab.codegen.model;


import cn.ibizlab.codegen.utils.StringAdvUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.ibizsys.model.app.view.IPSAppViewRef;
import net.ibizsys.model.control.IPSControl;
import net.ibizsys.model.control.IPSControlContainer;
import net.ibizsys.model.control.dashboard.IPSDBContainerPortletPart;
import net.ibizsys.model.control.dashboard.IPSDBPortletPart;
import net.ibizsys.model.control.dataview.IPSDEDataView;
import net.ibizsys.model.control.form.*;
import net.ibizsys.model.control.grid.IPSDEGrid;
import net.ibizsys.model.control.grid.IPSDEGridColumn;
import net.ibizsys.model.control.list.IPSList;
import net.ibizsys.model.control.panel.IPSLayoutPanel;
import net.ibizsys.model.control.toolbar.IPSDETBUIActionItem;
import net.ibizsys.model.control.toolbar.IPSDEToolbar;
import net.ibizsys.model.view.IPSUIAction;
import org.springframework.util.ObjectUtils;

import java.util.*;

@Getter
@Setter
@NoArgsConstructor
@Accessors(chain = true)
public class CtrlModel extends BaseModel{

    public CtrlModel(AppModel appModel,IPSControl psControl)
    {
        this.opt=psControl;
        this.app=appModel;
        this.setCodeName(psControl.getCodeName());
        this.setName(psControl.getName());

        if(psControl.getPSAppDataEntity()!=null)
            folder=new LabelExt(psControl.getPSAppDataEntity().getCodeName());
        else
            folder=new LabelExt("app");

        this.setId(String.format("%1$s-%2$s-%3$s-%4$s",app.getCodeName(),folder,psControl.getName(),psControl.getCodeName()));

        if(psControl instanceof IPSControlContainer){
            List<IPSAppViewRef> IPSAppViewRefs = ((IPSControlContainer)psControl).getPSAppViewRefs();
            if(IPSAppViewRefs != null && IPSAppViewRefs.size() >0){
                IPSAppViewRefs.forEach(appViewRef ->{
                    if(viewRefMap.get(appViewRef.getRefPSAppView().getId()) == null){
                        viewRefMap.put(appViewRef.getRefPSAppView().getId(),appViewRef);
                    }
                });
            }
        }
        handleChildControls();
        if("DASHBOARD".equals( getControl().getControlType())){
            handleAllPortlets((IPSControlContainer)getControl());
        }
    }

    public Map<String,CtrlModel> ctrlsMap = new LinkedHashMap();

    public Map<String,IPSControl> portletsMap = new LinkedHashMap();

    private AppModel app;

    private AppEntityModel appEntity;

    private LabelExt folder;

    private Map<String, IPSAppViewRef> viewRefMap = new LinkedHashMap();

    private String _quickToolbarName;
    public String getQuickToolBarName() { return _quickToolbarName; };
    private Collection<JSONObject> _quickToolbarItems = new ArrayList<>();
    public Collection<JSONObject> getQuickToolBarItems(){
        return _quickToolbarItems;
    }

    private String _batchToolbarName;
    public String getBatchToolBarName() { return _batchToolbarName; };
    private Collection<JSONObject> _batchToolbarItems = new ArrayList<>();
    public Collection<JSONObject> getBatchToolBarItems(){
        return _batchToolbarItems;
    }


    public CtrlModel addCtrl(String codeName,CtrlModel ctrlModel)
    {
        if(!ctrlsMap.containsKey(codeName))
            ctrlsMap.put(codeName,ctrlModel);
        return this;
    }

    public Collection<CtrlModel> getCtrls()
    {
        return ctrlsMap.values();
    }

    public Collection<IPSControl> getAllPortlets()
    {
        return portletsMap.values();
    }

    public IPSControl getControl()
    {
        return (IPSControl)opt;
    }

    public String getTempFilter() {
        String name = this.getControl().getName();
        if ("QUICKSEARCHFORM".equals(name.toUpperCase())) {
            return "QUICKSEARCHFORM";
        } else {
            return this.getControl().getControlType();
        }
    }

    public Collection<IPSAppViewRef> getAppViewRefs(){
        return this.viewRefMap.values();
    }

    public void handleChildControls() {
        IPSControl control = getControl();
        //  具有子部件的容器部件
        if (control instanceof IPSControlContainer) {
            IPSControlContainer controlContainer = (IPSControlContainer)control;
            List<IPSControl> controls = controlContainer.getPSControls();
            if (controls != null && controls.size() > 0) {
                for (IPSControl _control : controls) {
                    CtrlModel ctrlModel = new CtrlModel(app, _control);
                    if(ctrlModel.getControl().getPSAppDataEntity() != null) {
                        AppEntityModel ctrlAppEntity = app.getAppEntity(ctrlModel.getControl().getPSAppDataEntity().getCodeName());
                        ctrlModel.setAppEntity(ctrlAppEntity);
                        ctrlAppEntity.addCtrl(ctrlModel.getId(), ctrlModel);
                    }
                    addCtrl(ctrlModel.getId(), ctrlModel);
                    if(!app.getCtrlsMap().containsKey(ctrlModel.getId())) {
                        app.getCtrlsMap().put(ctrlModel.getId(),ctrlModel);
                    }
                    if("TOOLBAR".equals(_control.getControlType())){
                        JSONObject mdToolbar = new JSONObject();
                        mdToolbar.put("codeName",_control.getCodeName());
                        mdToolbar.put("controlType",_control.getControlType());
                        mdToolbar.put("logicName",_control.getLogicName());
                        if(((IPSDEToolbar)_control).getPSDEToolbarItems() != null){
                            JSONArray items = new JSONArray();
                            ((IPSDEToolbar)_control).getPSDEToolbarItems().forEach(singleItam ->{
                                JSONObject toolbarItem = new JSONObject();
                                toolbarItem.put("caption",singleItam.getCaption());
                                if(singleItam.getCapPSLanguageRes() != null && singleItam.getCapPSLanguageRes().getLanResTag() != null){
                                    toolbarItem.put("capPSLanguageRes",singleItam.getCapPSLanguageRes().getLanResTag());
                                }
                                toolbarItem.put("tooltip",singleItam.getTooltip());
                                if(singleItam.getTooltipPSLanguageRes() != null && singleItam.getTooltipPSLanguageRes().getLanResTag() != null){
                                    toolbarItem.put("tooltipPSLanguageRes",singleItam.getTooltipPSLanguageRes().getLanResTag());
                                }
                                toolbarItem.put("itemType",singleItam.getItemType());
                                toolbarItem.put("name",singleItam.getName());
                                toolbarItem.put("showCaption",singleItam.isShowCaption());
                                toolbarItem.put("showIcon",singleItam.isShowIcon());
                                if(singleItam.getPSSysImage() != null && singleItam.getPSSysImage().getCssClass() != null){
                                    toolbarItem.put("iconClass",singleItam.getPSSysImage().getCssClass());
                                }
                                if(singleItam.getPSSysImage() != null && singleItam.getPSSysImage().getImagePath() != null){
                                    toolbarItem.put("imgPath",singleItam.getPSSysImage().getImagePath());
                                }
                                if("DEUIACTION".equals(singleItam.getItemType())){
                                    IPSDETBUIActionItem actionItem = (IPSDETBUIActionItem)singleItam;
                                    toolbarItem.put("groupExtractMode",actionItem.getNoPrivDisplayMode());
                                    toolbarItem.put("noPrivDisplayMode",actionItem.getNoPrivDisplayMode());
                                    toolbarItem.put("id",actionItem.getPSAppViewUIAction().getId());
                                    toolbarItem.put("xDataControlName",actionItem.getPSAppViewUIAction().getXDataControlName());
                                    if(actionItem.getPSAppViewUIAction().getPSUIAction() != null){
                                        IPSUIAction UIAction = actionItem.getPSAppViewUIAction().getPSUIAction();
                                        JSONObject appUIAction = new JSONObject();
                                        appUIAction.put("caption",UIAction.getCaption());
                                        if(UIAction.getCapPSLanguageRes() != null && UIAction.getCapPSLanguageRes().getLanResTag() != null){
                                            appUIAction.put("capPSLanguageRes",UIAction.getCapPSLanguageRes().getLanResTag());
                                        }
                                        appUIAction.put("codeName",UIAction.getCodeName());
                                        appUIAction.put("fullCodeName",UIAction.getFullCodeName());
                                        appUIAction.put("name",UIAction.getName());
                                        appUIAction.put("uIActionMode",UIAction.getUIActionMode());
                                        appUIAction.put("uIActionTag",UIAction.getUIActionTag());
                                        appUIAction.put("uIActionType",UIAction.getUIActionType());
                                        appUIAction.put("actionTarget",UIAction.getActionTarget());
                                        appUIAction.put("dataAccessAction",UIAction.getDataAccessAction());
                                        toolbarItem.put("uIAction",appUIAction);
                                    }
                                }
                                items.add(toolbarItem);
                            });
                            mdToolbar.put("items", items);
                        }
                        if (_control.getName() != null && _control.getName().endsWith("quicktoolbar")) {
                            _quickToolbarItems.add(mdToolbar);
                            _quickToolbarName = _control.getName();
                        }
                        if (_control.getName() != null && _control.getName().endsWith("batchtoolbar")) {
                            _batchToolbarItems.add(mdToolbar);
                            _batchToolbarName = _control.getName();
                        }
                    }
                }
            }
        }
        //  列表部件项布局面板
        if (control instanceof IPSList) {
            IPSList list = (IPSList)control;
            IPSLayoutPanel layoutPanel = list.getItemPSLayoutPanel();
            if (layoutPanel != null) {
                CtrlModel ctrlModel = new CtrlModel(app, layoutPanel);
                if (ctrlModel.getControl().getPSAppDataEntity() != null) {
                    AppEntityModel ctrlAppEntity = app.getAppEntity(ctrlModel.getControl().getPSAppDataEntity().getCodeName());
                    ctrlModel.setAppEntity(ctrlAppEntity);
                    ctrlAppEntity.addCtrl(ctrlModel.getId(), ctrlModel);
                }
                addCtrl(ctrlModel.getId(), ctrlModel);
                if(!app.getCtrlsMap().containsKey(ctrlModel.getId())) {
                    app.getCtrlsMap().put(ctrlModel.getId(),ctrlModel);
                }
            }
        }
        //  卡片视图部件项布局面板
        if (control instanceof IPSDEDataView) {
            IPSDEDataView dataView = (IPSDEDataView) control;
            IPSLayoutPanel layoutPanel = dataView.getItemPSLayoutPanel();
            if (layoutPanel != null) {
                CtrlModel ctrlModel = new CtrlModel(app, layoutPanel);
                if (ctrlModel.getControl().getPSAppDataEntity() != null) {
                    AppEntityModel ctrlAppEntity = app.getAppEntity(ctrlModel.getControl().getPSAppDataEntity().getCodeName());
                    ctrlModel.setAppEntity(ctrlAppEntity);
                    ctrlAppEntity.addCtrl(ctrlModel.getId(), ctrlModel);
                }
                addCtrl(ctrlModel.getId(), ctrlModel);
                if(!app.getCtrlsMap().containsKey(ctrlModel.getId())) {
                    app.getCtrlsMap().put(ctrlModel.getId(),ctrlModel);
                }
            }
        }

    }

    public void handleAllPortlets(IPSControlContainer control) {
        List<IPSControl> controls = control.getPSControls();
        if (controls != null && controls.size() > 0) {
            for (IPSControl _control : controls) {
                if("CONTAINER".equals( ((IPSDBPortletPart)_control).getPortletType() )){
                    this.handleAllPortlets((IPSControlContainer)_control);
                }else{
                    if(!this.portletsMap.containsKey(_control.getCodeName())) {
                        this.portletsMap.put(_control.getCodeName(),_control);
                    }
                }
            }
        }
    }

    //  表格是否需要空白列
    public Boolean isNeedEmptyColumn() {
        if (getControl().getControlType() != null && "GRID".equals(getControl().getControlType())) {
            Boolean flag = true;
            for (IPSDEGridColumn column : ((IPSDEGrid)getControl()).getPSDEGridColumns()) {
                //  自适应列
                if (
                    column.getWidthUnit() != null
                    && "STAR".equals(column.getWidthUnit())
                    && column.getColumnType() != null
                    && !"GROUPGRIDCOLUMN".equals(column.getColumnType())
                ) {
                    flag = false;
                    break;
                }
            }
            return flag;
        }
        return false;
    }

    //  获取表格列总宽度
    public Integer getTotalColumnWidth() {
        Integer width = 10;
        if (getControl().getControlType() != null && "GRID".equals(getControl().getControlType())) {
            for (IPSDEGridColumn column : ((IPSDEGrid)getControl()).getPSDEGridColumns()) {
                width += column.getWidth();
            }
        }
        return width;
    }

    //  忽略发布
    public Boolean ignore() {
        IPSControl control = getControl();
        //  忽略容器门户部件
        if (control instanceof IPSDBContainerPortletPart) {
            return true;
        }
        //  后续有忽略发布的部件在此处补充
        return false;
    }

    public String getApiModelName()
    {
        if(appEntity!=null&&appEntity.getEntity()!=null) {

            return StringAdvUtils.pascalcase(appEntity.getEntity().getCodeName())+StringAdvUtils.pascalcase(getCodeName());
        }
        return StringAdvUtils.pascalcase(getCodeName());
    }

    private Map<String,VoFieldModel> voItemSets;

    public Map<String,VoFieldModel> getVoItemSets()
    {
        if(voItemSets==null && this.getControl() instanceof IPSDEEditForm)
        {
            IPSDEEditForm editForm=(IPSDEEditForm)this.getControl();

            if(editForm.getPSDEFormItems()!=null)
            {
                voItemSets = new LinkedHashMap<>();
                editForm.getPSDEFormPages().forEach(page->{
                    loopItem(page.getPSDEFormDetails()).forEach(item->{
                        VoFieldModel field=new VoFieldModel(this,item);
                        field.setPosition(voItemSets.size()+1);
                        voItemSets.put(field.getName().toLowerCase(),field);
                    });
                });
                if(appEntity!=null&&appEntity.getEntity()!=null)
                {
                    FieldModel keyField=appEntity.getEntity().getKeyField();
                    if(!voItemSets.containsKey(keyField.getCodeName().toLowerCase()))
                        sysField.put("key",keyField);
                    else
                        sysField.put("key",voItemSets.get(keyField.getCodeName().toLowerCase()));
                    FieldModel mainField=appEntity.getEntity().getMajorField();
                    if(mainField!=null && !voItemSets.containsKey(mainField.getCodeName().toLowerCase()))
                        sysField.put("major",mainField);
                    else if (voItemSets.containsKey(mainField.getCodeName().toLowerCase()))
                        sysField.put("major",voItemSets.get(mainField.getCodeName().toLowerCase()));
                }
            }
        }
        return voItemSets;
    }

    private Map<String,BaseModel> sysField=new LinkedHashMap<>();

    public Collection<VoFieldModel> getVoItems()
    {
        if(getVoItemSets()!=null)
            return voItemSets.values();
        return null;
    }


    public List<IPSDEFormItem> loopItem(List<IPSDEFormDetail> items)
    {
        List<IPSDEFormItem> list=new ArrayList<>();
        if(!ObjectUtils.isEmpty(items))
        {
            for(IPSDEFormDetail item:items)
            {
                if(item instanceof IPSDEFormItem) {
                    list.add((IPSDEFormItem)item);
                }
                else if(item instanceof IPSDEFormGroupBase)
                {
                    list.addAll(loopItem(((IPSDEFormGroupBase)item).getPSDEFormDetails()));
                }
            }
        }
        return list;
    }

}
