package cn.net.connor.std.processedit.newmeop;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.teamcenter.rac.aif.AbstractAIFApplication;
import com.teamcenter.rac.aif.AbstractAIFOperation;
import com.teamcenter.rac.aif.kernel.AIFComponentContext;
import com.teamcenter.rac.aif.kernel.InterfaceAIFComponent;
import com.teamcenter.rac.kernel.SoaUtil;
import com.teamcenter.rac.kernel.TCComponent;
import com.teamcenter.rac.kernel.TCComponentBOMLine;
import com.teamcenter.rac.kernel.TCComponentBOMWindow;
import com.teamcenter.rac.kernel.TCComponentBOMWindowType;
import com.teamcenter.rac.kernel.TCComponentItem;
import com.teamcenter.rac.kernel.TCComponentItemRevision;
import com.teamcenter.rac.kernel.TCComponentItemRevisionType;
import com.teamcenter.rac.kernel.TCComponentItemType;
import com.teamcenter.rac.kernel.TCComponentType;
import com.teamcenter.rac.kernel.TCException;
import com.teamcenter.rac.kernel.TCPropertyDescriptor;
import com.teamcenter.rac.kernel.TCSession;
import com.teamcenter.rac.util.MessageBox;
import com.teamcenter.rac.util.Registry;
import com.teamcenter.services.rac.core.DataManagementService;
import com.teamcenter.services.rac.core._2008_06.DataManagement.CreateIn;
import com.teamcenter.services.rac.core._2008_06.DataManagement.CreateInput;
import com.teamcenter.services.rac.core._2008_06.DataManagement.CreateOut;
import com.teamcenter.services.rac.core._2008_06.DataManagement.CreateResponse;

import cn.net.connor.std.aifrcp.KDialogController;
import cn.net.connor.std.aifrcp.util.KUtil;
import cn.net.connor.std.processedit.processview.KAssignResourceCommand;
import cn.net.connor.std.processedit.util.OptionItem;
import cn.net.connor.std.processedit.util.PrefComponent;
import cn.net.connor.std.processedit.util.ProcessUtil;

public class NewMeopDialogController extends KDialogController {

	private NewMeopDialog dialog;
	private TCComponentBOMLine targetLine;
	private TCComponentItemRevision targetRev;
	public static final String PREF_PREFIX = "Connor_AVIC_MEOP_";
	public static final String PREF_PREFIX_EXCEL = "Connor_AVIC_MEOPEXCEL_";
	public static final String PREF_PROPS = "Connor_AVIC_MEOP_Properties";
	public static final String PREF_REL_LOV = "Connor_AVIC_MEOP_LOV_";
	public static final String PREF_WORKCENTER_CLS_ID = "Connor_AVIC_MEOP_WorkCenter_Class";
	public static final Registry REG = Registry.getRegistry(NewMeopDialogController.class);

	protected List<MEOPType> meopTypes = new ArrayList<NewMeopDialogController.MEOPType>();
	protected List<PrefComponent> prefComponents = new ArrayList<PrefComponent>();
	protected int propCols = 1;
	protected PrefComponent shortDescPrefComp;
	private KAssignResourceCommand workcenterCmd;
	public TCSession session;
	public class MEOPType {
		protected String type;
		protected String disType;
		protected String additional;
		protected TCComponentItemType itemType;
		protected boolean isPrecise;

		public MEOPType(TCSession session, String type, String disType, String additional, boolean isPrecise) throws Exception {
			this.type = type;
			this.disType = disType;
			this.additional = additional;
			this.isPrecise = isPrecise;
			this.itemType = (TCComponentItemType) session.getTypeComponent(type);
			if (this.itemType == null) {
				throw new Exception(String.format(REG.getString("typenotfound.ERROR1"), type));
			}
		}

		@Override
		public String toString() {
			return "  " + disType;
		}
	}

	public NewMeopDialogController(AbstractAIFApplication app) {
		super();
		session = (TCSession) app.getSession();
	}

	@Override
	public boolean init() throws Exception {
		this.dialog = (NewMeopDialog) aifDialog;
		InterfaceAIFComponent comp = app.getTargetComponent();
		System.out.println("Select: " + comp);
		if (comp != null) {
			if (comp instanceof TCComponentBOMLine) {
				this.targetLine = (TCComponentBOMLine) comp;
				TCComponentItemRevision rev = this.targetLine.getItemRevision();
				System.out.println(">> " + rev.getType());
				if (ProcessUtil.isMEProcess(session, rev.getItem().getType())) {
					// if (rev instanceof TCComponentMEProcessRevision) {
					this.targetRev = rev;
				}
			}
		}
		if (targetRev == null) {
			throw new TCException(REG.getString("selectprocessrev.ERROR"));
		}
		{
			String prefName = PREF_PREFIX + this.targetRev.getType();
			String[] prefVals = KUtil.getPrefVals(session, prefName);
			int len = KUtil.getLen(prefVals);
			for (int i = 0; i < len; i++) {
				String type = prefVals[i];
				boolean isPrecise = type.startsWith("#");
				if (isPrecise) {
					type = type.substring(1);
				}
				String addition = "";
				int ind = type.indexOf('=');
				if (ind > 0) {
					addition = type.substring(ind + 1).replace("\\n", "\n");
					type = type.substring(0, ind);
				}
				String disType = KUtil.getTypeName(session, type);
				if (KUtil.isEmpty(disType)) {
					System.out.println("Error Config: " + prefVals[i]);
					continue;
				}
				this.meopTypes.add(new MEOPType(session, type, disType, addition, isPrecise));
			}
			if (this.meopTypes.size() == 0) {
				throw new TCException(String.format(REG.getString("prefnotconfiged.ERROR1"), prefName));
			}
		}
		{
			String[] prefVals = KUtil.getPrefVals(session, PREF_PROPS);
			int len = KUtil.getLen(prefVals);
			for (int i = 0; i < len; i++) {
				String pref = prefVals[i];
				if (pref.length() == 1 && Character.isDigit(pref.charAt(0))) {
					int col = pref.charAt(0) - '0';
					if (col > 0) {
						System.out.println("Reset Proc Col: " + col);
						this.propCols = col;
					}
					continue;
				}
				PrefComponent prefComp = new PrefComponent(pref, "");
				if (prefComp.init(session, targetRev, prefComponents)) {
					prefComponents.add(prefComp);
				} else {
					System.out.println("Error Config: " + pref);
				}
			}
			
			
			if (prefComponents.size() == 0) {
				throw new TCException(String.format(REG.getString("prefnotconfiged.ERROR1"), PREF_PROPS));
			}
			
			for (int i = 0; i < prefComponents.size(); i++) {
			    PrefComponent prefParent = prefComponents.get(i);
			    if (prefParent.isLovParent) {
			        for (int j = 0; j < prefComponents.size(); j++) {
			            PrefComponent prefChild = prefComponents.get(j);
			            if (prefParent.lovName.equals(prefChild.lovName) && prefChild.isLovChild) {
			                prefParent.comboBox.addActionListener(new ActionListener() {
			                    @Override
			                    public void actionPerformed(ActionEvent e) {
			                        String selectedProvince = (String) prefParent.bigJtf.getText();
			                        if (selectedProvince != null) {
			                            List<String> cities = prefParent.listLov.get(selectedProvince);
			                            
			                            // 清空子级控件和数据
			                            prefChild.comboBox.removeAllItems();
			                            prefChild.opHashMap.clear();
			                            prefChild.lovDisRealMap.clear();
			                            prefChild.list.clear();

			                            if (cities != null && !cities.isEmpty()) {
			                                for (String city : cities) {
			                                    OptionItem optionItem = new OptionItem(city, "");
			                                    prefChild.comboBox.addItem(optionItem);
			                                    prefChild.opHashMap.put(city, optionItem);
			                                    prefChild.lovDisRealMap.put(city, city);
			                                    prefChild.list.add(city);
			                                }
			                                //  关键：不自动选中任何项
			                                prefChild.comboBox.setSelectedIndex(-1);
			                            } else {
			                                // 没有子项时也确保无选中
			                                prefChild.comboBox.setSelectedIndex(-1);
			                            }
			                        } else {
			                            prefChild.comboBox.removeAllItems();
			                            prefChild.comboBox.setSelectedIndex(-1); // 确保无选中
			                        }
			                    }
			                });
			            }
			        }
			    }
			}
			
			
			
			
			
			

			String descPropName = REG.getString("shortdesc.PROPNAME");
			this.shortDescPrefComp = new PrefComponent(descPropName, "");
			if (!shortDescPrefComp.init(session, targetRev, prefComponents)) {
				this.shortDescPrefComp = null;
			}
		}

		return true;
	}

	public void assignId() throws Exception {
		MEOPType type = dialog.l_type.getSelectedValue();
		if (type == null) {
			throw new TCException(REG.getString("selectMeopType.INFO"));
		}
		TCComponentItemType itemType = type.itemType;
		String newId = itemType.getNewID();
		System.out.println("New ID: " + type.type + " -> " + newId);
		dialog.setAssignId(newId);
	}

	public int getMeopNo(TCComponentBOMLine line) throws Exception {
		// TCComponentItemRevision rev = line.getItemRevision();
		// if (rev == null) {
		// throw new TCException("Get Revision Failed: " + line);
		// }
		// TCComponent form = rev.getRelatedComponent("IMAN_master_form_rev");
		// if (form == null) {
		// throw new TCException("Get RevisionMaster Failed: " + rev);
		// }
		// form.refresh();
		// String seqStr = form.getStringProperty("ac5_OperationNumber");
		String seqStr = line.getProperty("bl_sequence_no");
		System.out.println("Op Number: " + line + " -> " + seqStr);
		int seq = 0;
		if (!KUtil.isEmpty(seqStr)) {
			try {
				seq = Integer.parseInt(seqStr);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return seq;
	}

	@SuppressWarnings("deprecation")
	public void setMeopNo(TCComponentBOMLine line, int meopNo) throws Exception {
		System.out.println("Set Op Number: " + line + " -> " + meopNo);
		line.lock();
		try {
			line.setProperty("bl_sequence_no", meopNo + "");
			line.save();
		} finally {
			line.unlock();
		}
		targetLine.refresh();
		// if(meopNo<0) {
		// return;
		// }
		// TCComponentItemRevision rev = line.getItemRevision();
		// if (rev == null) {
		// throw new TCException("Get Revision Failed: " + line);
		// }
		// TCComponent form = rev.getRelatedComponent("IMAN_master_form_rev");
		// if (form == null) {
		// throw new TCException("Get RevisionMaster Failed: " + rev);
		// }
		// form.refresh();
		// form.lock();
		// try {
		// form.setStringProperty("ac5_OperationNumber", meopNo + "");
		// form.save();
		// form.refresh();
		// } finally {
		// form.unlock();
		// }
	}

	public void assignMeopNo() throws Exception {
		targetLine.refresh();
		AIFComponentContext[] cc = targetLine.getChildren();
		int maxSeq = 0;
		int len = KUtil.getLen(cc);
		for (int i = 0; i < len; i++) {
			TCComponentBOMLine cLine = (TCComponentBOMLine) cc[i].getComponent();
			int seq = getMeopNo(cLine);
			maxSeq = Math.max(seq, maxSeq);
		}
		maxSeq += 10;
		System.out.println("New Sequence: " + maxSeq);
		dialog.setMeopNo("" + maxSeq);
	}

	public void insertMeopNo() throws Exception {
		Map<String, String> propData = new MeopNoDialog(dialog, true, new MeopNoDialogController(app, targetLine)).getMeopInfo();
		System.out.println("Prop Info: " + propData);
		if (propData == null || propData.size() == 0) {
			return;
		}
		for (PrefComponent comp : prefComponents) {
			String key = comp.getPropConfig();
			if (propData.containsKey(key)) {
				String value = propData.get(key);
				System.out.println(String.format("set [%s]=[%s]", key, value));
				comp.setValue(value);
			}
		}
	}

	public void doCreate() throws Exception {
		MEOPType typeComp = dialog.l_type.getSelectedValue();
		if (typeComp == null) {
			throw new TCException(REG.getString("selectMeopType.INFO"));
		}
		TCComponentItemType itemType = typeComp.itemType;
		// Check Require
//		if (!checkRequire()) {
//			return;
//		}
		
		
		
		
		
		
		String type = itemType.getName();
		System.out.println("Select Type: " + type);
		if (KUtil.isEmpty(type)) {
			throw new TCException(REG.getString("selectType.INFO"));
		}
		if (!checkRequire()) {
			return;
		}
		
		String checkCombox = checkCombox();
		
		
System.out.println("checkCombox==="+checkCombox);
		
		if (!checkCombox.equals("")) {
			
			throw new Exception(checkCombox);
		}
		
		
		
		TCComponentItemRevisionType revType = itemType.getItemRevisionType();
		String revTypeName = revType.getName();
		String itemMasterTypeName = type + " Master";
		String revMasterTypeName = revTypeName + " Master";
		if (session.getTypeComponent(itemMasterTypeName) == null) {
			itemMasterTypeName = type + "Master";
		}
		if (session.getTypeComponent(revMasterTypeName) == null) {
			revMasterTypeName = revTypeName + "Master";
		}
		TCComponentType revMasterType = session.getTypeComponent(revMasterTypeName);
		TCComponentType itemMasterType = session.getTypeComponent(itemMasterTypeName);
		System.out.println("Revision Type: " + type);
		System.out.println("Item Master Type: " + itemMasterTypeName);
		System.out.println("Revision Master Type: " + revMasterTypeName);
		Map<String, String> revPropMap = new HashMap<>();
		Map<String, String> revMasterPropMap = new HashMap<>();
		Map<String, String> itemPropMap = new HashMap<>();
		Map<String, String> itemMasterPropMap = new HashMap<>();
		Map<String, Double> revPropMapD = new HashMap<>();
		Map<String, Double> revMasterPropMapD = new HashMap<>();
		Map<String, Double> itemPropMapD = new HashMap<>();
		Map<String, Double> itemMasterPropMapD = new HashMap<>();
		Map<String, String> bomLinePropMap = new HashMap<>();
		for (PrefComponent prefComponent : this.prefComponents) {
			// KUtil.initPropMap(prefComponent.propConfig, prefComponent.getValue(),
			// itemPropMap, itemMasterPropMap, revPropMap, revMasterPropMap,
			// bomLinePropMap);
			String propConfig = prefComponent.propConfig;
			String value = prefComponent.getValue();
			if (KUtil.isEmpty(propConfig)) {
				continue;
			}
			String propFrom = null, propName = null;
			String[] split = propConfig.split("\\.");
			if (KUtil.getLen(split) == 2) {
				propFrom = split[0].trim().toUpperCase();
				propName = split[1].trim();
			}
			if (KUtil.isEmpty(propFrom) || KUtil.isEmpty(propName)) {
				continue;
			}
			TCComponentType targetType = null;
			Map<String, String> target;
			Map<String, Double> targetD = null;
			if ("ITEM".equals(propFrom)) {
				target = itemPropMap;
				targetD = itemPropMapD;
				targetType = itemType;
				// System.out.println(">> ITEM PROP: " + propName + " = " + value);
			} else if ("REV".equals(propFrom)) {
				// System.out.println(">> REV PROP: " + propName + " = " + value);
				target = revPropMap;
				targetD = revPropMapD;
				targetType = revType;
			} else if ("ITEMMASTER".equals(propFrom)) {
				// System.out.println(">> ITEMMASTER PROP: " + propName + " = " + value);
				target = itemMasterPropMap;
				targetD = itemMasterPropMapD;
				targetType = itemMasterType;
			} else if ("REVMASTER".equals(propFrom)) {
				// System.out.println(">> REVMASTER PROP: " + propName + " = " + value);
				target = revMasterPropMap;
				targetD = revMasterPropMapD;
				targetType = revMasterType;
			} else if ("BOMLINE".equals(propFrom)) {
				System.out.println(">> BOMLINE PROP: " + propName + " = " + value);
				target = bomLinePropMap;
			} else {
				throw new TCException(String.format(KUtil.REG.getString("proplocationnotdefined.ERROR1"), propFrom));
			}
			if (target == null && targetD == null) {
				return;
			}
			if (targetType != null) {
				TCPropertyDescriptor desc = targetType.getPropDesc(propName);
				// System.out.println(propName+" - "+desc.getType());
				if (desc != null && desc.getType() == TCPropertyDescriptor.SERVER_PROP_double) {
					if (!KUtil.isEmpty(value)) {
						double d = Double.parseDouble(value);
						targetD.put(propName, d);
					}
					continue;
				}
			}
			target.put(propName, value);
		}
		String bl_sequence_no = bomLinePropMap.get("bl_sequence_no");
		int n = 0;
		for(AIFComponentContext l : targetLine.getChildren()) {
			TCComponentBOMLine line = (TCComponentBOMLine) l.getComponent();
			if(line.getProperty("bl_sequence_no").equals(bl_sequence_no))
				n++;
		}
		if(n >= 3) {
			throw new TCException(REG.getString("sequence.ERROR"));
		}
		String propType = "ac5_Type";
		// propType = "object_desc"; // 
		// revMasterPropMap.remove("nhl8_ProShortDescss"); //TODO
		if (revMasterPropMap.containsKey(propType)) {
			String ac5Type = revMasterPropMap.get(propType);
			System.out.println(propType + ": " + ac5Type);
			if (!KUtil.isEmpty(ac5Type)) {
				revPropMap.put("item_revision_id", ac5Type + "00");
			}
		}
		CreateInput revMasterInput = new CreateInput();
		revMasterInput.boName = revMasterTypeName;
		revMasterInput.stringProps = revMasterPropMap;
		revMasterInput.doubleProps = revMasterPropMapD;
		CreateInput itemMasterInput = new CreateInput();
		itemMasterInput.boName = itemMasterTypeName;
		itemMasterInput.stringProps = itemMasterPropMap;
		itemMasterInput.doubleProps = itemMasterPropMapD;
		CreateInput revInput = new CreateInput();
		revInput.boName = revTypeName;
		revInput.stringProps = revPropMap;
		revInput.doubleProps = revPropMapD;
		Map<String, CreateInput[]> revMasterInfoMap = new HashMap<>();
		revMasterInfoMap.put("IMAN_master_form_rev", new CreateInput[] { revMasterInput });
		revInput.compoundCreateInput = revMasterInfoMap;
		// create rev
		CreateInput itemInput = new CreateInput();
		itemInput.boName = type;
		itemInput.stringProps = itemPropMap;
		itemInput.doubleProps = itemPropMapD;
		Map<String, CreateInput[]> revInfoMap = new HashMap<>();
		revInfoMap.put("revision", new CreateInput[] { revInput });
		revInfoMap.put("IMAN_master_form", new CreateInput[] { itemMasterInput });
		itemInput.compoundCreateInput = revInfoMap;
		// create info
		CreateIn cI = new CreateIn();
		cI.clientId = "CreateItem";
		cI.data = itemInput;
		// service
		DataManagementService service = DataManagementService.getService(session);
		// create
		CreateResponse resp = service.createObjects(new CreateIn[] { cI });
		SoaUtil.checkPartialErrors(resp.serviceData);
		CreateOut[] cOs = resp.output;
		TCComponentItem newItem = null;
		if (cOs.length > 0) {
			for (TCComponent s : cOs[0].objects) {
				if (s instanceof TCComponentItem) {
					newItem = (TCComponentItem) s;
				}
			}
		}
		System.out.println("New Item: " + newItem);
		if (newItem == null) {
			throw new TCException(REG.getString("createprocess.ERROR"));
		}
		newItem.refresh();
		TCComponentItemRevision newRev = newItem.getLatestItemRevision();
		System.out.println("New Rev: " + newRev);
		TCComponentBOMLine newLine = this.targetLine.add(newItem, newRev, null, false);
		if (bomLinePropMap.size() > 0) {
			System.out.println("Set Bom Property: " + bomLinePropMap);
			newLine.setProperties(bomLinePropMap);
			newLine.refresh();
		}
		targetLine.setPrecision(true);
		TCComponentItemType t = (TCComponentItemType) session.getTypeService().getTypeComponent("Item");
		TCComponentItem item1 = t.findItems("000001")[0];
		TCComponentBOMWindowType bomWinType = (TCComponentBOMWindowType) session.getTypeComponent("BOMWindow");
		TCComponentBOMWindow window = bomWinType.create(null);
		TCComponentBOMLine newBom = window.setWindowTopLine(null, newRev, null, null);
		TCComponentBOMLine newnewLine = newBom.add(item1, item1.getLatestItemRevision(), null, false);
		window.save();
		newnewLine.cut();
		window.save();
		window.close();
		if(workcenterCmd != null) {
			System.out.println("Add Workcenter: " + workcenterCmd.getSelected());
			workcenterCmd.doAssign(newLine);
		}
		session.queueOperation(new AbstractAIFOperation() {
			@Override
			public void executeOperation() throws Exception {
				try {
					System.out.println("Switch to Precise: " + typeComp.isPrecise);
					newLine.setPrecision(typeComp.isPrecise);
				} catch (Exception e) {
					e.printStackTrace();
				}
				targetLine.refresh();
			}
		});
		dialog.setAssignId(null);
		dialog.setMeopNo(null);
		for (PrefComponent c : this.prefComponents) {
			c.setValue(null);
		}
		if (this.shortDescPrefComp != null) {
			this.shortDescPrefComp.setValue(null);
		}
		clearWorkCenter();
	}

	private boolean checkRequire() {
		List<String> requireTitles = new ArrayList<String>();
		for (PrefComponent prefComponent : this.prefComponents) {
			if (!prefComponent.checkRequire()) {
				requireTitles.add(prefComponent.title.replace(" ", "").replace(":", "").replace(REG.getString("CN_SYMBEL4"), "").replace(REG.getString("CN_SYMBEL5"), ""));
			}
		}
//		if (workcenterCmd!=null && this.workcenterCmd.getSelected() == null) {
//			requireTitles.add(REG.getString("workcenter"));
//		}
		if (requireTitles.size() > 0) {
			MessageBox.post(dialog, String.format(REG.getString("requireprop.INFO1"), requireTitles.toString()), "", MessageBox.WARNING);
			return false;
		}
		return true;
	}

	public AbstractAIFApplication getApp() {
		return app;
	}

	public void chooseWorkCenter() throws Exception {
		if (this.workcenterCmd == null) {
			MEOPType typeComp = dialog.l_type.getSelectedValue();
			if (typeComp == null) {
				throw new TCException(REG.getString("selectMeopType.INFO"));
			}
			TCComponentItemType itemType = typeComp.itemType;
			TCComponentItem item = new TCComponentItem() {
				@Override
				public TCComponentItemType getTypeComponent() {
					return itemType;
				}

				@Override
				public TCSession getSession() {
					return session;
				}

				@Override
				public String[] getClassNameHierarchy() throws TCException {
					return itemType.getClassNameHierarchy();
				}
			};
			System.out.println("TypeName: " + itemType);
			this.workcenterCmd = new KAssignResourceCommand(KUtil.getPrefVal(session, NewMeopDialogController.PREF_WORKCENTER_CLS_ID), item);
		}
		this.workcenterCmd.executeModal();
		TCComponent comp = workcenterCmd.getSelected();
		if(dialog.tf_WorkCenter != null)
			dialog.tf_WorkCenter.setText(comp == null ? "" : comp.toString());
	}

	public void clearWorkCenter() {
		workcenterCmd = null;
		if(dialog.tf_WorkCenter != null)
			dialog.tf_WorkCenter.setText("");
	}

	private String checkCombox() {
		List<String> requireTitles = new ArrayList<String>();
		for (PrefComponent prefComponent : prefComponents) {
			if (!prefComponent.checkCombox()) {
				requireTitles.add(prefComponent.title+"请选择下拉值!");
			}
		}
		if (requireTitles.size() > 0) {
			//MessageBox.post(dialog, String.format(REG.getString("requireprop.INFO1"), requireTitles.toString()), "", MessageBox.WARNING);
			return requireTitles.toString();
		}
		return "";
	}
}
