package com.dbs.mplus.fatima.consent.webservice;

import com.dbs.mplus.fatima.consent.ConsentConstants;
import com.dbs.mplus.fatima.consent.webservice.model.SaveCompleteAll;
import com.dbs.mplus.fatima.consent.webservice.model.CheckConsentState;
import com.dbs.mplus.fatima.consent.webservice.model.SaveImageSignInfo;
import com.dbs.mplus.fatima.consent.webservice.model.SaveTempData;
import com.dbs.mplus.fatima.framework.util.MPlusLogUtil;
import com.dbs.mplus.fatima.framework.util.MPlusStringUtil;

import org.json.JSONObject;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.Map;

/**
 * Created by dbs on 2016-10-12.
 */

public class ConsentWSWrapper {

    private static ConsentWSWrapper instance;

    private ConsentWSWrapper() { };

    public static ConsentWSWrapper getInstance() {
        if(instance == null) {
            instance = new ConsentWSWrapper();
        }
        return instance;
    }

    public int checkConsentState(int consentMstRid, String consentState) throws  Exception {
        CheckConsentState checkConsentState = new CheckConsentState();
        // 1번째 인자:  string consentmstrid    동의서Rid
        checkConsentState.consentMstRid = consentMstRid;
        // 2번째 인자:  string consentState    동의서상태 O:CERTIFY_CMP, X:ELECTR_CMP
        checkConsentState.consentState = consentState;
        Object result = this.callConsentWebService(checkConsentState.GetSoapAction(), checkConsentState.GetSoapParams());
        return Integer.parseInt((String)result);
    }

    /**
     *
     * @param formParam
     * @param userId
     * @param dataXml
     * @param formXml
     * @param deviceMacAddr
     * @param visitType
     * @return
     * @throws Exception
     */
    public int saveTempData(Map<String, String> formParam, String userId, String dataXml, String formXml, String deviceMacAddr, String visitType) throws  Exception {
        SaveTempData saveTempData = new SaveTempData();
        // 1번째 인자:	string dschdd	로그인 사용자ID
        saveTempData.userId = userId;
        // 2번째 인자:	string patientCode	환자 등록번호 PatientVO	IO_Pt_ID
        saveTempData.patientCode = null2Blink(formParam.get("IO_Pt_ID"));
        // 3번째 인자:	string clnDeptCode	진료과 코드 PatientVO	IO_DeptCd	환자의 진료과 코드(선택된 내원 기준)
        saveTempData.clnDeptCode = null2Blink(formParam.get("IO_DeptCd"));
        // 4번째 인자:	int cretno	작성된 서식Rid GetConsentBySearch 함수의 반환 값인 ConsentBySearchVO의 FormRid를 넘겨야 함
        saveTempData.formRid = MPlusStringUtil.convertStringToInteger(formParam.get("formRid"));
        // 5번째 인자:	string formCd	서식 코드 GetConsentBySearch 함수의 반환 값인 ConsentBySearchVO의 FormCd를 넘겨야 함
        saveTempData.formCd = null2Blink(formParam.get("formCd"));
        // 6번째 인자:	int orddd	동의서 마스터 데이터 Rid "이전 동의서 저장시 발생한 동의서 마스터 키 최초 작성시 -1을 넘겨야 하고 재 임시저장시 원래 Rid를 넘겨야 Update됨"
        String rid = null2Blink(formParam.get("rid"));
        if(rid == null || rid.isEmpty()) {
            saveTempData.consentMstRid = -1;
        } else {
            saveTempData.consentMstRid = MPlusStringUtil.convertStringToInteger(rid);
        }
        // 7번째 인자:	int rewriteConsentMstRid	재 작성 대상 동의서 마스터 데이터 Rid						재작성의 경우는 없으므로 무조건 0 넘김
        saveTempData.rewriteConsentMstRid = 0;
        // 8번째 인자:	string formXml	동의서 임시저장 형식(EPT) Xml	"CLIP e-Form View를 통해서 임시 저장된 결과를 받아 넘겨야 함TEMP_SAVE_PATH 이벤트에서 전달되는 value"
        saveTempData.formXml = formXml;
        // 9번째 인자:	string dataXml	CLIP e-Form Data Xml ViewerCtrl.GetDataXml()
        saveTempData.dataXml = dataXml;
        // 10번째 인자:	string deviceType	장비 유형	안드로이드 기기는 AND
        saveTempData.deviceType = ConsentConstants.DEVICE_TYPE;
        // 11번째 인자:	string deviceIdentNo	장비 고유 식별자 동의서를 저장한 디바이스의 고유 식별자 Android는 MAC address
        saveTempData.deviceIdentNo = deviceMacAddr;
        // 12번째 인자:	string visitType	내원구분 PatientVO	IO_VisitType	PatientVO객체의 IO_VisitType속성 사용
        saveTempData.vistType = visitType;
        // 13번째 인자:	string hosType	병원구분 PatientVO	IO_HosType	"111"고정 값
        saveTempData.hosType = ConsentConstants.HOSPITAL_TYPE;
        // 14번째 인자:	string clnDate	수진일자 PatientVO	IO_ADdate "입원일자 또는 진료일자 (yyyyMMdd)PatientVO객체의 IO_Addate속성 사용"
        saveTempData.clnDate = null2Blink(MPlusStringUtil.convertDateString(formParam.get("IO_ADdate"), "yyyy/MM/dd", "yyyyMMdd"));
        // 15번째 인자:	string ward	병동 코드 PatientVO	IO_Ward	입원환자의 병동 코드(외래의 경우 빈 문자열)
        saveTempData.ward = null2Blink(formParam.get("ward"));
        // 16번째 인자:	string roomcd	병실 코드 PatientVO	IO_RoomNo	입원환자의 병실 코드(외래의 경우 빈 문자열)
        saveTempData.roomcd = null2Blink(formParam.get("roomNo"));
        // 17번째 인자:	int orderNo	처방번호 PatientVO	IO_OrderNo
        saveTempData.orderNo = MPlusStringUtil.convertStringToInteger(formParam.get("orderNo"));
        // 18번째 인자:	string orderName	처방명	PatientVO	IO_DxNm
        saveTempData.orderName = null2Blink(formParam.get("IO_Dx"));
        // 19번째 인자:	string orderCd	처방코드 PatientVO	IO_DxCd
        saveTempData.orderCd = null2Blink(formParam.get("orderCd"));
        // 20번째 인자:	string ocrCode	OCR 코드 PatientVO	IO_OcrCd	Consent_Mst
        // 테이블에 처방에 의해서 데이터가 생성되는 경우에는 OCR코드가 있으므로, 그것을 설정하고,
        // OCR코드가 없는 경우(동의서를 찾기해서 미리보는 경우, 멀티출력 등)에는 웹서비스를 호출해서 OCR코드를 채번해서 넣어준다.
        saveTempData.ocrCode = null2Blink(formParam.get("IO_ocr_cd"));
        // 21번째 인자:	int cretno	생성번호 PatientVO	IO_CretNo
        saveTempData.cretno = MPlusStringUtil.convertStringToInteger(formParam.get("consentCretno"));    // 동의서 생성번호
        // 22번째 인자:	string createUserName	작성자명 로그인 사용자 이름
        saveTempData.createUserName = null2Blink(formParam.get("IO_INPUTNM"));
        // 23번째 인자: 수정자명 로그인 사용자 이름
        saveTempData.modifyUserName = null2Blink(formParam.get("IO_INPUTNM"));
        // 24번째 인자: 환자 주치의 아이디
        saveTempData.mainDrId = null2Blink(formParam.get("mainDrId"));
        Object result = this.callConsentWebService(saveTempData.GetSoapAction(), saveTempData.GetSoapParams());
        MPlusLogUtil.DEBUG(this.getClass(), "SaveTempData 결과:" + result);
        return Integer.parseInt((String)result);
    }

    public int saveCompleteAll(Map<String, String> formParam, String userId, String dataXml, String formXml, String deviceMacAddr, String visitType, String consentState, JSONObject imageFilesJsonObj, String certTarget, String certResult) throws Exception {
        SaveCompleteAll request = new SaveCompleteAll();
        // 1번째 인자:	string userId	로그인 사용자ID
        request.userId = userId;
        // 2번째 인자:	string patientCode	환자 등록번호
        request.patientCode = null2Blink(formParam.get("IO_Pt_ID"));
        // 3번째 인자:	string clnDeptCode	진료과 코드
        request.clnDeptCode = null2Blink(formParam.get("IO_DeptCd"));
        // 4번째 인자:	int formRid	작성된 서식Rid
        request.formRid = MPlusStringUtil.convertStringToInteger(formParam.get("formRid"));
        // 5번째 인자:	string formCd	서식 코드
        request.formCd = null2Blink(formParam.get("formCd"));
        // 6번째 인자:	int consentMstRid	동의서 마스터 데이터 Rid	최초 작성시 -1을 넘겨야 하고 재 임시저장시 원래 Rid를 넘겨야 Update됨
        String rid = formParam.get("rid");
        if(rid == null || rid.isEmpty()) {
            request.consentMstRid = -1;
        } else {
            request.consentMstRid = MPlusStringUtil.convertStringToInteger(rid);
        }
        // 7번째 인자:	int rewriteConsentMstRid	재 작성 대상 동의서 마스터 데이터 Rid	재작성의 경우는 없으므로 0
        request.rewriteConsentMstRid = 0;
        // 8번째 인자:	string formXml	동의서 임시저장 형식(EPT) Xml
        request.formXml = formXml;
        // 9번째 인자:	string dataXml	CLIP e-Form Data Xml	아직 데이터 사용하는 곳이 없으나 기왕력에 적용할 예정 임
        request.dataXml = dataXml;
        // 10번째 인자:	string deviceType	장비 유형	WIN, AND, IOS, PRT 중1
        request.deviceType = ConsentConstants.DEVICE_TYPE;
        // 11번째 인자:	string deviceIdentNo	장비 고유 식별자
        request.deviceIdentNo = deviceMacAddr;
        // 12번째 인자:	string vistType	내원구분
        request.vistType = visitType;
        // 13번째 인자:	string hosType	병원구분
        request.hosType = ConsentConstants.HOSPITAL_TYPE;
        // 14번째 인자:	string clnDate	수진일자 	입원일자 또는 진료일자 (yyyyMMdd)
        request.clnDate = null2Blink(MPlusStringUtil.convertDateString(formParam.get("IO_ADdate"), "yyyy/MM/dd", "yyyyMMdd"));
        // 15번째 인자:	string ward	병동 코드
        request.ward = null2Blink(formParam.get("ward"));
        // 16번째 인자:	string roomcd	병실 코드
        request.roomcd = null2Blink(formParam.get("roomNo"));
        // 17번째 인자:	int orderNo	처방번호
        request.orderNo = MPlusStringUtil.convertStringToInteger(formParam.get("orderNo"));
        // 18번째 인자:	string orderName	처방명
        request.orderName = null2Blink(formParam.get("IO_Dx"));
        // 19번째 인자:	string orderCd	처방코드
        request.orderCd = null2Blink(formParam.get("orderCd"));
        // 20번째 인자:	string ocrCode	OCR 코드
        request.ocrCode = null2Blink(formParam.get("IO_ocr_cd"));
        // 21번째 인자:	int cretno	생성번호
        request.cretno = MPlusStringUtil.convertStringToInteger(formParam.get("hospitalCretno"));    // 동의서 생성번호
        // 22번째 인자:	string createUserName	작성자명
        request.createUserName = null2Blink(formParam.get("IO_INPUTNM"));
        // 23번째 인자:	string modifyUserName	수정자명
        request.modifyUserName = null2Blink(formParam.get("IO_INPUTNM"));
        // 24번째 인자:	string imageFileJson	이미지파일 경로	{ "imageFile1" : "201611/01/6c4b63c6b2294d8b9b05cd32d9c1dd54_1.jpg", "imageFile2" : "201611/01/6c4b63c6b2294d8b9b05cd32d9c1dd54_2.jpg", "imageFile3" : "201611/01/6c4b63c6b2294d8b9b05cd32d9c1dd54_3.jpg" }
        request.imageFileJson = imageFilesJsonObj.toString();
        // 25번째 인자:	string certTarget	전자서명 대상	이미지 해쉬 연결 값(adfsdfa^asdfasdf)
        request.certTarget = certTarget;
        // 26번째 인자:	string certResult	전자서명 결과	공인인증서 전자서명 결과 값
        request.certResult = certResult;
        // 27번째 인자:	string dschdd	퇴원일자	환자의 퇴원일자
        request.dschdd = null2Blink(formParam.get("outDate"));
        // 28번째 인자:	string consentState	동의서 상태
        // 공인인증 O:CERTIFY_CMP, X:ELECTR_CMP
        request.consentState = consentState;
        // 24번째 인자:	string mainDrId	환자 주치의 아이디
        request.mainDrId = null2Blink(formParam.get("mainDrId"));

        MPlusLogUtil.DEBUG(this.getClass(), "SaveCompleteAll 요청:" + request.toString());

        Object result = this.callConsentWebService(request.GetSoapAction(), request.GetSoapParams());
        MPlusLogUtil.DEBUG(this.getClass(), "SaveCompleteAll 결과:" + result);
        Integer mstRid = Integer.parseInt((String)result);
        if(mstRid == null) {
            throw new Exception("SaveCompleteAll 실패");
        }
        return mstRid.intValue();
    }

    /**
     * SaveComplete을 하는 경우에만 이미지를 저장한다.
     * 한 동의서가 5페이지인 경우, 1개의 consentMstRid에 1개의 Row가 생성된다.
     *  떄문에 이미지당 하나씩 해쉬정보를 추출한 후 ^ 표시로 연결하여, 한번에 certTarget으로 저장한다."
     * @param consentMstRid
     * @param consentImgRid
     * @param userId
     * @param hashValue
     * @throws Exception
     */
    public void saveImageSignInfo(int consentMstRid, int consentImgRid, String userId, String hashValue, String certValue) throws Exception {
        SaveImageSignInfo imageSignInfo = new SaveImageSignInfo();
        // 1번째 인자:	string pid	동의서 상태	"ELECTR_CMP"
        imageSignInfo.consentState = "ELECTR_CMP";
        // 2번째 인자:	int orddd	동의서 마스터 데이터 Rid
        imageSignInfo.consentMstRid = consentMstRid;
        // 3번째 인자:	int consentImageRid	이미지 데이터 Rid	"첫번째 consentImageRid 웹서비스 SaveImageUploadInfo() 에서 리턴받은 이미지 데이터 Rid"
        imageSignInfo.consentImageRid = consentImgRid;
        // 4번째 인자:	string dschdd	등록자ID
        imageSignInfo.userId = userId;
        // 5번째 인자:	string certTarget	hash 정보	페이지별 생성된 각 이미지의 해쉬정보를 추출한 문자열을 페이지1^페이지2^ 이런식으로 조합한 문자열
        imageSignInfo.certTarget = hashValue;
        // 6번째 인자: 서명값
        imageSignInfo.sCertResult = certValue;
        this.callConsentWebService(imageSignInfo.GetSoapAction(), imageSignInfo.GetSoapParams());
    }

    /**
     * 웹서비스 호출
     * @param action
     * @param request
     * @return
     * @throws IOException
     * @throws XmlPullParserException
     */
    private Object callWebService(String action, SoapObject request, String address) throws Exception {
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.dotNet = true;
        envelope.setOutputSoapObject(request);

        // Create HTTP call object
        HttpTransportSE androidHttpTransport = new HttpTransportSE(address);

        MPlusLogUtil.DEBUG(this.getClass(), "웹서비스 call(" + address + ") request: " +  request);

        androidHttpTransport.call(action, envelope);

        Object body = envelope.bodyIn;
        if(body instanceof SoapObject) {
            SoapObject response = (SoapObject)body;
            // 값이 있는 경우 빼옴
            if(response.getPropertyCount() > 0) {
                // 앱에서 필요한 데이터는 1개씩 밖에 없어서 첫번째 값만 뽑음
                Object bodyValue = response.getProperty(0);
                if(bodyValue != null && bodyValue instanceof SoapPrimitive) {
                    return ((SoapPrimitive)bodyValue).getValue();
                }
            }
        } else if(body instanceof SoapFault){
            SoapFault response = (SoapFault)body;
            throw new Exception(response.faultstring);
        }
        return null;
    }

    private Object callHospitalWebService(String action, SoapObject request) throws Exception {
        return this.callWebService(action, request, ConsentConstants.HOSPITAL_WEBSERVICE);
    }

    private Object callConsentWebService(String action, SoapObject request) throws Exception {
        return this.callWebService(action, request, ConsentConstants.CONSENT_WEBSERVICE);
    }

    private String null2Blink(String value) {
        if(value == null) {
            return "";
        }
        return value;
    }
}
