/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.vas.sicbosubnc.wsfw.services;

import com.vas.sicbosubnc.wsfw.common.Common;
import com.vas.sicbosubnc.wsfw.common.EncryptUtil;
import com.vas.sicbosubncom.wsfw.obj.MpsConfigObj;
import com.viettel.ussdfw.log.ProcessTransLog;
import com.viettel.ussdfw.object.TransactionLog;
import com.viettel.ussdfw.object.WebserviceMsg;
import com.viettel.ussdfw.object.WebserviceObject;
import com.viettel.ussdfw.webservice.WebserviceFW;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 *
 * @author Sungroup
 */
public class WSProcessor extends WebserviceFW {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    public static String propertyTag = "original";
    public static String errorTag = "return";
    public static List<String> NOT_ENOUGH_MONEY_RES;
    public static List<String> ACCOUNT_BLOCKED_RES;
    public static List<String> LIST_SUCCESS_RES;
    public static List<String> LIST_CANCEL_SUCCESS_RES;

    public WSProcessor(Logger logger, String pathWSConfig) throws Exception {
        super(logger, pathWSConfig);
    }

    public WSProcessor(Logger logger, String pathWSConfig, String pathDatabaseConfig) throws Exception {
        super(logger, pathWSConfig, pathDatabaseConfig);
    }

    public String cancelService(String msisdn, String packName) {

        // TODO add your handling code here:  
        // insert to webservice table
        WebserviceObject wsObj = this.getWebservice("register");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        // get mps config
        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("CANCEL_" + packName);
        String mpsUrl = makeMpsUrl(msisdn, mpsConfig, wsObj.getWsdl(), false, null);

        logger.info("mpsUrl: " + mpsUrl);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());

        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);

            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when cancel service via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String registerMps(String msisdn, double fee, String packName) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("register");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("REGISTER_" + packName);
        String mpsUrl = makeMpsUrl(msisdn, mpsConfig, wsObj.getWsdl(), false, null);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when charge money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String requestMpsOtp(String msisdn, int fee, String REQ, String packName) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("register_otp");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("REGISTER_" + packName);

        logger.info("wsObj: " + wsObj.getWsdl());

        String mpsUrl = makeMpsUrl(msisdn, mpsConfig, wsObj.getWsdl(), true, REQ);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when charge money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String registerMpsConfirm(String msisdn, int fee, String otp, String REQ, String packName) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("register_otp");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("REGISTER_" + packName);
        String mpsUrl = makeMpsUrlOtpConfirm(msisdn, mpsConfig, wsObj.getWsdl(), otp, REQ);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when charge money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String chargeFeeOtp(String msisdn, int fee, String REQ) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("charge_fee");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("CHARGE_" + fee);
        String mpsUrl = makeMpsUrl(msisdn, mpsConfig, wsObj.getWsdl(), true, REQ);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when charge money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String chargeFeeConfirm(String msisdn, int fee, String otp, String REQ) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("charge_fee");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("CHARGE_" + fee);
        String mpsUrl = makeMpsUrlOtpConfirm(msisdn, mpsConfig, wsObj.getWsdl(), otp, REQ);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when charge money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String addMoney(String msisdn, int fee) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("add_money");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("ADD_" + fee);

//        MpsConfigObj mpsConfig = Common.mapMpsConfig.get(actionCode);
        String mpsUrl = makeMpsUrl(msisdn, mpsConfig, wsObj.getWsdl(), false, null);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when add money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }

    public String addData(String msisdn, int data) {
        // TODO add your handling code here: 
//        Map<String, String> params = new HashMap();
        WebserviceObject wsObj = this.getWebservice("add_data");
//        String isdn = msisdn.substring(Common.COUNTRY_CODE.length());
//        String keyPath = "../etc/key/" + packName + "/";

        MpsConfigObj mpsConfig = Common.mapMpsConfig.get("ADD_DATA_" + data);

//        MpsConfigObj mpsConfig = Common.mapMpsConfig.get(actionCode);
        String mpsUrl = makeMpsUrl(msisdn, mpsConfig, wsObj.getWsdl(), false, null);

        String value = null;
        //
        TransactionLog log = new TransactionLog();
        log.setMsisdn(msisdn);
        log.setType(3);
        log.setRequest(mpsUrl);
        log.setCommand(wsObj.getWsCode());
        log.setErrorCode("000");
        log.setChannel(wsObj.getWsdl());
        log.setRequestTime(new Timestamp(System.currentTimeMillis()));
        setTimeSt(System.currentTimeMillis());
        try {
            String response = sendMps(mpsUrl);
            //
            log.setResponse(response.length() >= 4000 ? response.substring(0, 3999) : response);
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));

            logger.info("Response from MPS:" + response);
            String data_complete_spamsms = EncryptUtil.decodeMpsResponse(response, mpsConfig.getKeyPath());
            value = EncryptUtil.analyseCodeReturn(data_complete_spamsms);
            logger.info("mps response value:" + value);
            String error = value.split("\\|")[0];

            log.setErrorCode(error);
            return error;
        } catch (Exception ex) {
            logger.error("Error when add money via MPS", ex);
            log.setResponse("Exception");
            log.setResponseTime(new Timestamp(System.currentTimeMillis()));
        } finally {
            logTime("Time to " + wsObj.getWsCode());
            ProcessTransLog.enqueue(log);
        }
        return value;
    }
    
    public String extendService(String msisdn,String prizeCode , String prizeType) {
        WebserviceObject obj = this.getWebservice("ADD_EMOLA");
        WebserviceMsg request = new WebserviceMsg();
        request.setMsisdn(msisdn);
        String msgTemplate = obj.getMsgTemplate();
        
        msgTemplate = msgTemplate.replace("#MSISDN#", msisdn);
        msgTemplate = msgTemplate.replace("#PRIZECODE#", prizeCode);
        msgTemplate = msgTemplate.replace("#PRIZETYPE#", prizeType);
        request.setRequest(msgTemplate);

        WebserviceMsg response = this.send(request, obj);
        //String original = response.getProperty("return");
        String error = StringUtils.substringBetween(response.getResponse(), "<errorCode>", "</errorCode>");
        if (!error.equals("0")) {
            String content = StringUtils.substringBetween(response.getResponse(), "<content>", "</content>");
            return error + "|" + content;
        }
        return error;
    }
//    public String extendServiceDoSpin(String msisdn) {
//        WebserviceObject obj = this.getWebservice("Prize_winner");
//        WebserviceMsg request = new WebserviceMsg();
//        request.setMsisdn(msisdn);
//        String msgTemplate = obj.getMsgTemplate();
//        
//        msgTemplate = msgTemplate.replace("#MSISDN#", msisdn);
//        request.setRequest(msgTemplate);
//
//        WebserviceMsg response = this.send(request, obj);
//        //String original = response.getProperty("return");
//        String error = StringUtils.substringBetween(response.getResponse(), "<errorCode>", "</errorCode>");
//        if (!error.equals("0")) {
//            String content = StringUtils.substringBetween(response.getResponse(), "<content>", "</content>");
//            return error + "|" + content;
//        }
//        return error;
//    }
    

    private String sendMps(String url) throws Exception {
        logger.info("Request to mps: " + url);
        String strTemp = "";
        try {
            URL urlre_spamsms = new URL(url);
            InputStream ips = urlre_spamsms.openStream();
            BufferedReader br_spamsms = new BufferedReader(new InputStreamReader(ips));
            while (null != (strTemp = br_spamsms.readLine())) {
                if (strTemp.length() > 200) {
                    return strTemp;
                } else {
                    logger.warn("abort, mps response:" + strTemp);
                }
            }
        } catch (Exception ex) {
            logger.error("Error when send charge request to MPS", ex);
            throw ex;
        }
        return strTemp;

    }

    private String makeMpsUrl(String msisdn, MpsConfigObj mpsConfig, String wsUrl, boolean isOtpRequest, String requestId) {

        Map<String, String> params = new HashMap();
        String service = mpsConfig.getService();
        String subService = mpsConfig.getSubService();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String REQ = requestId != null ? requestId : dateFormat.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
        String SESS = dateFormat.format(new Date()) + "2" + msisdn.substring(Common.COUNTRY_CODE.length());
        String command = mpsConfig.getCommand();
        String proCode = mpsConfig.getCpName();
        params.put("SUB", mpsConfig.getSubService());//fix
        params.put("REQ", REQ);//fix
        params.put("CATE", mpsConfig.getCategory());
        params.put("ITEM", "NULL");
        params.put("IMEI", "NULL");
        params.put("SUB_CP", "");
        params.put("CONT", "BLANK");
        params.put("PRICE", mpsConfig.getPrice());
        params.put("MOBILE", msisdn);
        params.put("TYPE", "MOBILE");
        params.put("SOURCE", "CLIENT");

//        logger.info("command " + mpsConfig.getCommand());
//        logger.info("getCpName " + mpsConfig.getCpName());
//        logger.info("getSubService " + mpsConfig.getSubService());
//        logger.info("getCategory " + mpsConfig.getCategory());
        if (isOtpRequest) {
            params.put("OTP_TYPE", "0");
        } else {
            params.put("SESS", SESS);//fix 
        }

        String mpsUrl = EncryptUtil.makeMpsRequestUrl(proCode, service, subService, command, wsUrl, params, mpsConfig.getKeyPath());
        return mpsUrl;
    }

    private String makeMpsUrlOtpConfirm(String msisdn, MpsConfigObj mpsConfig, String wsUrl, String otp, String REQ) {

        Map<String, String> params = new HashMap();
        String service = mpsConfig.getService();
        String subService = mpsConfig.getSubService();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
//        String REQ = dateFormat.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
        String SESS = dateFormat.format(new Date()) + "2" + msisdn.substring(Common.COUNTRY_CODE.length());
        String command = mpsConfig.getCommand();
        String proCode = mpsConfig.getCpName();
        params.put("SUB", mpsConfig.getSubService());//fix
        params.put("REQ", REQ);//fix
//        params.put("SESS", SESS);//fix 
        params.put("CATE", mpsConfig.getCategory());
        params.put("ITEM", "NULL");
        params.put("IMEI", "NULL");
        params.put("SUB_CP", "");
        params.put("CONT", "BLANK");
        params.put("PRICE", mpsConfig.getPrice());
        params.put("MOBILE", msisdn);
        params.put("TYPE", "MOBILE");
        params.put("SOURCE", "CLIENT");
        params.put("OTP", otp);
        params.put("OTP_TYPE", "1");

        String mpsUrl = EncryptUtil.makeMpsRequestUrl(proCode, service, subService, command, wsUrl, params, mpsConfig.getKeyPath());
        return mpsUrl;
    }
    
    public static String getMessageFromResult(Logger logger, String resultFromMps) {
        logger.info("Response from MPS to convert to message:" + resultFromMps);
        if (resultFromMps.contains("416")) {
            return "Your OTP is wrong";
        } else if (resultFromMps.contains("415")) {
            return "Your OTP is not valid";
        } else if (resultFromMps.contains("401")) {
            return "You have not enough money to make this transaction";
        } else if (resultFromMps.contains("408")) {
            return "Msisdn is using service";
        } else {
            String[] resSeprate = resultFromMps.split("|");
            return (resultFromMps.length() > 1 ? resSeprate[1] : "ERROR when charging");
        }
    }

    public static String getErrorCodeFromResult(Logger logger, String resultFromMps) {
        logger.info("Response from MPS to convert to error code:" + resultFromMps);
        return resultFromMps;
//        String[] resSeprate = resultFromMps.split("|");
//        return (resultFromMps.length() > 0 ? resSeprate[0] : Common.ErrorCode.CHARGE_ERROR);
    }
}
