package com.dbs.mplus.fatima.consent;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.webkit.WebView;
import android.widget.EditText;

import com.dbs.mplus.fatima.MPlusConstants;
import com.dbs.mplus.fatima.consent.sign.SignWrapper;
import com.dbs.mplus.fatima.framework.MPlusFrameworkConstants;
import com.dbs.mplus.fatima.framework.processor.msg.ConsentMessage;
import com.dbs.mplus.fatima.framework.util.MPlusDeviceUtil;
import com.dbs.mplus.fatima.framework.util.MPlusLogUtil;
import com.dbs.mplus.fatima.framework.util.MPlusStringUtil;
import com.dbs.mplus.fatima.framework.view.dialog.MPlusDialog;
import com.lumensoft.ks.KSException;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

import kr.co.clipsoft.eform.EFormToolkit;
import kr.co.clipsoft.eform.information.RunOption;
import kr.co.clipsoft.eform.type.enumtype.LogLevel;
import kr.co.clipsoft.eform.type.enumtype.Position;
import kr.co.clipsoft.eform.type.enumtype.ScreenOrientation;

/**
 * Created by dbs on 2016-09-22.
 */

public class ConsentFacade {
    private EFormToolkit toolkit;

    private final WebView webView;

    public ConsentFacade(Context context, WebView webView) {
        // 뷰어 생성
        this.toolkit = new EFormToolkit(context);
        this.webView = webView;
    }

    private RunOption createRunOption() {
        RunOption runOption = new RunOption();
        // default Option
        runOption.setScreenOrientation(ScreenOrientation.Sensor); 	// 가로세로 전환 모드
        runOption.setFirstPageLoad(true);						 	// 서식 로딩 시 첫 페이지만 로딩
        runOption.setUseCaching(false);								// 로컬 파일 생성하여 캐싱 사용 여부
        runOption.setLogLevel(LogLevel.INFO); 						// 로그 레벨
        runOption.setFosLogging(true);								// fos 로그 여부
        runOption.setUseCameraAttachPage(true);                     // 첨지기능 사용여부
        runOption.setExternalControlDefinedPath(ConsentConstants.CONSENT_SERVICE_URL);
        runOption.setParameterDefaultValueClear(false);

        // CLIP e-Form Android 연동 개발자 가이드 setUiStyle 참조
        runOption.setUiStyle("{"
                + "'required-input':{'border':{'visible':'false','color':{'b':0,'g':0,'r':225,'a':120},'width':2},'background':{'visible':'true','color':{'b':0,'g':0,'r':225,'a':120}}}"
                + ",'toast-message':{'signature-missing-data':{'text':'서명이 누락되었습니다.'}}"
                + ",'toolbar':{"
                + "				'buttons':{"
                + "							'tempsave2':{'visible':'false','enabled':'true','text':''}"
                + "							,'record':{'visible':'true'}"
                + "							,'information':{'visible':'true'}"
                + "							,'tempsave':{'visible':'true','enabled':'true','text':'임시저장'}"
                + "							,'save':{'visible':'true','enabled':'true','text':'저장'}"
                + "							,'exit':{'visible':'true','text':'종료'}"
                + "							,'pageattach':{'visible':'true'}"
                + "							,'page-number':{'current':{'text-color':{'b':116,'g':186,'r':14,'a':255}}"
                + "				}"
                + "}"
                + ",'move-next':{"
                + "     'buttons':{"
                + "   		'save-move':{'text':'저장 후 이동','visible':true,'enabled':true}"
                + "    		,'tempsave-move':{'text':'임시저장 후 이동','visible':true,'enabled':true}"
                + "			,'tempsave2-move':{ 'text':'임시저장2 후 이동','visible':false ,'enabled':true}"
                + "    		,'move':{'text':'저장 없이 이동','visible':true ,'enabled':true}"
                + " 	}"
                + "}}}"
        ); // 툴바 및 UI 관련 옵션 설정

        runOption.setInitializeScrollOnPageMove(true);		// 페이지 이동시 스크롤 초기화
        runOption.setAttachPagePosition(Position.Next);		// 첨지 옵션
        runOption.setBottomToolbarButtonsVisibleOnPenDrawMode(true); // 펜드로잉 모드일때 하단 이동 버튼 보이기 여부

        // 저장시 옵션
        runOption.setReturnDataXmlOnSave(true);				// 저장시 dataXml 리턴 여부
        runOption.setDataXmlSaveAsFileOnSave(false);  		// 저장시 dataXml 리턴 시 file 여부(true : file, false : String)

        runOption.setReturnImageOnSave(true);				// 저장시 이미지 파일 리턴 여부
        runOption.setImageSaveOption("{"
                + " 'dpi' 			: 150 "
                + " ,'gray' 		: false "
                + " ,'encode' 		: 'jpg' "
                + " ,'start-index' 	: 0 "
                + " ,'quality' 		: 100 "
                + "}"
        );													// 저장 시 이미지 타입 옵션
        runOption.setReturnTempDocumentOnSave(true);		// 저장 시 ept 파일 저장 여부
        runOption.setIncludesDrawingOnDataXml(false);		// 저장시 펜드로잉 정보 저장 여부
        runOption.setReturnPdfOnSave(false); 				// 저장 시 PDF 저장 여부

        // 임시 저장시 옵션
        runOption.setReturnDataXmlOnTempSave(true);			// 임시 저장시 dataXml 리턴 여부
        runOption.setDataXmlSaveAsFileOnTempSave(false);  	// 임시 저장시 dataXml 리턴 시 file 여부(true : file, false : String)
        runOption.setIncludesDrawingOnTempDocument(true); 	// 임시저장시 펜드로잉 정보 저장 여부

        runOption.setUseNextDocumentOpenDialogAfterSave(false);// 연속 출력시 저장 후 알림 여부
        return runOption;
    }

    /**
     * 동의서 뷰어 시작
     * @param msg
     */
    public void startConsent(ConsentMessage msg) {
        String callbackFunction = msg.getValueMap().get(MPlusFrameworkConstants.MSG_VALUE_KEY.CALLBACK_FN.toString());
        // 핸들러 등록
        this.toolkit.setExitEventHandler(new EFormExitHandler(this.webView, callbackFunction));
        String deviceUUID = MPlusDeviceUtil.getDeviceUUID(this.webView.getContext());
        this.toolkit.setResultEventHandler(new EFormSaveHandler(this.toolkit, msg, deviceUUID));

        // 뷰어 띄우는 옵션 설정
        this.toolkit.setRunOption(this.createRunOption());
        String fos = this.createFOS(msg);
        MPlusLogUtil.DEBUG(this.getClass(), fos);
        // 인증된 사용자인지 확인
        if(SignWrapper.getInstance().isCertificate(msg.getUserId())) {
            toolkit.startEFormViewer(fos);
        } else {
            // 인증서 인증시작
            startCertificate(this.webView.getContext(), this.toolkit, fos, msg.getUserId());
        }
    }

    /**
     * 인증서 인증
     * @param context
     * @param toolkit
     * @param fos
     */
    private void startCertificate(final Context context, final EFormToolkit toolkit, final String fos, final String userId) {
        final EditText passwordEdit = new EditText(context);
        passwordEdit.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
        passwordEdit.setTransformationMethod(PasswordTransformationMethod.getInstance());

        DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                String password = passwordEdit.getText().toString();
                MPlusLogUtil.DEBUG(this.getClass(), "비밀번호 입력 확인:" + password);
                try {
                    // 인증서 인증
                    if(SignWrapper.getInstance().certificate(context, userId, password)) {
                        toolkit.startEFormViewer(fos);
                    } else {
                        MPlusDialog.getOKDialog(context, "인증서 입력-" + userId, "인증서 암호가 올바르지 않습니다.", null).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    MPlusDialog.getOKDialog(context, "인증서 입력-" + userId, e.getMessage(), null).show();
                }
            }
        };


        DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        };

        AlertDialog dialog = MPlusDialog.getPasswordInputDialog(context, "인증서 입력-" + userId, "인증서 암호를 입력하세요", okListener, cancelListener);
        dialog.setView(passwordEdit);
        dialog.show();
    }

    /**
     * 기존 동의서 불러오기
     * @param msg
     */
    public String createFOS(ConsentMessage msg) {
        String fos = "";
        fos += "<fos version='1.0'>";
        fos += "	<global>";
        fos +=          this.createFosPageTemplate();
        fos += "		<parameters>"; // form-list의 모든 서식에 적용될 파라미터
        fos += "            <param key='UrlParam'>" + ConsentConstants.CONSENT_POPUP_URL + "</param>";
        fos +=                 this.createParamString(msg.getParamMap());
        fos += "		</parameters>";
        fos += " 	</global>";
        fos += "	<form-list>";
        fos +=          this.createFormString(msg.getFormParamMapList());
        fos += "	</form-list>";
        fos += "</fos>";
        return fos;
    }

    // 페이지 템플릿
    private String createFosPageTemplate(){
        String pageTemplate = "";
        pageTemplate += "<page-template path='"+ ConsentConstants.CONSENT_SERVICE_URL+"' request-encode ='utf-8' response-encode ='utf-8'>";
        pageTemplate += "	<template-get-parameters>";
        pageTemplate += "		<post-param key='OP'>";
        pageTemplate += "			<![CDATA[PAGE_TEMPLATE]]>";
        pageTemplate += "		</post-param>";
        pageTemplate += "		<post-param key='PD'>";
        pageTemplate += "			<![CDATA[";
        pageTemplate += "				<data>";
        pageTemplate += "					<action>GET_LIST</action>";
        pageTemplate += "					<params>";
        pageTemplate += "						<param name='adaptername'>defaultadapter</param>";
        pageTemplate += "					</params>";
        pageTemplate += "				</data>";
        pageTemplate += "			]]>";
        pageTemplate += "	 	</post-param>";
        pageTemplate += "	</template-get-parameters>";
        pageTemplate += "</page-template>";
        return pageTemplate;
    }

    /**
     * Form 내용 생성
     * @param formMapList
     * @return
     */
    private String createFormString(List<Map<String, String>> formMapList) {
        String fos = "";
        for(int i=0; i<formMapList.size(); i++) {
            Map<String, String> formMap = formMapList.get(i);
            String rid = formMap.get("rid");
            String guid = formMap.get("guid");
            String type = formMap.get("type");
            boolean newForm = true;
            String newConsent = formMap.get("newConsent");
            if(newConsent != null && "true".equals(newConsent)) {
                newForm = true;
            } else {
                newForm = false;
            }
            fos += "		<form name='noname' open-sequence='"+ (i+1) +"' path='" + ConsentConstants.CONSENT_SERVICE_URL+ "' request-encode='utf-8' response-encode='utf-8'>";
            fos += "			<parameters>";
            fos +=                  this.createParamString(formMap);
            fos += "			</parameters>";
            fos += "			<form-get-parameters>";
            fos += "				<post-param key='OP'><![CDATA[" + (newForm ? "VIEWER_FORM" : "VIEWER_DATA") + "]]></post-param>";
            fos += "				<post-param key='PD'>";
            fos += "				<![CDATA[";
            fos += "					<data>";
            fos += "					<action>" + (newForm ? "GET" : "GET_DATA") + "</action>";
            fos += "						<params>";
            fos += "							<param name='adaptername'>defaultadapter</param>";
            if(newForm) {
                fos += "						    <param name='type'>guid</param>";
                fos += "						    <param name='guid'>"+guid+"</param>";
                fos += "						    <param name='version'>-1</param>";
            } else {
                fos += "						    <param name='rid'>"+rid+"</param>";
            }
            fos += "						</params>";
            fos += "					</data>";
            fos += "				]]>";
            fos += "				</post-param>";
            fos += "			</form-get-parameters>";
            fos += "		</form>";
        }
        return fos;
    }

    private String createParamString(Map<String, String> param) {
        StringBuffer paramStr = new StringBuffer();
        if(param != null && !param.isEmpty()) {
            for(String key : param.keySet()) {
                paramStr.append("<param key=\'").append(key).append("\'>");
                paramStr.append("<![CDATA[");
                paramStr.append(MPlusStringUtil.getNull2EmptyString(param.get(key)));
                paramStr.append("]]>");
                paramStr.append("</param>");
            }
        }
        return paramStr.toString();
    }
}