# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true

require 'contrast/components/interface'
require 'contrast/utils/os'

module Contrast
  # A Rake task designed to allow control of the Contrast Service as a stand
  # alone executable rather than one managed by the Agent running in a process
  # forked from the application
  module Service
    extend Rake::DSL
    include Contrast::Components::Interface

    access_component :contrast_service

    # Start the service if it is not already running
    def self.start_service
      puts 'Starting Contrast Service'
      service_log = CONTRAST_SERVICE.logger_path
      if File.writable?(service_log)
        spawn('contrast_service', out: File::NULL, err: service_log)
      else
        spawn('contrast_service', %i[out err] => File::NULL)
      end

      watcher = Contrast::Agent::Thread.new do
        sleep(0.05) until Contrast::Utils::OS.running?
      end
      watcher.join(1)
      puts Contrast::Utils::OS.running? ? 'Contrast Service started successfully.' : 'Contrast Service did not start.'
    end

    # Stop the service if it is running
    def self.stop_service
      pid = `ps aux | grep contrast-servic[e] | awk '{print $2}'`
      `kill #{ pid }` if pid
    end

    namespace :contrast do
      namespace :service do
        desc 'Starts the Contrast Service'
        task :start do
          if Contrast::Utils::OS.running?
            puts 'Contrast Service already running. No need to start'
          else
            start_service
          end
        end
      end
    end

    namespace :contrast do
      namespace :service do
        desc 'Prints the status of the Contrast Service'
        task :status do
          if Contrast::Utils::OS.running?
            puts 'online'
          else
            puts 'offline'
          end
        end
      end
    end

    namespace :contrast do
      namespace :service do
        desc 'Stops the Contrast Service'
        task :stop do
          if Contrast::Utils::OS.running?
            puts 'Stopping Contrast Service'
            stop_service
            watcher = Contrast::Agent::Thread.new do
              sleep(0.05) while Contrast::Utils::OS.running?
            end
            watcher.join(1)
            puts Contrast::Utils::OS.running? ? 'Contrast Service did not stop.' : 'Contrast Service stopped successfully.'
          else
            puts 'Contrast Service is not already running. No need to stop.'
          end
        end
      end
    end
  end
end