//
//  WebViewControllerSwift.swift
//  MCPlus
//
//  Created by seo ha on 14/02/2019.
//  Copyright © 2019 KangSH. All rights reserved.
//

import Foundation
import UIKit
import WebKit

class WebViewController: UIViewController {
    
    @IBOutlet weak var webView:WKWebView!{
        didSet{
            webView.uiDelegate = self
            webView.navigationDelegate = self
            
            webView.configuration.userContentController.add(self, name: "mCarePlus")
            webView.configuration.suppressesIncrementalRendering = false // 데이터를 모두 받아야만 화면이 보여지게 하는 옵션
            
            var scriptContent = "var meta = document.createElement('meta');"
            scriptContent += "meta.name='viewport';"
            scriptContent += "meta.content='width=device-width';"
            scriptContent += "document.getElementsByTagName('head')[0].appendChild(meta);"
            
            webView.evaluateJavaScript(scriptContent, completionHandler: nil)
            webView.evaluateJavaScript("navigator.userAgent") { [weak webView](result, error) in
                if let userAgent = result as? String{
                    webView?.customUserAgent = userAgent.appending("/mCarePlus")
                }
            }
            
            guard let url = URL(string: urlString) else {
                return
            }
            
            let request = URLRequest(url: url)
            webView.load(request)
            webView.isUserInteractionEnabled = true
            webView.scrollView.bounces = false
            webView.scrollView.isScrollEnabled = true
            
            
        }
    }
    
    var rememberme:String?
    let urlString = "\(MCarePlusConstants.DOMAIN_NAME)\(MCarePlusConstants.APP_NAME)\(Constants.SERVICE_START_ADDR)"
    
}

extension WebViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.navigationController?.navigationBar.isHidden = true
        //    status bar 폰트 흰색으로, plist 파일에 View controller-based status bar appearance : NO를 추가해야함
        self.setStatusBarBackgroundColor(color: .white)
        
        
        let targetName = Bundle.main.infoDictionary?["TargetName"] as? String ?? ""
        print("\n ####### target name:\(targetName) ####### \n")
        
        self.showStatusBarInfo()
        self.orderFileDelete()
        
        webView.frame = self.view.frame
        
        Notification.registerNotification(name:  UIApplication.userDidTakeScreenshotNotification, object: nil, queue: OperationQueue.main) { [weak self](notification) in
            self?.webView.evaluateJavaScript("window.activeObj.inputLoginLog('')", completionHandler: nil)
            
            let alert = UIAlertController(title: "", message: "개인정보보호를 준수해주세요. \n캡쳐행위는 모니터링 될 수 있습니다.", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "확인", style: .default, handler: nil))
            
            self?.present(alert, animated: true, completion: nil)
        }
    }
    
    func showStatusBarInfo(){
        let statusBar = UIApplication.shared.statusBarFrame
        print("Status Bar : \(statusBar)")
    }
    
    func orderFileDelete(){
        let fileManager = FileManager.default
        let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
        let documentsURL = urls.first
        //원본파일
        guard let origin = documentsURL?.appendingPathComponent("kunkuk") else{ return }
        //썸네일
        guard let thumb = documentsURL?.appendingPathComponent("thumb") else{ return }
    
        //원본 하위 파일을 가져온다
        do{
            let files = try fileManager.contentsOfDirectory(at: origin, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
            
            for file in files{
                //이름 추출
                let name = file.lastPathComponent
                //일시 추출
                let date = String(name[7...14])
                
                //현재날짜와 파일의 일시를 date형식으로 추출
                let currentDate = Date()
                guard let fileDate = date.fromDate(format: "yyyyMMddhhmmss") else{ continue }
                
                //파일 날짜에 1month를 더한다
                var dateComponents = DateComponents()
                dateComponents.month = 1
                let calendar = Calendar.current
                guard let toMonth = calendar.date(byAdding: dateComponents, to: fileDate) else{ continue }
                
                //생성일이 한 달 된 파일일 경우 원본과 썸네일을 삭제한다
                if toMonth < currentDate{
                    let originPath = origin.appendingPathComponent("/").appendingPathComponent(name)
                    let thumbPath = thumb.appendingPathComponent("/").appendingPathComponent(name)
                    do{
                        try fileManager.removeItem(at: originPath)
                        try fileManager.removeItem(at: thumbPath)
                    }catch{
                        print(error)
                        continue
                    }
                }
            }
        }catch{
            print(error)
            return
        }
        
        
    }
    
    func degreesToRadians(_ x:Double) -> CGFloat {
        return CGFloat(M_PI * (x) / 180.0)
    }
    
    func setStatusBarBackgroundColor(color:UIColor){
        guard let statusBarView = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else {
            return
        }
        statusBarView.backgroundColor = color
        
    }
    
    func exitApp(){
        exit(0)
    }
    
    func lockscreen(){
        let lockOptionVC = LockOptionViewViewController()
        self.present(lockOptionVC, animated: true, completion: nil)
    }
    
    func makeUrlStringForPACS(queryDic:[String:Any]) -> String? {
        do{
            let pacsObject = try JSONDecoder().decode(PACS.self, from: queryDic.json())
            let urlString = "\(Constants.PACS_APP_SCHEME)//searchstudy?"
            var reduceArray = [String]()
            
            if let serverUrl = pacsObject.serverUrl{
                reduceArray.append("serverurl=\(serverUrl)")
            }
            
            if let userId = pacsObject.userId{
                reduceArray.append("&id=\(userId)")
            }
            
            if let userPw = pacsObject.userPw{
                reduceArray.append("&pw=\(userPw)")
            }
            
            if let product = pacsObject.product{
                reduceArray.append("&product=\(product)")
            }
            
            if let pId = pacsObject.pId{
                reduceArray.append("&pid=\(pId)")
            }
            
            if let accno = pacsObject.accno{
                reduceArray.append("&accno=\(accno)")
            }
            
            if let type = pacsObject.type{
                reduceArray.append("&type=\(type)")
            }
            
            if let studyInstanceUid = pacsObject.studyInstanceUid{
                reduceArray.append("&study_instance_uid=\(studyInstanceUid)")
            }
            
            return reduceArray.reduce(urlString, {"\($0)\($1)"})
        }catch{
            print(error)
            return nil
        }

    }
    
    
}

//MARK: - < toNative functions >
extension WebViewController{
    func callPacs(param:String){
        print("tonative param=[\(param)]")
        
        var queryStringDictionary = [String:Any]()
        let urlComponents = param.components(separatedBy: "&")
        
        for keyValuePair in urlComponents{
            let pairComponents = keyValuePair.components(separatedBy: "=")
            let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
            let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
            
            queryStringDictionary[key] = value
        }
        
        print("parameter dictionary is \(queryStringDictionary)")
        
        guard let pameteredURL = self.makeUrlStringForPACS(queryDic: queryStringDictionary)else{ return }
        print("url address to PACS =[\(pameteredURL)]")
        
        guard let url = URL(string: pameteredURL) else{ return }
        
        // PACS 앱 다운로드 사이트 유도
        // iPhone 5     9.3.3(13G34) 테스트 완료
        // iPhone 5s   10.2.0(14C92) 테스트 완료
        
        if #available(iOS 10.0, *){
            let options = [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly : false] // 유니버셜링크만 열도록 하는 옵션
            UIApplication.shared.open(url, options: options) { [weak self](success) in
                if success{
                    print("true = \(success)")
                }else{
                    print("false = \(success)")
                    guard let url = URL(string: Constants.PACS_APP_DOWNLOAD_ADDR) else { return }
                    UIApplication.shared.open(url, options: options, completionHandler: { (success) in
                        //앱 설치 유도
                        if success{
                            print("앱스토어로 제대로 보내줌.")
                        }else{
                            self?.showAlert("", "인터넷연결을 확인하세요", "확인")
                        }
                    })
                }
            }
        }else{
            let PACSInstallYn = UIApplication.shared.canOpenURL(url)
            if PACSInstallYn{
                UIApplication.shared.open(url)
            }else{
                guard let url = URL(string: Constants.PACS_APP_DOWNLOAD_ADDR) else { return }
                UIApplication.shared.open(url)
            }
        }
        
    }
    
    func rotateScreen(param:String){
        var queryStringDictionary = [String:Any]()
        let urlComponents = param.components(separatedBy: "&")
        
        for keyValuePair in urlComponents{
            let pairComponents = keyValuePair.components(separatedBy: "=")
            let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
            let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
            
            queryStringDictionary[key] = value
        }
        
        print("parameter dictionary is \(queryStringDictionary)")
        
        let orientation = queryStringDictionary["orientation"] as? String ?? ""
        
        let screenRect = UIScreen.main.bounds
        let screenWidth = screenRect.size.width
        let screenHeight = screenRect.size.height
        
        //    NSNumber * value;
        if orientation == "landscape"{
            UIApplication.shared.statusBarOrientation = .landscapeRight
            UIApplication.shared.isStatusBarHidden = true
            let transform:CGAffineTransform = CGAffineTransform(rotationAngle: degreesToRadians(90))
            self.view.transform = transform
            self.view.frame = CGRect(x: 0, y: 0, width: screenHeight, height: screenWidth)
        }else{
            UIApplication.shared.statusBarOrientation = .portrait
            UIApplication.shared.isStatusBarHidden = false
            let transform:CGAffineTransform = CGAffineTransform(rotationAngle: degreesToRadians(0))
            self.view.transform = transform
            self.view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)
        }
        
    }
    
    // 팝업 브라우징
    func popup(param:String){
        var queryStringDictionary = [String:Any]()
        let urlComponents = param.components(separatedBy: "url=")
        
        queryStringDictionary["url"] = urlComponents[safe:1] ?? ""
        
        let storyboard = self.storyboard
        let VC = storyboard?.instantiateViewController(withIdentifier: "ExtraWebViewController") as! ExtraWebViewController
        
        if let url = queryStringDictionary["url"] as? String{
            VC.url = url
        }
        
        self.present(VC, animated: true, completion: nil)
        
    }
    
    func getDeviceInfo(param:String){
        var queryStringDictionary = [String:Any]()
        let urlComponents = param.components(separatedBy:  "&")
        
        for keyValuePair in urlComponents{
            let pairComponents = keyValuePair.components(separatedBy: "=")
            let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
            let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
            
            queryStringDictionary[key] = value
        }
        
        print("parameter dictionary is \(queryStringDictionary)")
        
        let dic = NSMutableDictionary()
        let uuid = UIDevice.current.identifierForVendor?.uuidString ?? ""
        let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
        
        var sysinfo = utsname()
        uname(&sysinfo) // ignore return value
        let phoneKind = NSString(bytes: &sysinfo.machine, length: Int(_SYS_NAMELEN), encoding: String.Encoding.utf8.rawValue)! as String
        
        dic["deviceId"] = uuid
        dic["appVersion"] = version
        dic["appKind"] = "IOS"
        dic["phoneKind"] = phoneKind
        
        let callback = CallbackUtil()
        let callbackFunc = queryStringDictionary["callbackFn"] as? String ?? ""
        let callbackUrl = callback.callBackFunc(callbackFunc, withDic: dic)
        
        self.webView.evaluateJavaScript(callbackUrl, completionHandler: nil)

    }
    
    func readBarcode(param:String){
        let storyboard = self.storyboard
        let VC = storyboard?.instantiateViewController(withIdentifier: "BarcodeViewController") as! BarcodeViewController
        
        //바코드 콜백
        VC.callBack = { [weak self](barcode) in
            print("doCompletionHandler \(barcode)")
            var queryStringDictionary = [String:Any]()
            let urlComponents = param.components(separatedBy: "&")
            
            for keyValuePair in urlComponents{
                let pairComponents = keyValuePair.components(separatedBy: "=")
                let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
                let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
                
                queryStringDictionary[key] = value
            }
            
//            print("parameter dictionary is\n\(queryStringDictionary)")
//            let dic = NSMutableDictionary()
//            if barcode == ""{
//                dic["success"] = "fail"
//                dic["result"] = "barcode is null"
//            }else{
//                dic["success"] = "true"
//                dic["result"] = barcode
//            }
            
//            let callback = CallbackUtil()
            let callbackFunc = queryStringDictionary["callbackFn"] as? String ?? ""
//            let callbackUrl = callback.callBackFunc(callbackFunc, withDic: NSMutableDictionary())
            let callbackUrl = "\(callbackFunc)({\"success\":\"true\",\"result\":\"\(barcode)\"})"
            self?.webView?.evaluateJavaScript(callbackUrl, completionHandler: nil)
        }
        
        self.navigationController?.pushViewController(VC, animated: false)
        
    }
    
    func readQrcode(param:String){
        let storyboard = self.storyboard
        let VC = storyboard?.instantiateViewController(withIdentifier: "BarcodeViewController") as! BarcodeViewController
        
        //qr코드 콜백
        VC.callBack = { [weak self](qrcode) in
            print("doCompletionHandler \(qrcode)")
            var queryStringDictionary = [String:Any]()
            let urlComponents = param.components(separatedBy: "&")
            
            for keyValuePair in urlComponents{
                let pairComponents = keyValuePair.components(separatedBy: "=")
                let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
                let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
                
                queryStringDictionary[key] = value
            }
            
//            print("parameter dictionary is\n\(queryStringDictionary)")
//            let dic = NSMutableDictionary()
//            if qrcode == ""{
//                dic["success"] = "fail"
//                dic["result"] = "qrcode is null"
//            }else{
//                dic["success"] = "true"
//                dic["result"] = qrcode
//            }
//
//            let callback = CallbackUtil()
            let callbackFunc = queryStringDictionary["callbackFn"] as? String ?? ""
//            let callbackUrl = callback.callBackFunc(callbackFunc, withDic: dic)
            let callbackUrl = "\(callbackFunc)({\"success\":\"true\",\"result\":\"\(qrcode)\"})"
            self?.webView.evaluateJavaScript(callbackUrl, completionHandler: nil)
        }
        
        
        self.navigationController?.pushViewController(VC, animated: false)
    }
    
    func readPicture(param:String){
        let storyboard = self.storyboard
        let VC = storyboard?.instantiateViewController(withIdentifier: "PictureViewController") as! PictureViewController
        
        let splited = param.split(separator: "&")
        var params = [String:String]()
        for p in splited{
            let pair = p.split(separator: "=")
            let k = String(pair[safe:0] ?? "")
            let v = String(pair[safe:1] ?? "").removingPercentEncoding
            params[k] = v
        }
        
        let user = User.init()
        do{
            user.hospitalCD = params["hospitalCD"]
            user.patientId = params["patientId"]
            user.userId = params["userId"]
            user.patientNm = params["patientNm"]
            user.age = params["age"]
            user.gender = params["gender"]
            user.deptCd = params["deptCd"]
            user.deptNm = params["deptNm"]
            user.doctorId = params["doctorId"]
            user.doctorNm = params["doctorNm"]
            user.treatCls = params["treatCls"]
            user.treatClsKr = params["treatClsKr"]
            user.serviceUrl = params["serviceUrl"]
            user.visitDt = params["visitDt"]
        }
        
        VC.user = user
        VC.callBack = { [weak self] (result) in
            var queryStringDictionary = [String:Any]()
            let urlComponents = param.components(separatedBy: "&")
            
            for keyValuePair in urlComponents{
                let pairComponents = keyValuePair.components(separatedBy: "=")
                let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
                let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
                
                queryStringDictionary[key] = value
            }
            
            print("parameter dictionary is\n\(queryStringDictionary)")
            let dic = NSMutableDictionary()
            dic["success"] = "true"
            dic["result"] = result
            
            let callback = CallbackUtil()
            let callbackFunc = queryStringDictionary["callbackFn"] as? String ?? ""
            let callbackUrl = callback.callBackFunc(callbackFunc, withDic: dic)
            
            self?.webView.evaluateJavaScript(callbackUrl, completionHandler: nil)
        }
        

        self.navigationController?.pushViewController(VC, animated: false)
    }
    
    func showBrowsingUrl(param:String) {
        var queryStringDictionary = [String:Any]()
        let urlComponents = param.components(separatedBy: "&")
        
        for keyValuePair in urlComponents{
            let pairComponents = keyValuePair.components(separatedBy: "=")
            let key = pairComponents[safe: 0]?.removingPercentEncoding ?? ""
            let value = pairComponents[safe: 1]?.removingPercentEncoding ?? ""
            
            queryStringDictionary[key] = value
        }
        
        guard let urlString = queryStringDictionary["url"] as? String,
            let url = URL(string: urlString) else {
            return
        }
        self.webView.load(URLRequest(url: url))
    }
}


extension WebViewController:WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler{
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping ((WKNavigationActionPolicy) -> Void)) {
        
        let request = navigationAction.request
        print(request)
        guard let url = request.url else {
            return
        }
        
        let absoluteString = url.absoluteString
        
        switch absoluteString {
            
        case let variable where variable.hasPrefix("sms:"):
            fallthrough
            //메일
        case let variable where variable.hasPrefix("mailto:"):
            fallthrough
            //전화
        case let variable where variable.hasPrefix("tel:"):
            fallthrough
            //아이튠즈
        case let variable where variable.hasPrefix("https://itunes.apple.com/"):
            fallthrough
            //스토리링크
        case let variable where variable.hasPrefix("storylink://"):
            UIApplication.shared.open(url)
            decisionHandler(.cancel)
            //일반 웹호출
        case let variable where variable.hasPrefix("http://"):
            fallthrough
        case let variable where variable.hasPrefix("https://"):
            decisionHandler(.allow)
        //url scheme은 중간에 대문자가 들어가도 소문자로 변환됨.. 근데 이게 안될때도 있고 그러하다. 따라서 웹에서는 계속 소문자로만 보내도록 약속.
        case let variable where variable.hasPrefix("tonative://"):
            let components = variable.components(separatedBy: "?")
            let functionName = components.first?[11...] ?? ""
            var parameters = components[safe: 1] ?? ""
            if components.count > 2{
                var addParam = [String]()
                
                for i in 2..<components.count{
                    addParam.append("?")
                    addParam.append(components[safe: i] ?? "")
                }
                print("addParam [\(addParam)]")
                parameters.append(contentsOf: addParam.reduce("", {"\($0)\($1)"}))
            }
            
            print("functionName =[\(functionName)], parameter = [\(parameters)]")
            
            switch functionName{
            case "callPacs", "callpacs", "call_pacs":
                callPacs(param: parameters)
            case "rotateScreen", "rotatescreen", "rotate_screen":
                rotateScreen(param: parameters)
            case "popUp", "popup":
                popup(param: parameters)
            case "getDeviceInfo", "getdeviceinfo", "get_device_info":
                getDeviceInfo(param: parameters)
            case "readBarcode", "readbarcode", "read_barcode":
                readBarcode(param: parameters)
            case "readQrcode", "readqrcode", "read_qrcode":
                readQrcode(param: parameters)
            case "readPicture", "readpicture", "read_picture":
                readPicture(param: parameters)
            case "exitApp":
                self.exitApp()
            case "lockscreen":
                self.lockscreen()
            case "showBrowsingUrl":
                self.showBrowsingUrl(param: parameters)
            default:
                break
            }
            
            decisionHandler(.cancel)
        default:
            decisionHandler(.cancel)
        }
    
        
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        if let urlResponse = navigationResponse.response as? HTTPURLResponse,
            let url = urlResponse.url,
            let allHeaderFields = urlResponse.allHeaderFields as? [String : String] {
            let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHeaderFields, for: url)
            HTTPCookieStorage.shared.setCookies(cookies , for: url, mainDocumentURL: nil)
            decisionHandler(.allow)
        }
    }
    
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping () -> Void) {
        
        self.showAlert("", message, "확인", nil, { (action) in
            completionHandler()
        })
    }
    
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping (Bool) -> Void) {
        
        self.showAlert("", message, "확인", "취소", { (action) in
            completionHandler(true)
        },{ (action) in
            completionHandler(false)
        })
    }
    
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping (String?) -> Void) {
        
        let alertController = UIAlertController(title: "", message: prompt, preferredStyle: .alert)
        alertController.addTextField { (textField) in
            textField.text = defaultText
        }
        alertController.addAction(UIAlertAction(title: "확인", style: .default, handler: { (action) in
            if let text = alertController.textFields?.first?.text {
                completionHandler(text)
            } else {
                completionHandler(defaultText)
            }
        }))
        
        alertController.addAction(UIAlertAction(title: "취소", style: .default, handler: { (action) in
            completionHandler(nil)
        }))
        
        self.present(alertController, animated: true, completion: nil)
    }
    
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        let userController = WKUserContentController()
        
        configuration.preferences.javaScriptCanOpenWindowsAutomatically = true
        configuration.userContentController = userController
        
        let newWebView:WKWebView = {
            let webView = WKWebView(frame: webView.frame, configuration: configuration)
            webView.uiDelegate = self
            webView.navigationDelegate = self
            webView.frame.origin.y = 0
            webView.configuration.userContentController.add(self, name: "mCarePlus")
            webView.evaluateJavaScript("navigator.userAgent") { [weak webView](result, error) in
                if let userAgent = result as? String{
                    webView?.customUserAgent = userAgent.appending("/mCarePlus")
                }
            }
            
            return webView
        }()
        
        let button:UIButton = {
            let button = UIButton(type: .system)
            button.isHidden = true
            button.frame = CGRect(x:(webView.frame.size.width) - 30, y:0, width: 30, height: 30)
            button.backgroundColor = UIColor.black
            button.layer.cornerRadius = 15
            button.setTitle("X", for: .normal)
            button.addTapGestureRecognizer(action: deleteSubWebView)
            return button
        }()
        
        webView.addSubview(newWebView)
        webView.addSubview(button)
        
        return newWebView
    }
    
    func deleteSubWebView(){
        for view in webView.subviews{
            view.removeFromSuperview()
        }
    }
    
    func webViewDidClose(_ webView: WKWebView) {
        for view in webView.subviews{
            view.removeFromSuperview()
        }
        webView.removeFromSuperview()
    }
    
    public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        // 중복적으로 리로드가 일어나지 않도록 처리 필요.
        webView.reload()
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
    }
}
