package com.lemonhc.mplus.mcare_plus.activity.webView

import android.app.AlertDialog
import android.content.ComponentName
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.text.InputType
import android.text.method.PasswordTransformationMethod
import android.util.Log
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.webkit.WebView
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import com.google.gson.Gson
import com.google.gson.stream.JsonReader
import com.lemonhc.mplus.MPlusConstants.PACS_CLASS_NAME
import com.lemonhc.mplus.MPlusConstants.PACS_PACKAGE_NAME
import com.lemonhc.mplus.MPlusConstants.PACS_SERVER_URL
import com.lemonhc.mplus.MPlusConstants.USE_LOCK_SCREEN
import com.lemonhc.mplus.Sign.SignWrapper
import com.lemonhc.mplus.classes.PACSObject
import com.lemonhc.mplus.framework.constant.FrameworkConstant
import com.lemonhc.mplus.mcare_plus.R
import com.lemonhc.mplus.mcare_plus.activity.BarcodeActivity
import com.lemonhc.mplus.mcare_plus.activity.MPlusPopupActivity
import com.lemonhc.mplus.mcare_plus.activity.MainActivity.Companion.checkInstallPACS
import com.lemonhc.mplus.mcare_plus.activity.PhotoActivity
import com.lemonhc.mplus.mcare_plus.activity.Util.Util
import com.lemonhc.mplus.mcare_plus.activity.lockScreen.LockOptionActivity
import com.lemonhc.mplus.model.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.json.JSONObject
import java.io.StringReader
import java.util.concurrent.Executors

/**
 * 웹뷰에서 호출한 functionType 명으로 함수를 호출하기 위한 클래스.
 */
class WebViewCallFunctions(val activity: AppCompatActivity, val webView: WebView) {
  var functionName: String? = null
  var param: Map<String, Any>? = null
  
  
  fun exitApp() {
    activity.moveTaskToBack(true)
    activity.finish()
    android.os.Process.killProcess(android.os.Process.myPid())
  }
  
  fun callPacs() {
    if (checkInstallPACS(activity, PACS_PACKAGE_NAME)) {
      // 암호에 슬래쉬가 들어가서..  JSONObject사용하였음, 밸류에 슬래쉬"/"가 들어있는 경우 json string으로 변환이 필요하다.
      // 그냥 param.toString()으로 Gson으로 넘기면 파싱하다 에러난다.
      val jsonObject = JSONObject(this.param)
      
      var pacsObject = PACSObject()
      val gson = Gson()
      val reader = JsonReader(StringReader(jsonObject.toString()))
      reader.isLenient = true
      pacsObject = gson.fromJson(reader, PACSObject::class.java)
      
      val intent = Intent()
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
      intent.component = ComponentName(PACS_PACKAGE_NAME, PACS_CLASS_NAME)
      
      val url = pacsObject.returnurl
      val isEmpty: Boolean = pacsObject.returnurl.isNullOrEmpty()
      Log.e("!!!!", "url -- > $url, isEmpty -- > $isEmpty")
      
//    intent.putExtra("ServerUrl", url)
      if (!pacsObject.returnurl.isNullOrEmpty()) {
        intent.putExtra("ServerUrl", pacsObject.returnurl)
      }
      
      if (!pacsObject.user_id.isNullOrEmpty()) {
        intent.putExtra("UserID", pacsObject.user_id)
      }
      
      if (!pacsObject.user_pw.isNullOrEmpty()) {
        intent.putExtra("UserPassword", pacsObject.user_pw)
      }
      
      if (!pacsObject.type.isNullOrEmpty()) {
        pacsObject.callType = FrameworkConstant.pacsType.getEnum(pacsObject.type)
      }
      
      intent.putExtra("CallType", pacsObject.callType.getTypeName())
      
      //선택 파라미터.
      if (!pacsObject.pid.isNullOrEmpty()) {
        intent.putExtra("PatientID", pacsObject.pid)
      }
      
      if (!pacsObject.accno.isNullOrEmpty()) {
        intent.putExtra("AccessionNo", pacsObject.accno)
      }
      
      if (!pacsObject.study_start_date.isNullOrEmpty()) {
        intent.putExtra("StudyStartDate", pacsObject.study_start_date)
      }
      
      if (!pacsObject.study_end_date.isNullOrEmpty()) {
        intent.putExtra("StudyEndDate", pacsObject.study_end_date)
      }
      
      intent.extras.apply {
        val keys = keySet()
        val it = keys.iterator()
        
        while (it.hasNext()) {
          val key = it.next()
        }
        
      }
      activity.startActivity(intent)
    } else {
      // 설치페이지로 보냄
      val intent = Intent(Intent.ACTION_VIEW)
      intent.data = Uri.parse("market://details?id=$PACS_PACKAGE_NAME")
      activity.startActivity(intent)
    }
  }
  
  /**
   * Acting Button Click Event
   * Native : Xml Data Signing to Javascript Callback
   * param -- > type, functionType, value
   * param[value] -- > userId, xmlData, callbackFunction
   */
  fun certDataToNative() {
    val param = param ?: return
    val functionName = param["callbackFn"].toString()
    val json = JSONObject()
    var result: String? = null
    
    var userId: String = param["userId"].toString() //
    var xmlData: String = param["xmlData"].toString() // XML 데이터가 여러개인 경우 구분자를 통한 하나의 스트링으로 받아서 split
    var xmlArray = xmlData.split("|%POC%|")

//        var certFlag = SignWrapper.getInstance().isCertificate("96070") // 인증서를 가지고 와서 인증된 데이터인지 확인
    var certFlag = SignWrapper.getInstance().isCertificate(userId) // 실제 사용하는 변수
    
    // 액팅버튼 클릭 -- > certFlag가 false면 인증비밀번호를 입력받기 위해 alert에 EditText를 추가
    val passwordEdit: EditText = EditText(activity)
    passwordEdit.setRawInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT)
    passwordEdit.transformationMethod = PasswordTransformationMethod.getInstance()
    Util.setCursorColor(passwordEdit, R.color.black_overlay)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      passwordEdit.setTextColor(activity.getColor(R.color.black))
    }
    val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    
    /**
     * 인증비밀번호 입력 및 인증
     */
    val thread = Thread(Runnable {
      Handler(Looper.getMainLooper()).post {
        if (!certFlag) {
          var okListener: DialogInterface.OnClickListener = DialogInterface.OnClickListener { dialog, which ->
            val certPw: String = passwordEdit.text.toString()
            try {
              if (SignWrapper.getInstance().certificate(activity, userId, certPw)) {
                for ((index, value) in xmlArray.withIndex()) {
                  try {
                    result = SignWrapper.getInstance().signData(userId, value)
                    json.put("success", "0000")
                    json.put("index", index.toString())
                  } catch (e: Exception) {
                    e.printStackTrace()
                    Util.getOKDialog(activity, activity.getString(R.string.emptyCertPw), activity.getString(R.string.certAuthFail), null).show()
                  }
                  val callback = "javascript:$functionName('$json', '$result', '$value')"
                  Util.LOG(webView.javaClass, "result -- > $result")
                  webView.post(Runnable { webView.loadUrl(callback) })
                }
              } else {
                Util.getOKDialog(activity, activity.getString(R.string.emptyCertPw), activity.getString(R.string.certAuthFail), null).show()
              }
            } catch (e: Exception) {
              e.printStackTrace()
              Util.getOKDialog(activity, activity.getString(R.string.emptyCertPw), activity.getString(R.string.certAuthFail), null).show()
            }
          }
          var dismissListener: DialogInterface.OnClickListener = DialogInterface.OnClickListener { dialog, which ->
            imm.hideSoftInputFromWindow(passwordEdit.windowToken, 0)
          }
          val dialog: AlertDialog = Util.getPasswordInputDialog(activity, activity.getString(R.string.emptyCertPw), activity.getString(R.string.certAuthFail), okListener, dismissListener)
          dialog.setView(passwordEdit)
          dialog.show()
        } else {
          for ((index, value) in xmlArray.withIndex()) {
            try {
              result = SignWrapper.getInstance().signData(userId, value)
              json.put("success", "0000")
              json.put("index", index.toString())
            } catch (e: Exception) {
              e.printStackTrace()
              Util.getOKDialog(activity, activity.getString(R.string.emptyCertPw), activity.getString(R.string.certAuthFail), null).show()
            }
            val callback = "javascript:$functionName('$json', '$result', '$value')"
            Util.LOG(webView.javaClass, "result -- > $result")
            webView.post(Runnable { webView.loadUrl(callback) })
          }
        }
      }
    })
    thread.start()
  }
  
  fun lockscreen() {
    if (USE_LOCK_SCREEN == false) {
      return
    }
    
    val intent = Intent(activity, LockOptionActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
    intent.putExtra("lock_yn", false)
    activity.startActivity(intent)
  }
  
  fun popup() {
    val param = param ?: return
    val url = param["url"] as String
    
    val intent = Intent(activity, MPlusPopupActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
    
    intent.putExtra("Url", url)
    activity.startActivityForResult(intent, 0)
  }
  
  fun getDeviceInfo() {
    val param = param ?: return
    val functionName = param["callbackFn"].toString()
    val json = JSONObject()
    val params = JSONObject()
    try {
      val pkgInfo = activity.packageManager.getPackageInfo(activity.packageName, 0)
      params.put("deviceId", Settings.Secure.getString(activity.contentResolver, Settings.Secure.ANDROID_ID))
      params.put("appVersion", pkgInfo.versionCode.toString())
      params.put("appKind", "android")
      params.put("phoneKind", "${Build.MANUFACTURER}, ${Build.MODEL}")
      params.put("osVersion", "${android.os.Build.VERSION.RELEASE}")
      
      json.put("success", "true")
      json.put("result", params)
    } catch (e: Exception) {
      e.printStackTrace()
    }
    
    val callback = "javascript:$functionName('$json')"
    
    webView.post(Runnable { webView.loadUrl(callback) })
  }
  
  fun readBarcode() {
    BarcodeActivity.callBack = fun(s: String?): Unit {
      val param = param ?: return
      val functionName = param["callbackFn"].toString()
      val json = JSONObject()
      try {
        json.put("success", "true")
        json.put("result", s)
      } catch (e: Exception) {
        e.printStackTrace()
      }
      val callback = "javascript:$functionName('$json')"
      Log.e("MPLUS", "READ BARCODE SCAN CALLBACK - $callback")
      webView.post { webView.loadUrl(callback) }
    }
    val intent = Intent(activity, BarcodeActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
    activity.startActivity(intent)
  }
  
  fun readQrcode() {
    BarcodeActivity.callBack = fun(s: String?): Unit {
      val param = param ?: return
      val functionName = param["callbackFn"].toString()
      val json = JSONObject()
      try {
        json.put("success", "true")
        json.put("result", s)
      } catch (e: Exception) {
        e.printStackTrace()
      }
      
      val callback = "javascript:" + functionName + "('" + json.toString() + "')"
      webView.post(Runnable { webView.loadUrl(callback) })
    }
    val intent = Intent(activity, BarcodeActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
    activity.startActivity(intent)
  }
  
  fun readPicture() {
    PhotoActivity.callBack = fun(successOrFail: JSONObject): Unit {
      val param = param ?: return
      val functionName = param["callbackFn"].toString()
      val json = JSONObject()
      try {
        json.put("success", "true")
        json.put("result", successOrFail)
      } catch (e: Exception) {
        e.printStackTrace()
      }
      
      val callback = "javascript:" + functionName + "('" + json.toString() + "')"
      webView.post(Runnable { webView.loadUrl(callback) })
    }
    
    kotlin.run {
      val param = param ?: return
      val gson = Gson()
      val json = gson.toJson(param)
      PhotoActivity.user = gson.fromJson(json, User::class.java)
    }
    
    val intent = Intent(activity, PhotoActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
    activity.startActivity(intent)
  }
  
  fun showBrowsingUrl() {
    val param = param ?: return
    val url = param["url"] as String
//        val intent = Intent(activity, MPlusPopupActivity::class.java)
//        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
//        intent.putExtra("Url", url)
//        activity.startActivityForResult(intent, 0)
    
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
    activity.startActivity(intent)
    
  }
  
  fun appCheck() {
    val param = param ?: return
    val url = param["target"] as String
    
    val packageInfoList = activity.packageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES)
    val s = packageInfoList.asSequence().filter { it?.packageName == url }.any()
    
    val functionName = param["callbackFn"].toString()
    val json = JSONObject()
    try {
      json.put("success", s)
    } catch (e: Exception) {
      e.printStackTrace()
    }
    
    
    val callback = "javascript:" + functionName + "('" + json.toString() + "')"
    webView.post(Runnable { webView.loadUrl(callback) })
    
  }
  
  fun appInstall() {
    val param = param ?: return
    val url = param["target"] as String
    
    try {
      activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("$url")))
    } catch (exception: android.content.ActivityNotFoundException) {
      activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$url")))
    }
  }
  
  fun openApp() {
    val param = param ?: return
    val url = param["target"] as String
    // Get an instance of PackageManager
    val pm = activity.packageManager
    
    // Initialize a new Intent
    val intent: Intent? = pm.getLaunchIntentForPackage(url)
    
    // Add category to intent
    intent?.addCategory(Intent.CATEGORY_LAUNCHER)
    
    // If intent is not null then launch the app
    if (intent != null) {
      activity.startActivity(intent)
      
    }
  }
}