package com.eactive.eai.rms.onl.manage.rule.transformrule;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.eactive.eai.common.util.NullControl;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformRuleVo;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformVo;
import com.eactive.eai.rms.onl.manage.rule.transformfunc.TransformFuncDao;
import com.eactive.eai.transformer.layout.Item;
import com.eactive.eai.transformer.layout.ItemFactory;
import com.eactive.eai.transformer.layout.Layout;
import com.eactive.eai.transformer.layout.LayoutType;
import com.eactive.eai.transformer.message.BytesMessage;
import com.eactive.eai.transformer.message.CardMessage;
import com.eactive.eai.transformer.message.CommonBytesMessage;
import com.eactive.eai.transformer.message.CommonEbcdicMessage;
import com.eactive.eai.transformer.message.DelimiterMessage;
import com.eactive.eai.transformer.message.EbcdicMessage;
import com.eactive.eai.transformer.message.JSONMessage;
import com.eactive.eai.transformer.message.Message;
import com.eactive.eai.transformer.message.MonitoringVBytesMessage;
import com.eactive.eai.transformer.message.MonitoringVEbcdicMessage;
import com.eactive.eai.transformer.message.ObjectMessage;
//import com.eactive.eai.transformer.message.UJSONMessage;
import com.eactive.eai.transformer.message.VariableBytesMessage;
import com.eactive.eai.transformer.message.VariableEbcdicMessage;
import com.eactive.eai.transformer.message.VariableFieldMessage;
import com.eactive.eai.transformer.message.XMLMessage;


@Service("transformRuleService")
public class TransformRuleService extends BaseService {

    String resultFileName = "/fsapp/doc/TransformRule/loadResult.txt";
    String loadFileName = "/fsapp/doc/TransformRule/load.sh";
    
    @Autowired
 	@Qualifier("transformRuleDao")
 	private TransformRuleDao transformRuleDao;
    
    @Autowired
 	@Qualifier("transformFuncDao")
 	private TransformFuncDao transformFuncDao;
    
    
    
	/**
	 * 변환규칙 목록 조회
	 * 
	 */
	public void load(TransformRuleVo vo) throws IOException {	    
	   
	    File result = new File(resultFileName);
	    StringBuffer loadResult = new StringBuffer();
	    Runtime         run = null;
	    Process			p = null;

        if(result.exists()) { 
            result.delete();        //기존 결과 파일 삭제
        }
        loadResult = new StringBuffer();
        run = Runtime.getRuntime();
        p = run.exec(loadFileName+" > "+resultFileName);  
	}
	
	public void clear(TransformRuleVo vo) {
	    File result = new File(resultFileName);
	   // StringBuffer loadResult = new StringBuffer();
	    if(result.exists()) { 
	       result.delete();        //기존 결과 파일 삭제
	   }
	}
	
	public void view(TransformRuleVo vo) throws IOException {
	    File result = new File(resultFileName);
	    StringBuffer loadResult = new StringBuffer();
	    BufferedReader readLog = new BufferedReader (new InputStreamReader(new  FileInputStream(result)));
	    String msg = "";
        if (readLog != null ) {
        	try{
        		while ((msg = readLog.readLine()) != null){
        			loadResult.append("&nbsp;"+msg+"\n");
        		}
        	}
    		catch(Exception ex) {
				logger.error("view error", ex);
			}
			finally {
				if(readLog != null) try { readLog.close(); } catch(Exception ee) {}
			}
        }  
        vo.setResult(loadResult.toString());
	}
	
	public void info(TransformRuleVo vo) throws IOException {
	    String proFileName = "/fsapp/doc/TransformRule/data/transform/config/config.properties";
	    String buildPropFileName = "/fsapp/doc/TransformRule/build.properties";
	    
	    File dir = new File(proFileName);
	    BufferedReader in = new BufferedReader(new InputStreamReader(new  FileInputStream(dir)));
	    StringBuffer dbinfo = new StringBuffer();
	    String msg = "";
	    String transRuleHome = "";
	    File buildProp = new File(buildPropFileName);
	    
	   try{
	        while ((msg = in.readLine()) != null){
	           if ( msg.length() > 0 && !msg.startsWith("#")){
	              dbinfo.append("&nbsp;"+msg+"<br>");
	            }
	        }
	    }catch (Exception e){
	    	logger.debug("error", e);
	    } finally {
        	try {
        		if(in != null) in.close();
        	}
        	catch(Exception e) {
        		logger.debug("close error", e);
        	}
        }
	    
	    if(buildProp != null) {
	        BufferedReader build = new BufferedReader(new InputStreamReader(new  FileInputStream(buildProp))); 
	        try{
	        	 while((msg = build.readLine()) != null) {
	 	            if ( msg.length() > 0 && msg.startsWith("TRAN.RULE.HOME")){
	 	                transRuleHome = msg.split("=")[1];
	 	            }     
	 	        } 
	        }catch (Exception e){
		    	logger.debug("error", e);
		    } finally {
	        	try {
	        		if(build != null) build.close();
	        	}
	        	catch(Exception e) {
	        		logger.debug("close error", e);
	        	}
	        }
	       
	    }
	    
	    vo.setDbinfo(dbinfo.toString());
	    vo.setLocation(transRuleHome);

	}

  /**
     * 변환룰 엑셀 파일 업로드용 : DB 에서 레이아웃 정보를 조회한다.
     * @return
     * @throws Exception
     */
    //@Transactional(readOnly = true, rollbackFor = Exception.class)
    public List loadLayoutMap(String layoutName) throws Exception {
        HashMap map = new HashMap();
        map.put("loutName", layoutName);
        return transformRuleDao.selectLoadLayout(map);
    }

    public Layout loadLayout(String layoutName) throws Exception {

        Layout layout = new Layout();
        List<HashMap> list = loadLayoutMap(layoutName);
        
        for (HashMap returnMap : list) {
        	
            layout.setName((String) returnMap.get("LOUTNAME"));
            layout.setDescription((String) returnMap.get("LOUTDESC"));
            
            LayoutType layoutType = getLayoutType((String) returnMap.get("LOUTPTRNNAME"));
            if (layoutType == null) {
                throw new Exception("target layout type not found ! - "
                        + returnMap.get("loutPtrnName"));
            }
            layout.setLayoutType(layoutType);
            Item root = findItemByName(layout.getName(), layout);
            
            layout.setRootItem(root);
            // 실제로 레이아웃명을 파라미터로 하기 때문에 리턴 갯수는 1개 이다.            
            break;
        }

        return layout;
    }

    public Item findItemByName(String layoutName, Layout layout)
            throws Exception {
      
        List<HashMap> list = transformRuleDao.selectLayoutItemList(layoutName);
        
        if (list == null || list.size() == 0) {
            return null;
        }
        
        HashMap<Integer, Integer> levelMap = new HashMap<Integer, Integer>();
        
        Iterator iter = list.iterator();
        
        HashMap rowMap = (HashMap) iter.next();
        
        int level = 0;
        int itemId = ((Integer)rowMap.get("LOUTITEMIDNAME"));
        int parentId = ((Integer)rowMap.get("PARNTLOUTITEMIDNAME"));
        
        if (parentId != 0) {
            throw new Exception("ROOT Item ParntLoutItemIDName는 0 이어야 합니다. - "
                    + parentId);
        }
        
    	level = 1;
    	levelMap.put(itemId, level);
        rowMap.put("level", level);
        
        Item root = makeItem(rowMap, layout);
        
        // root 는 Message 인지 체크
        if (root.getNodeTypeId() != Item.NODE_MESSAGE) {
            throw new Exception("ROOT Item Node Type은 MESSAGE TYPE이어야 합니다. - "
                    + root.getNodeTypeId());
        }

        Item parent = root;

        while(iter.hasNext()) {
        	rowMap = (HashMap) iter.next();
        	itemId = ((Integer)rowMap.get("LOUTITEMIDNAME"));
            parentId = ((Integer)rowMap.get("PARNTLOUTITEMIDNAME"));
            
        	if(levelMap.get(parentId) != null) {
        		level = levelMap.get(parentId);
        		level++;
        	}
        	else {
        		level = (Integer) rowMap.get("LOUTDPTCNT");
        	}
        	
        	levelMap.put(itemId, level);            
            rowMap.put("level", level);
            
            Item child = makeItem(rowMap, layout);

            parent = getRecursiveParent(child, parent, layoutName);

            switch (child.getNodeTypeId()) {
            case Item.NODE_MESSAGE:
            case Item.NODE_GROUP:
                parent.addChild(child);
                child.setParent(parent);
                parent = child;
                break;
            case Item.NODE_FIELD:
                parent.addChild(child);
                child.setParent(parent);
                break;
            case Item.NODE_ATTR:
                parent.addChild(child);
                child.setParent(parent);
                break;
            default:
                throw new Exception("Layout Item 의 타입이 정의된 값이 아닙니다. : " + child);
            }
        }
        return root;
    }
    
    public LayoutType getLayoutType(String layoutTypeName) throws Exception {
        HashMap<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("loutName", layoutTypeName);

        List<HashMap> list = transformRuleDao.selectLayoutTypeManDetail(paramMap);
        if (list == null || list.size() == 0) {
            return null;
        }

        HashMap map = (HashMap) list.get(0);

        // F/W 의 transformer 패키지 내 class
        LayoutType type = new LayoutType();
        type.setName((String) map.get("LAYOUT_NAME"));
        type.setDescription((String) map.get("LAYOUT_DESC"));
        type.setGenClass((String) map.get("GEN_CLASS"));

        return type;
    }
    
    /**
     * Transformer.jar 의 LayoutJdbcDao.java 에서 그대로 복사해옴.
     * @param child
     * @param parent
     * @param layoutName
     * @return
     * @throws Exception
     */
    private Item getRecursiveParent(Item child, Item parent, String layoutName)
            throws Exception {
        if (parent == null) {
            StringBuffer sb = new StringBuffer();
            sb.append("item의 parent id 지정이 잘못 되었읍니다. - ");
            sb.append("layout=" + layoutName + ", ");
            sb.append("child=" + child.getName() + ", ");
            sb.append("child's parent id=" + child.getParentId());
            throw new Exception(sb.toString());
        }

        if (child.getParentId() == parent.getItemId())
            return parent;
        else
            return getRecursiveParent(child, parent.getParent(), layoutName);
    }
    
    /**
     * Transformer.jar 의 LayoutJdbcDao.java 파일에서 가져옴.
     * 변환규칙 엑셀 파일 업로드시 사용
     * @param row
     * @param layout
     * @return
     */
    private Item makeItem(HashMap row, Layout layout) throws Exception {
    	//String layoutName = (String) row.get("LOUTNAME");
        if (layout == null) {
            // 주의 : 이곳에서 loadLayout() 을 수행하면 무한루프에 빠진다.
            throw new Exception("layout not found : '"
                    + ((String) row.get("LOUTNAME")) + "'");
        }
        Item item = null;
        
        if (((Integer) row.get("LOUTITEMNODEPTRNIDNAME")) == Item.NODE_MESSAGE) {
            if (layout.getLayoutType().getName().equals("BYTES")) {
                item = new BytesMessage();
            } else if (layout.getLayoutType().getName().equals("OBJECT")) {
                item = new ObjectMessage();
            } else if (layout.getLayoutType().getName().equals("XML")) {
                item = new XMLMessage();
            } else if (layout.getLayoutType().getName().equals("EBCDIC")) {
                item = new EbcdicMessage();
            } else if (layout.getLayoutType().getName().equals("CARD")) {
                item = new CardMessage();
            } else if (layout.getLayoutType().getName().equals("COMBYTES")) {
                item = new CommonBytesMessage();
            } else if (layout.getLayoutType().getName().equals("COMEBCDIC")) {
                item = new CommonEbcdicMessage();

                // 2009.10.06 dhlee 추가 - new type
            } else if (layout.getLayoutType().getName().equals("VBYTES")
                    || layout.getLayoutType().getName().equals("VASCII")) {
                item = new VariableBytesMessage();
                // 2014.04.15 KSH 추가
            } else if (layout.getLayoutType().getName().equals("VFIELD")) {
                item = new VariableFieldMessage();
            } else if (layout.getLayoutType().getName().equals("VEBCDIC")) {
                item = new VariableEbcdicMessage();
            } else if (layout.getLayoutType().getName().equals("JSON")) {
	            item = new JSONMessage();
//	        } else if (layout.getLayoutType().getName().equals("UJSON")) {
//		        item = new UJSONMessage();
	        } else if (layout.getLayoutType().getName().equals("MVBYTES")) {//오류 파싱을 위해서
	        	item = new MonitoringVBytesMessage();
	        } else if (layout.getLayoutType().getName().equals("MVEBCDIC")) {//오류 파싱을 위해서
	        	item = new MonitoringVEbcdicMessage();
	        } else if (layout.getLayoutType().getName().equals("DELIMITER")) {
	        	item = new DelimiterMessage();
	        }
            if (item == null) {
                throw new Exception("unsupported layout type - "
                        + layout.getLayoutType().getName());
            }

            if (layout.getName().equals((String) row.get("LOUTITEMNAME"))) {
                ((Message) item).setLayout(layout);
                item.setName((String) row.get("LOUTITEMNAME"));
                layout.setRootItem(item);
            }
        } else {
            int nodeTypeId = (Integer) row.get("LOUTITEMNODEPTRNIDNAME");
            item = ItemFactory.createItem(nodeTypeId);
        }

        item.setNodeTypeId((Integer) row.get("LOUTITEMNODEPTRNIDNAME"));
        item.setItemId((Integer) row.get("LOUTITEMIDNAME"));
        item.setParentId((Integer) row.get("PARNTLOUTITEMIDNAME"));
        //item.setNodeTypeId((Integer) row.get("LoutItemNodePtrnIDName"));
        item.setName((String) row.get("LOUTITEMNAME"));
        item.setDataTypeId((Integer) row.get("LOUTITEMPTRNIDNAME"));
        item.setDescription((String) row.get("LOUTITEMDESC"));
        item.setPath((String) row.get("LOUTITEMPATH"));
        item.setLength((Integer) row.get("LOUTITEMLENCNT"));
        item.setRefInfo((String) row.get("LOUTITEMREFINFO"));
        // use 'NullControl.trimSpace' to avoid 'DB2 NOT NULL ISSUE'
        item.setOccRef(NullControl.trimSpace((String) row.get("LOUTITEMREFINFO2")));
        item.setSeqNo((Integer) row.get("LOUTITEMSERNO"));
        item.setOccType((String) row.get("LOUTITEMOCCURPTRNDSTCD"));
        item.setOccMax((Integer) row.get("LOUTITEMMAXOCCURNOITM"));
        item.setOccMin((Integer) row.get("LOUTITEMMINOCCURNOITM"));
        //item.setDefaultValue(NullControl.trimSpace((String) row.get("LOUTITEMBASCVAL")));
        item.setLayoutName((String) row.get("LOUTNAME"));
        item.setMask((String) row.get("LOUTITEMMSKYN"));
                
        if (row.get("level") != null) {
            item.setDepth((Integer) row.get("level"));
        } else {
            item.setDepth((Integer) row.get("LYOUTDPTCNT"));
        }
        
        item.setDecimalPointLength((Integer) row.get("DECPTLENCNT"));
        item.setDataTypeRef((String) row.get("LOUTITEMREFPTRNIDNAME"));
        return item;
    }
    
    public void deleteTransform(TransformVo vo) throws Exception {
    	HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName",vo.getCnvsnName());
    	transformRuleDao.deleteTransform(paramMap);
    	transformRuleDao.deleteTransformSourceResult(paramMap);
    	transformRuleDao.deleteTransformItem(paramMap);
    
    }
	public void insertTransform(TransformVo vo, String eaiSevrDStcd) throws Exception{
		HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName",vo.getCnvsnName());
		paramMap.put("cnvsnDesc",vo.getCnvsnDesc());
		paramMap.put("eaiSevrDStcd",eaiSevrDStcd);
		paramMap.put("modfimgtStusdstcd","");
		paramMap.put("useYn","1");
		transformRuleDao.insertTransform(paramMap);
		
	}
	
	public void insertTransformLayout(TransformVo vo) throws Exception{
		HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName",vo.getCnvsnName());
		paramMap.put("loutName",vo.getLoutName());
		paramMap.put("sourcRsultDstcd",vo.getSourcRsultDstcd());
		
		transformRuleDao.insertTransformLayout(paramMap);
		
	}

	public void insertTransformItem(TransformVo vo) throws Exception{
		HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName",vo.getCnvsnName());
		paramMap.put("cnvsnRsultItemPathName",vo.getCnvsnRsultItemPathName());
		paramMap.put("cnvsnCmdName",vo.getCnvsnCmdName());
		paramMap.put("cnvsnItemBascVal",vo.getCnvsnItemBascVal());
		paramMap.put("cnvsnItemSerno",vo.getCnvsnItemSerno());
		transformRuleDao.insertTransformItem(paramMap);
		
	}
	
	public void updateTransfromEaiSvcName(HashMap paramMap) throws Exception{
		paramMap.put("chngEonot","1");
		transformRuleDao.updateTransfromEaiSvcName(paramMap);
		
	}
	
	public void deleteRefMsgID(TransformVo vo) throws Exception{
		transformRuleDao.deleteRefMsgID(vo);
	}
	
	public void insertRefMsgID(TransformVo vo) throws Exception{
		transformRuleDao.insertRefMsgID(vo);
	}

	public List getUserBizCode(String empno) throws  Exception{
		HashMap paramMap = new HashMap();
		paramMap.put("userId",empno);
		return transformRuleDao.getUserBizCode(paramMap);
	}

	
	public List selectAllTransFuncList() throws  Exception{
		HashMap paramMap = new HashMap();
		return transformFuncDao.selectListAll(paramMap);
	}
	

}
