package nc.ui.arap.view;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.JComponent;

import nc.bs.arap.bill.ArapBillPubUtil;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Log;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.uap.bd.notetype.INotetypeConst;
import nc.itf.arap.fieldmap.IBillFieldGet;
import nc.itf.cmp.busi.ISettleinfoCarrier;
import nc.md.data.access.NCObject;
import nc.md.model.MetaDataException;
import nc.md.persist.framework.MDPersistenceService;
import nc.ui.arap.bill.ArapBillUIUtil;
import nc.ui.arap.bill.LinkHyperListener;
import nc.ui.arap.event.TabAddEventType;
import nc.ui.arap.model.ArapBillManageModel;
import nc.ui.arap.scale.ArapBillCardPanelScaleProcessor;
import nc.ui.arap.scale.FIBillCardPanelScaleProcessor;
import nc.ui.arap.viewhandler.ViewHandlerUIUtil;
import nc.ui.arap.viewhandler.card.LoadBillCardTemplate;
import nc.ui.pub.beans.UIComboBox;
import nc.ui.pub.beans.UIRefPane;
import nc.ui.pub.beans.constenum.DefaultConstEnum;
import nc.ui.pub.beans.constenum.IConstEnum;
import nc.ui.pub.bill.BillData;
import nc.ui.pub.bill.BillItem;
import nc.ui.pub.bill.IBillItem;
import nc.ui.pub.bill.IGetBillRelationItemValue;
import nc.ui.pub.linkoperate.ILinkType;
import nc.ui.pubapp.uif2app.event.AppUiStateChangeEvent;
import nc.ui.pubapp.uif2app.mediator.mutiltrans.NodekeyEvent;
import nc.ui.uif2.AppEvent;
import nc.ui.uif2.components.widget.IWidgetBillSourceEditor;
import nc.ui.uif2.editor.TemplateContainer;
import nc.vo.arap.basebill.BaseAggVO;
import nc.vo.arap.basebill.BaseBillVO;
import nc.vo.arap.basebill.BaseItemVO;
import nc.vo.arap.bill.util.BillEventHandlerUtil;
import nc.vo.arap.pub.ArapBillTypeInfo;
import nc.vo.arap.pub.BillEnumCollection;
import nc.vo.arap.pub.IArapBilltypeInfo;
import nc.vo.arap.pub.BillEnumCollection.ObjType;
import nc.vo.bd.cust.CustomerVO;
import nc.vo.bd.supplier.SupplierVO;
import nc.vo.cmp.BusiInfo;
import nc.vo.cmp.settlement.SettlementAggVO;
import nc.vo.fipub.exception.ExceptionHandler;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.BusinessRuntimeException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.pub.lang.UFBoolean;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

@SuppressWarnings("restriction")
public class ArapBillCardForm extends nc.ui.pubapp.uif2app.view.MutilTransBillForm implements ICurrtypeGetter, 
		ISettleinfoCarrier, IWidgetBillSourceEditor {

	private static final long serialVersionUID = -4066776166301370901L;
	private FIBillCardPanelScaleProcessor arapBillCardPanelScaleProcessor;

	private Collection<String> clearHyperlink;

	private IArapBilltypeInfo arapBilltypeInfo;
	
	private String pk_org_event; //记录发送了组织变化事件，没有做处理的组织pk

	public String getPk_org_event() {
		return pk_org_event;
	}

	public void setPk_org_event(String pkOrgEvent) {
		pk_org_event = pkOrgEvent;
	}

	private void loadSpecialData(BaseAggVO bill) {

		if (bill != null && bill.getItems() != null) {
			int row = 0;
			
			for (BaseItemVO item : bill.getItems()) {
				if (item != null) {
					// 加载票据号
					loadBodyCheckType(bill.getHeadVO(), row, item);
				}
				row++;
			}
//			// 加载散户银行账户
//			List<Integer> freecustList  = isFreecust(bill);
//			if(freecustList != null && freecustList.size() > 0){
//				loadBodyFreecustAccount(bill,freecustList);
//			}
			// 处理表体摘要
			ArapBillUIUtil.loadHeadScomment(bill,getBillCardPanel().getBodyItem(IBillFieldGet.SCOMMENT));
			// 摘要问题 这段暂时不需要 
			int i=0;
			for(CircularlyAccessibleValueObject item:bill.getChildrenVO()){
				String key=IBillFieldGet.SCOMMENT;
				Object attributeValue = item.getAttributeValue(key);
				if(attributeValue!=null){
					getBillCardPanel().setBodyValueAt(attributeValue, i, key);
				}
				i++;
			}
			
			try{
				if (getBillCardPanel().getHeadItem(IBillFieldGet.SUBJCODE) != null
						&& getBillCardPanel().getHeadItem(IBillFieldGet.SUBJCODE).getComponent()!=null
						&& ((UIRefPane) getBillCardPanel().getHeadItem(IBillFieldGet.SUBJCODE).getComponent()).getRefModel() != null
						&& ((UIRefPane) getBillCardPanel().getHeadItem(IBillFieldGet.SUBJCODE).getComponent()).getRefModel().getPara() == null
						&& StringUtils.isNotEmpty(bill.getHeadVO().getSubjcode())) {
					new ArapRefUtil().setSubjcodeModelParam(getBillCardPanel().getHeadItem(IBillFieldGet.SUBJCODE), bill.getHeadVO().getPk_org());
					getBillCardPanel().getHeadItem(IBillFieldGet.SUBJCODE).setValue(bill.getHeadVO().getSubjcode());
				}

			}catch(Exception e){
			}
			
			// 付款单在新增时删除往来对象，现在编辑后往来对象添加客户
			boolean fk = IBillFieldGet.FK.equals(bill.getHeadVO().getBillclass())
					&& BillEnumCollection.ObjType.CUSTOMER.VALUE.equals(bill.getHeadVO().getObjtype());

			boolean sk = IBillFieldGet.SK.equals(bill.getHeadVO().getBillclass())
			&& BillEnumCollection.ObjType.SUPPLIER.VALUE.equals(bill.getHeadVO().getObjtype());
			
			if (fk || sk) {
				List<Object> needRemovedValues = Arrays.asList(new Object[] { fk ? ObjType.CUSTOMER.VALUE : ObjType.SUPPLIER.VALUE });
				String billtype_enumName = (fk ? IBillFieldGet.F3 : IBillFieldGet.F2 )+ "_" + IBillFieldGet.OBJTYPE;
				
				ViewHandlerUIUtil.tryAddComboBoxValue((UIComboBox) getBillCardPanel().getHeadItem(IBillFieldGet.OBJTYPE)
						.getComponent(), needRemovedValues, billtype_enumName);
			}
		}
	}

	@Override
	protected void setDefaultValue() {
		// if (this.getDefValueItf() != null) {
		// this.getBillCardPanel().setBillValueVO(this.getDefValueItf().getDefaultVO());
		// }
	}

	private void loadBodyCheckType(BaseBillVO headvo, int row, BaseItemVO item) {
		String checktype = item.getChecktype();
		if (StringUtils.isNotEmpty(checktype)) {
			Integer noteclass = BillEventHandlerUtil.getNoteClassByPK(checktype);
			BillItem checkItem = getBillCardPanel().getBodyItem(IBillFieldGet.CHECKNO);
			if (checkItem == null){
				return ;
			}
			UIRefPane ref = ((UIRefPane) checkItem.getComponent());

			if (noteclass == INotetypeConst.NOTETYPE_CLASS_BUSIPO) {
				ArapBillUIUtil.setRefTypeByReflectMethod(checkItem,IBillItem.UFREF);
				ref.setAutoCheck(true);
			} else {
				ArapBillUIUtil.setRefTypeByReflectMethod(checkItem,IBillItem.STRING);
				ref.setAutoCheck(false);
			}
			
			getBillCardPanel().setBodyValueAt(item.getCheckno(), row, IBillFieldGet.CHECKNO);
			getBillCardPanel().getBillModel().loadLoadRelationItemValue(row, IBillFieldGet.CHECKNO);
		}
	}

	@SuppressWarnings("unused")
	private List<Integer> isFreecust(BaseAggVO bill) {
		List<Integer> freecustList = new ArrayList<Integer>();
		Map<String, UFBoolean> freecust = new HashMap<String, UFBoolean>();
		if (bill.getItems() == null || bill.getItems().length <= 0) {
			return freecustList;
		}
		String pk_billtype = bill.getHeadVO().getPk_billtype();
		BaseItemVO[] itemVOs = bill.getItems();
		try {
			if (pk_billtype.equals(IBillFieldGet.F3) || pk_billtype.equals(IBillFieldGet.F1)) {
				Set<String> supplier = new HashSet<String>();
				for (int i = 0; i < itemVOs.length; i++) {
					supplier.add(itemVOs[i].getSupplier());
				}
				NCObject[] supplierVOs = MDPersistenceService.lookupPersistenceQueryService().queryBillOfNCObjectByPKs(SupplierVO.class, supplier.toArray(new String[0]),
						new String[] { SupplierVO.PK_SUPPLIER, SupplierVO.ISFREECUST }, true);
				for (int i = 0; i < supplierVOs.length; i++) {
					if (supplierVOs[i] != null) {
						UFBoolean isFreeCust = ((SupplierVO) supplierVOs[i].getContainmentObject()).getIsfreecust();
						String pkSupplier = ((SupplierVO) supplierVOs[i].getContainmentObject()).getPk_supplier();
						freecust.put(pkSupplier, isFreeCust);
					}
				}
				for (int i = 0; i < itemVOs.length; i++) {
					UFBoolean isFreeCust = freecust.get(itemVOs[i].getSupplier());
					if (isFreeCust != null && isFreeCust.booleanValue()) {
						freecustList.add(i);
					}
				}
				return freecustList;
			} else if (pk_billtype.equals(IBillFieldGet.F0) || pk_billtype.equals(IBillFieldGet.F2)) {
				Set<String> customer = new HashSet<String>();
				for (int i = 0; i < itemVOs.length; i++) {
					customer.add(itemVOs[i].getCustomer());
				}
				NCObject[] customerVOs = MDPersistenceService.lookupPersistenceQueryService().queryBillOfNCObjectByPKs(CustomerVO.class, customer.toArray(new String[0]),
						new String[] { CustomerVO.PK_CUSTOMER, CustomerVO.ISFREECUST }, true);
				for (int i = 0; i < customerVOs.length; i++) {
					if (customerVOs[i] != null) {
						UFBoolean isFreeCust = ((CustomerVO) customerVOs[i].getContainmentObject()).getIsfreecust();
						String pkCustomer = ((CustomerVO) customerVOs[i].getContainmentObject()).getPk_customer();
						freecust.put(pkCustomer, isFreeCust);
					}
				}
				for (int i = 0; i < itemVOs.length; i++) {
					UFBoolean isFreeCust = freecust.get(itemVOs[i].getCustomer());
					if (isFreeCust != null && isFreeCust.booleanValue()) {
						freecustList.add(i);
					}
				}
				return freecustList;
			}
		} catch (MetaDataException e) {
			ExceptionHandler.consume(e);
		}
		return freecustList;

	}
	
//	private void loadBodyFreecustAccount(BaseAggVO bill, List<Integer> freecustList) {
//		String pk_billtype = bill.getHeadVO().getPk_billtype();
//		String account = "";
//		if (IBillFieldGet.F3.equals(pk_billtype) || IBillFieldGet.F1.equals(pk_billtype)) {
//			account = IBillFieldGet.RECACCOUNT;
//		}else if(IBillFieldGet.F2.equals(pk_billtype) || IBillFieldGet.F0.equals(pk_billtype)){
//			account = IBillFieldGet.PAYACCOUNT;
//		}
//		
//		BillItem accountItem = getBillCardPanel().getBodyItem(account);
//		if (accountItem == null){
//			return ;
//		}
//		UIRefPane ref = ((UIRefPane) accountItem.getComponent());
//		ArapBillUIUtil.setRefTypeByReflectMethod(accountItem, IBillItem.UFREF);
//		ref.setAutoCheck(false);
//		
//		//如果是散户，把散户银行账号设到对应的银行账户字段  
//		BaseItemVO[] itemVOs = bill.getItems();
//		for(int i = 0; i < freecustList.size(); i++){
//			int row = freecustList.get(i);
//			getBillCardPanel().setBodyValueAt(itemVOs[row].getAttributeValue(account), row, account);
//			getBillCardPanel().getBillModel().loadLoadRelationItemValue(row, account);
//		}
//	}
	
	@Override
	public void setValue(Object object) { 
		if(object == null){
			return ;
		}
		reloadBillTemplate(object);
		
		ArapBillUIUtil.refreshChildVO2HeadVO((AggregatedValueObject) object);
		String pk_org  = (String)((AggregatedValueObject) object).getParentVO().getAttributeValue(IBillFieldGet.PK_ORG);
		
		if(pk_org.equals(getPk_org_event())){
			getModel().getContext().setPk_org(pk_org);
			getModel().fireEvent(new nc.ui.pubapp.uif2app.event.OrgChangedEvent(null, pk_org));
		}
		setPk_org_event(null);
		loadCurrtype(object);
		dealSpecialItem();
		resetHeadDigit();
		super.setValue(object);
		// 如果这个地方不设置一下表头精度 第一次 列表切换卡片 组织本币金额精度会有问题
		loadSpecialData((BaseAggVO) object);
		resetHeadDigit();
	}

	private void dealSpecialItem() {
		BillItem item = this.getBillCardPanel().getBodyItem("facard");
		
		if(item!=null){
			LoadBillCardTemplate.setFaCard(item);
		}
	}
	
	// 重新加载模板
	private void reloadBillTemplate(Object object) {
		String oldNodeKey = this.getNodekey();
		JComponent entranceUI = this.getModel().getContext().getEntranceUI();
		resetMenuAction(entranceUI);
		String newNodekey = object == null ? null : ((BaseAggVO) object).getHeadVO().getPk_tradetype();

		if (newNodekey != null && oldNodeKey != null && !newNodekey.equals(oldNodeKey)) {
			this.getModel().fireEvent(new NodekeyEvent(oldNodeKey, newNodekey));
		}
	}

	public static void resetMenuAction(JComponent entranceUI) {
		if (entranceUI instanceof ArapToftPanelBase) {
			ArapToftPanelBase ui = (ArapToftPanelBase) entranceUI;
			if (ui.getLinkType() != ILinkType.NONLINK_TYPE) {
				ui.resetMenuAction(ui.getLinkType());
			}
		}
	}

	private void loadCurrtype(Object object) {
		if (object instanceof BaseAggVO) {
			BaseItemVO[] items = ((BaseAggVO) object).getItems();
				for (BaseItemVO item : items) {
					putCurrtype(item.getPrimaryKey(), item.getPk_currtype());
				}	
			this.headCurrtype = ((BaseAggVO) object).getHeadVO().getPk_currtype();
			this.getBillCardPanel().getHeadItem(IBillFieldGet.PK_CURRTYPE).setValue(((BaseAggVO) object).getHeadVO().getPk_currtype());
		}
	}

	public void resetHeadDigit() {
		if (getBillCardPanel() == null) {
			return;
		}
		getArapBillCardPanelScaleProcessor().resetHeadExchangeRateDigit(getBillCardPanel());
		getArapBillCardPanelScaleProcessor().resetHeadCurrencyDigit(getBillCardPanel());
		getArapBillCardPanelScaleProcessor().resetHeadGlobalDigit(getBillCardPanel());
		getArapBillCardPanelScaleProcessor().resetHeadGorupDigit(getBillCardPanel());
		getArapBillCardPanelScaleProcessor().resetHeadLocalDigit(getBillCardPanel());
	}

	@Override
	public Object getValue() {
		return super.getValue();
	}

	@Override
	public void handleEvent(AppEvent event) {
		
		super.handleEvent(event);
		
		if(this.getModel()==null || !(this.getModel() instanceof ArapBillManageModel)){ //兼容补差界面的模型初始化事件
			return;
		}
		// 保存结算信息
		if (getBillCardPanel() == null)
			return;
		if (event.getClass().equals(AppUiStateChangeEvent.class)) {
			if (!((ArapBillManageModel) this.getModel()).getIsLink()) {
				resetHeadDigit();
			}
		} else if (event.getType().equals(TabAddEventType.REFRESH_BILL)) {
		} else if (event.getType().equals(TabAddEventType.BROW_BUSI_BILL)) {
			BusiInfo info = (BusiInfo) event.getContextObject();
			BilltypeVO billType = PfDataCache.getBillType(info.getBill_type());
			String parentbilltype = billType == null ? "" : billType.getParentbilltype();
			if (ArapBillPubUtil.isArapBilltype(info.getBill_type()) || ArapBillPubUtil.isArapBilltype(parentbilltype)) {
				setArapBilltypeInfo(ArapBillTypeInfo.getInstance(parentbilltype));
				try {
					BaseAggVO[] vos = NCLocator.getInstance().lookup(getArapBilltypeInfo().getBillQueryService()).findBillByPrimaryKey(new String[] {
						info.getPk_bill()
					});
					ArapBillUIUtil.refreshChildVO2HeadVO(vos);
					if (ArrayUtils.isEmpty(vos)) {
						throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006v61008_0", "02006v61008-0250")/* @res "没有业务单据, 业务单据id" */+ info.getPk_bill());
					}
					setValue(ArrayUtils.isEmpty(vos) ? null : vos[0]);
				} catch (BusinessException e) {
					ExceptionHandler.consume(e);
				}
			}
		}

	}

	public IArapBilltypeInfo getArapBilltypeInfo() {
		return arapBilltypeInfo;
	}

	public void setArapBilltypeInfo(IArapBilltypeInfo arapBilltypeInfo) {
		this.arapBilltypeInfo = arapBilltypeInfo;
	}

	@Override
	public boolean canBeHidden() {
		return true;
	}

	public Collection<String> getClearHyperlink() {
		return this.clearHyperlink;
	}

	@Override
	public void initUI() {
		super.initUI();
		BillItem bodyItem = this.getBillCardPanel().getBodyItem(IBillFieldGet.SCOMMENT);
		bodyItem.setGetBillRelationItemValue(new IGetBillRelationItemValue() {
			@Override
			public IConstEnum[] getRelationItemValue(ArrayList<IConstEnum> ies, String[] id) {
				DefaultConstEnum[] ss = new DefaultConstEnum[1];
				Object[] s = new Object[id.length];
				for (int i = 0; i < s.length; i++) {
					s[i] = id[i];
				}
				ss[0] = new DefaultConstEnum(s, IBillFieldGet.SCOMMENT);
				return ss;
			}
		});
		//2023/10/12 YY 添加超链接监听
		String tableName = bodyItem.getTableName();
		if("应付单行".equals(tableName)) {
			if(this.getBillCardPanel().getBodyItem("def41") != null){
				this.getBillCardPanel().getBodyItem("def41").addBillItemHyperlinkListener(new LinkHyperListener(this.getBillCardPanel()));
			}else if(this.getBillCardPanel().getBodyItem("def22") != null){
				this.getBillCardPanel().getBodyItem("def22").addBillItemHyperlinkListener(new LinkHyperListener(this.getBillCardPanel()));
			}
		}
		if("应收单行".equals(tableName)) {
			if(this.getBillCardPanel().getBodyItem("def22") != null){
				this.getBillCardPanel().getBodyItem("def22").addBillItemHyperlinkListener(new LinkHyperListener(this.getBillCardPanel()));
			}
		}
		
		processHyperlink();
	}

	private void processHyperlink() {
		if (null == this.getClearHyperlink() || 0 == this.getClearHyperlink().size()) {
			return;
		}

		BillData billdata = this.getBillCardPanel().getBillData();
		for (String key : this.getClearHyperlink()) {
			BillItem item = billdata.getHeadItem(key);
			if (null == item)
				continue;
			item.getCaptionLabel().setHyperlinkLabel(false);
			item.setHyperlink(false);
		}
		for (String key : this.getClearHyperlink()) {
			BillItem item = billdata.getBodyItem(key);
			if (null == item)
				continue;
			item.getCaptionLabel().setHyperlinkLabel(false);
		}
	}

	public void setClearHyperlink(Collection<String> clearHyperlink) {
		this.clearHyperlink = clearHyperlink;
	}

	@Override
	public void showMeUp() {
		super.showMeUp();

	}

	private FIBillCardPanelScaleProcessor getArapBillCardPanelScaleProcessor() {
		if (null == arapBillCardPanelScaleProcessor) {
			arapBillCardPanelScaleProcessor = new ArapBillCardPanelScaleProcessor();
		}
		return arapBillCardPanelScaleProcessor;
	}

	/**
	 * 解决列表界面, 自定义交易类型的单据模板的templateContainer没有加载
	 * 
	 * @see nc.ui.uif2.editor.BillForm#initBillCardPanel()
	 */
	@Override
	protected void initBillCardPanel() {
		Log.getInstance(this.getClass()).error("strat initcardpanel");
		try {
			super.initBillCardPanel();
		} catch (IllegalArgumentException e) {
			Log.getInstance(this.getClass()).error("error initcardpanel");
			Log.getInstance(this.getClass()).error(e);
			// 不能缓存单据模板
			TemplateContainer templateContainer = getTemplateContainer();
			setTemplateContainer(null);
			super.initBillCardPanel();
			setTemplateContainer(templateContainer);
		}
		Log.getInstance(this.getClass()).error("strat initcardpanel");

	}

	// only for 外来单据打开收付界面， 然后往界面上设置VO
	private final Map<String, String> currtypeMap = new HashMap<String, String>();
	private String headCurrtype;

	@Override
	public Map<String, String> getPk_currtype() {
		return this.currtypeMap;
	}

	public void putCurrtype(String itemPK, String pk_currtype) {
		currtypeMap.put(itemPK, pk_currtype);
	}

	@Override
	public String getHeadCurrtype() {
		return headCurrtype;
	}
	
	//存放结算信息的地方
	private SettlementAggVO settleInfo ;

	@Override
	public SettlementAggVO getSettlementInfo() {
		return settleInfo;
	}

	@Override
	public void setSettlementInfo(SettlementAggVO settlementInfo) {
		this.settleInfo = settlementInfo;
	}

	@Override
	public Object getBillApproveStatus() {
		BillItem item = ((BillData)getBillData()).getHeadItem(IBillFieldGet.APPROVESTATUS);
		return item.getValueObject().toString();
	}

	@Override
	public Object getBillData() {
		return this.getBillCardPanel().getBillData();
	}
}