// Basis of this code comes from https://github.com/lubritto/flutter_share

import Flutter
import UIKit
    
public class Share {
    public static func share(call: FlutterMethodCall, result: @escaping FlutterResult) {
        let args = call.arguments as? [String: Any?]

        let title = args!["title"] as? String
        let text = args!["text"] as? String
        let filename = args!["filename"] as? String
        let tmpDirURL = FileManager.default.temporaryDirectory
        
        if (filename == nil || filename!.isEmpty) {
            return result(false)
        }

        let tmpFile = tmpDirURL.appendingPathComponent(filename!)
        do {
            try text?.write(to: tmpFile, atomically: true, encoding: .utf8)
        } catch {
            //TODO: return error
            return result(false)
        }
        
        pop(title: title, file: tmpFile) { pass in
            let fm = FileManager()
            do {
                try fm.removeItem(at: tmpFile)
            } catch {}
            
            return result(pass)
        }
    }

    public static func shareFile(call: FlutterMethodCall, result: @escaping FlutterResult) {
        let args = call.arguments as? [String: Any?]

        let title = args!["title"] as? String
        let filePath = args!["filePath"] as? String
        let filename = args!["filename"] as? String

        if (filePath == nil || filePath!.isEmpty) {
            return result(false)
        }
        
        var tmpFile: URL?
        let fm = FileManager()
        var realPath = URL(fileURLWithPath: filePath!)
        
        if (filename != nil && !filename!.isEmpty) {
            tmpFile = FileManager.default.temporaryDirectory.appendingPathComponent(filename!)
            
            do {
                try fm.linkItem(at: URL(fileURLWithPath: filePath!), to: tmpFile!)
            } catch {
                //TODO: return error
                return result(false)
            }
            
            realPath = tmpFile!
        }

        pop(title: title, file: realPath) { pass in
            if (tmpFile != nil) {
                do {
                    try fm.removeItem(at: tmpFile!)
                } catch {}
            }
            result(pass)
        }
    }
    
    private static func pop(title: String?, file: URL, completion: @escaping ((Bool) -> Void)) {
        if (title == nil || title!.isEmpty) {
            return completion(false)
        }
        
        let activityViewController = UIActivityViewController(activityItems: [ShareCopy(file: file)], applicationActivities: nil)
        
        activityViewController.completionWithItemsHandler = {(activityType: UIActivity.ActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) in
            completion(true)
        }
                
        // Subject
        activityViewController.setValue(title, forKeyPath: "subject")

        // For iPads, fix issue where Exception is thrown by using a popup instead
        if UIDevice.current.userInterfaceIdiom == .pad {
          activityViewController.popoverPresentationController?.sourceView = UIApplication.topViewController()?.view
          if let view = UIApplication.topViewController()?.view {
              activityViewController.popoverPresentationController?.permittedArrowDirections = []
              activityViewController.popoverPresentationController?.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
          }
        }

        DispatchQueue.main.async {
          UIApplication.topViewController()?.present(activityViewController, animated: true)
        }
    }
}

extension UIApplication {
    class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    }
}

class ShareCopy: UIActivityItemProvider {
    private let file: URL
    private let content: String

    init(file: URL) {
        self.file = file
        do {
            self.content = try String.init(contentsOf: file)
        } catch {
            self.content = "Error"
        }
        
        // the type of the placeholder item is used to
        // display correct activity types by UIActivityControler
        super.init(placeholderItem: self.content)
    }

    override var item: Any {
        get {
            guard let activityType = activityType else {
                return file
            }

            switch activityType {
            case .copyToPasteboard: return content
            default: return file
            }
        }
    }
}