//
//  NCViewerDocumentWeb.swift
//  Nextcloud
//
//  Created by Marino Faggiana on 28/09/2018.
//  Copyright © 2018 Marino Faggiana. All rights reserved.
//
//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

import Foundation
import WebKit

class NCViewerDocumentWeb: NSObject {
    
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    var safeAreaBottom: Int = 0
    var mimeType: String?
    
    @objc static let sharedInstance: NCViewerDocumentWeb = {
        let instance = NCViewerDocumentWeb()
        return instance
    }()
    
    @objc func viewDocumentWebAt(_ metadata: tableMetadata, view: UIView) {
        
        if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { return }
        
        if #available(iOS 11.0, *) {
            safeAreaBottom = Int((UIApplication.shared.keyWindow?.safeAreaInsets.bottom)!)
        }
        
        let fileNamePath = NSTemporaryDirectory() + metadata.fileNameView
        let fileNameExtension = (metadata.fileNameView as NSString).pathExtension.uppercased()

        CCUtility.copyFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView), toPath: fileNamePath)
        
        let url = URL.init(fileURLWithPath: fileNamePath)

        let preferences = WKPreferences()
        let configuration = WKWebViewConfiguration()

        preferences.javaScriptEnabled = false

        // Detect file xls, xlss for enable javascript
        if fileNameExtension == "XLS" || fileNameExtension == "XLSX" {
            if let fileHandle = FileHandle(forReadingAtPath: fileNamePath) {
                let data = fileHandle.readData(ofLength: 4)
                if data.starts(with: [0x50, 0x4b, 0x03, 0x04]) { // "PK\003\004"
                    preferences.javaScriptEnabled = true
                }
                fileHandle.closeFile()
            }
        }
        
        configuration.preferences = preferences
        
        let webView = WKWebView(frame: view.frame)
        webView.navigationDelegate = self
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        webView.backgroundColor = .white
        
        webView.isOpaque = false
        
        if fileNameExtension == "CSS" || fileNameExtension == "PY" || fileNameExtension == "XML" || fileNameExtension == "JS" {
            
            do {
                let dataFile = try String(contentsOf: url, encoding: String.Encoding(rawValue: String.Encoding.ascii.rawValue))
                
                if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.phone {
                    webView.loadHTMLString("<div style='font-size:40;font-family:Sans-Serif;'><pre>" + dataFile, baseURL: nil)
                } else {
                    webView.loadHTMLString("<div style='font-size:20;font-family:Sans-Serif;'><pre>" + dataFile, baseURL: nil)
                }
                
            } catch {
                print("error")
            }
            
        } else if CCUtility.isDocumentModifiableExtension(fileNameExtension) {
            
            let session = URLSession(configuration: URLSessionConfiguration.default)
            var request = URLRequest(url: url)
            request.httpMethod = "HEAD"
            
            let task = session.dataTask(with: request) { (data, response, error) in
                
                guard let data = data else {
                    return
                }
                guard let response = response else {
                    return
                }
                
                DispatchQueue.main.async {
                    
                    guard let encodingName = NCUchardet.sharedNUCharDet()?.encodingStringDetect(with: data) else {
                        return
                    }
                    self.mimeType = response.mimeType
                    webView.load(data, mimeType: response.mimeType!, characterEncodingName: encodingName, baseURL: url)
                }
            }
            
            task.resume()
            
        } else {
            
            webView.load(URLRequest(url: url))
        }
        
        view.addSubview(webView)
    }
}

extension NCViewerDocumentWeb: WKNavigationDelegate {
    
    public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if let serverTrust = challenge.protectionSpace.serverTrust {
            completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust))
        } else {
            completionHandler(URLSession.AuthChallengeDisposition.useCredential, nil);
        }
    }
    
    public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.allow)
    }
    
    public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print("didStartProvisionalNavigation");
    }
    
    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        if self.mimeType != nil && self.mimeType == "text/plain" && CCUtility.getDarkMode() {
            let js = "document.getElementsByTagName('body')[0].style.webkitTextFillColor= 'white';DOMReady();"
            webView.evaluateJavaScript(js) { (_, _) in }
        }
    }
    
    public func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        print("didReceiveServerRedirectForProvisionalNavigation");
    }
}