//
//  SafariViewController.swift
//  flutter_inappwebview
//
//  Created by Lorenzo on 25/09/18.
//

import Foundation
import SafariServices

@available(iOS 9.0, *)
public class SafariViewController: SFSafariViewController, FlutterPlugin, SFSafariViewControllerDelegate {
    
    var channel: FlutterMethodChannel?
    var safariOptions: SafariBrowserOptions?
    var uuid: String = ""
    var menuItemList: [[String: Any]] = []
    
    public static func register(with registrar: FlutterPluginRegistrar) {
        
    }
    
    deinit {
        print("SafariViewController - dealloc")
    }
    
    public func prepareMethodChannel() {
        channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser_" + uuid, binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
        SwiftFlutterPlugin.instance!.registrar!.addMethodCallDelegate(self, channel: channel!)
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        // let arguments = call.arguments as? NSDictionary
        switch call.method {
            case "close":
                close(result: result)
                break
            default:
                result(FlutterMethodNotImplemented)
                break
        }
    }
    
    public override func viewWillAppear(_ animated: Bool) {
        // prepareSafariBrowser()
        super.viewWillAppear(animated)
        onChromeSafariBrowserOpened()
    }
    
    public override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        self.onChromeSafariBrowserClosed()
        self.dispose()
    }
    
    
    func prepareSafariBrowser() {
        if #available(iOS 11.0, *) {
            self.dismissButtonStyle = SFSafariViewController.DismissButtonStyle(rawValue: (safariOptions?.dismissButtonStyle)!)!
        }
        
        if #available(iOS 10.0, *) {
            if !(safariOptions?.preferredBarTintColor.isEmpty)! {
                self.preferredBarTintColor = color(fromHexString: (safariOptions?.preferredBarTintColor)!)
            }
            if !(safariOptions?.preferredControlTintColor.isEmpty)! {
                self.preferredControlTintColor = color(fromHexString: (safariOptions?.preferredControlTintColor)!)
            }
        }
        
        self.modalPresentationStyle = UIModalPresentationStyle(rawValue: (safariOptions?.presentationStyle)!)!
        self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (safariOptions?.transitionStyle)!)!
    }
    
    func close(result: FlutterResult?) {
        dismiss(animated: true)
        
        // wait for the animation
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in
            if result != nil {
               result!(true)
            }
        })
    }
    
    public func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
        close(result: nil)
    }
    
    public func safariViewController(_ controller: SFSafariViewController,
                              didCompleteInitialLoad didLoadSuccessfully: Bool) {
        if didLoadSuccessfully {
            onChromeSafariBrowserCompletedInitialLoad()
        }
        else {
            print("Cant load successfully the 'SafariViewController'.")
        }
    }
    
    public func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
        var uiActivities: [UIActivity] = []
        menuItemList.forEach { (menuItem) in
            let activity = CustomUIActivity(uuid: uuid, id: menuItem["id"] as! Int64, url: URL, title: title, label: menuItem["label"] as? String, type: nil, image: nil)
            uiActivities.append(activity)
        }
        return uiActivities
    }
//
//    public func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivity.ActivityType] {
//        print("excludedActivityTypesFor")
//        print(URL)
//        print(title)
//        return []
//    }
//
//    public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {
//        print("initialLoadDidRedirectTo")
//        print(URL)
//    }
    
    public func onChromeSafariBrowserOpened() {
        channel!.invokeMethod("onChromeSafariBrowserOpened", arguments: [])
    }
    
    public func onChromeSafariBrowserCompletedInitialLoad() {
        channel!.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", arguments: [])
    }
    
    public func onChromeSafariBrowserClosed() {
        channel!.invokeMethod("onChromeSafariBrowserClosed", arguments: [])
    }
    
    public func dispose() {
        delegate = nil
        channel!.setMethodCallHandler(nil)
    }
    
    // Helper function to convert hex color string to UIColor
    // Assumes input like "#00FF00" (#RRGGBB).
    // Taken from https://stackoverflow.com/questions/1560081/how-can-i-create-a-uicolor-from-a-hex-string
    func color(fromHexString: String, alpha:CGFloat? = 1.0) -> UIColor {
        
        // Convert hex string to an integer
        let hexint = Int(self.intFromHexString(hexStr: fromHexString))
        let red = CGFloat((hexint & 0xff0000) >> 16) / 255.0
        let green = CGFloat((hexint & 0xff00) >> 8) / 255.0
        let blue = CGFloat((hexint & 0xff) >> 0) / 255.0
        let alpha = alpha!
        
        // Create color object, specifying alpha as well
        let color = UIColor(red: red, green: green, blue: blue, alpha: alpha)
        return color
    }
    
    func intFromHexString(hexStr: String) -> UInt32 {
        var hexInt: UInt32 = 0
        // Create scanner
        let scanner: Scanner = Scanner(string: hexStr)
        // Tell scanner to skip the # character
        scanner.charactersToBeSkipped = CharacterSet(charactersIn: "#")
        // Scan hex value
        scanner.scanHexInt32(&hexInt)
        return hexInt
    }
}

class CustomUIActivity : UIActivity {
    var uuid: String
    var id: Int64
    var url: URL
    var title: String?
    var type: UIActivity.ActivityType?
    var label: String?
    var image: UIImage?
    
    init(uuid: String, id: Int64, url: URL, title: String?, label: String?, type: UIActivity.ActivityType?, image: UIImage?) {
        self.uuid = uuid
        self.id = id
        self.url = url
        self.title = title
        self.label = label
        self.type = type
        self.image = image
    }

    override class var activityCategory: UIActivity.Category {
        return .action
    }

    override var activityType: UIActivity.ActivityType? {
        return type
    }

    override var activityTitle: String? {
        return label
    }

    override var activityImage: UIImage? {
        return image
    }

    override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
        return true
    }

    override func perform() {
        let channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser_" + uuid, binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
        
        let arguments: [String: Any?] = [
            "url": url.absoluteString,
            "title": title,
            "id": id,
        ]
        channel.invokeMethod("onChromeSafariBrowserMenuItemActionPerform", arguments: arguments)
    }
}