// Copyright 2016 The Tulsi Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation


/// Encapsulates functionality to launch and manage NSTasks.
public final class TaskRunner {

  /// Information retrieved through execution of a task.
  public struct CompletionInfo {
    /// The task that was executed.
    public let task: Process

    /// The commandline that was executed, suitable for pasting in terminal to reproduce.
    public let commandlineString: String
    /// The task's standard output.
    public let stdout: Data
    /// The task's standard error.
    public let stderr: Data

    /// The exit status for the task.
    public var terminationStatus: Int32 {
      return task.terminationStatus
    }
  }


  public typealias CompletionHandler = (CompletionInfo) -> Void

  private static var defaultInstance: TaskRunner = {
    TaskRunner()
  }()

    /// The outstanding tasks.
  private var pendingTasks = Set<Process>()
  private let taskReader: TaskOutputReader

  /// Prepares an NSTask using the given launch binary with the given arguments that will collect
  /// output and passing it to a terminationHandler.
  public static func createTask(_ launchPath: String,
                         arguments: [String]? = nil,
                         environment: [String: String]? = nil,
                         terminationHandler: @escaping CompletionHandler) -> Process {
    return defaultInstance.createTask(launchPath,
                                      arguments: arguments,
                                      environment: environment,
                                      terminationHandler: terminationHandler)
  }

  // MARK: - Private methods

  private init() {
    taskReader = TaskOutputReader()
    taskReader.start()
  }

  deinit {
    taskReader.stop()
  }

  private func createTask(_ launchPath: String,
                          arguments: [String]? = nil,
                          environment: [String: String]? = nil,
                          terminationHandler: @escaping CompletionHandler) -> Process {
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments
    if let environment = environment {
      task.environment = environment
    }

    let dispatchGroup = DispatchGroup()
    let notificationCenter = NotificationCenter.default
    func registerAndStartReader(_ fileHandle: FileHandle, outputData: NSMutableData) -> NSObjectProtocol {
      let observer = notificationCenter.addObserver(forName: NSNotification.Name.NSFileHandleReadToEndOfFileCompletion,
                                                           object: fileHandle,
                                                           queue: nil) { (notification: Notification) in
        defer { dispatchGroup.leave() }
        if let err = notification.userInfo?["NSFileHandleError"] as? NSNumber {
          assertionFailure("Read from pipe failed with error \(err)")
        }
        guard let data = notification.userInfo?[NSFileHandleNotificationDataItem] as? Data else {
          assertionFailure("Unexpectedly received no data in read handler")
          return
        }
        outputData.append(data)
      }

      dispatchGroup.enter()

      // The docs for readToEndOfFileInBackgroundAndNotify are unclear as to exactly what work is
      // done on the calling thread. By observation, it appears that data will not be read if the
      // main queue is in event tracking mode.
      let selector = #selector(FileHandle.readToEndOfFileInBackgroundAndNotify as (FileHandle) -> () -> Void)
      fileHandle.perform(selector, on: taskReader.thread, with: nil, waitUntilDone: true)
      return observer
    }

    let stdoutData = NSMutableData()
    task.standardOutput = Pipe()
    let stdoutObserver = registerAndStartReader((task.standardOutput! as AnyObject).fileHandleForReading,
                                                outputData: stdoutData)
    let stderrData = NSMutableData()
    task.standardError = Pipe()
    let stderrObserver = registerAndStartReader((task.standardError! as AnyObject).fileHandleForReading,
                                                outputData: stderrData)

    task.terminationHandler = { (task: Process) -> Void in
      // The termination handler's thread is used to allow the caller's callback to do off-main work
      // as well.
      assert(!Thread.isMainThread,
             "Task termination handler unexpectedly called on main thread.")
      _ = dispatchGroup.wait(timeout: DispatchTime.distantFuture)

      // Construct a string suitable for cutting and pasting into the commandline.
      let commandlineArguments: String
      if let arguments = arguments {
        commandlineArguments = " " + arguments.map({ "\"\($0)\"" }).joined(separator: " ")
      } else {
        commandlineArguments = ""
      }
      let commandlineRunnableString = "\"\(task.launchPath!)\"\(commandlineArguments)"
      terminationHandler(CompletionInfo(task: task,
                                        commandlineString: commandlineRunnableString,
                                        stdout: stdoutData as Data,
                                        stderr: stderrData as Data))

      Thread.doOnMainQueue {
        notificationCenter.removeObserver(stdoutObserver)
        notificationCenter.removeObserver(stderrObserver)
        assert(self.pendingTasks.contains(task), "terminationHandler called with unexpected task")
        self.pendingTasks.remove(task)
      }
    }

    Thread.doOnMainQueue {
      self.pendingTasks.insert(task)
    }
    return task
  }


  // MARK: - TaskOutputReader

  // Provides a thread/runloop that may be used to read NSTask output pipes.
  private class TaskOutputReader: NSObject {
    lazy var thread: Thread = { [unowned self] in
      let value = Thread(target: self, selector: #selector(threadMain(_:)), object: nil)
      value.name = "com.google.Tulsi.TaskOutputReader"
      return value
    }()

    private var continueRunning = false

    func start() {
      assert(!thread.isExecuting, "Start called twice without a stop")
      thread.start()
    }

    func stop() {
      perform(#selector(TaskOutputReader.stopThread),
                      on:thread,
                      with:nil,
                      waitUntilDone: false)
    }

    // MARK: - Private methods

    @objc
    private func threadMain(_ object: AnyObject) {
      let runLoop = RunLoop.current
      // Add a dummy port to prevent the runloop from returning immediately.
      runLoop.add(NSMachPort(), forMode: RunLoopMode.defaultRunLoopMode)

      while !thread.isCancelled {
        runLoop.run(mode: RunLoopMode.defaultRunLoopMode, before: Date.distantFuture)
      }
    }

    @objc
    private func stopThread() {
      thread.cancel()
    }
  }
}
