# frozen_string_literal: true

require 'pathname'
require 'shellwords'
require 'mkmf'
require_relative 'build/configuration'

module JenkinsfileRunner
  module Commands
    class Build
      attr_reader :configuration

      def initialize(argv)
        @configuration = Configuration.new(argv.dup)
      end

      def run
        puts "Running build with #{configuration.inspect}"
        @configuration.validate!
        find_docker_binary!
        validate_docker_version!

        puts "Logging in to #{configuration.registry}"
        docker('login', configuration.registry)
        docker('image', 'build', context_dir ,'--pull', '--tag', image_tag)
        docker('push', image_tag)
        docker('logout', configuration.registry)
      end

      private

      def find_docker_binary!
        @docker = MakeMakefile.find_executable('docker')
        abort('Could not find docker') unless @docker
      end

      def validate_docker_version!
        minimal_docker_version = Gem::Version.new('19.0')

        client_version = `#{@docker} version --format '{{.Client.Version}}'`
        client_version = Gem::Version.new(client_version)

        sever_version = `#{@docker} version --format '{{.Server.Version}}'`
        sever_version = Gem::Version.new(sever_version)

        return if client_version >= minimal_docker_version && sever_version >= minimal_docker_version

        abort("Docker #{minimal_docker_version} or above is required")
      end

      def context_dir
        Pathname(configuration.build_output).expand_path
      end

      def image_tag
        "#{configuration.registry}/#{configuration.image}".downcase
      end

      def docker(*args)
        system!(@docker, *args)
      end

      def system!(*args)
        args = args.map { |arg| Shellwords.escape(arg) }

        system(*args) || abort("\n== Command #{args} failed ==")
      end
    end
  end
end
