dockerbuild_plugin = self

namespace :docker do

desc "check directory exist"
task :check do
  on fetch(:docker_build_server_host) do
    execute :mkdir, "-p", dockerbuild_plugin.docker_build_base_path.dirname.to_s
    execute :git, :'ls-remote', repo_url, "HEAD"
  end
end

desc "Clone the repo to docker build base directory"
task :clone => [:'docker:check'] do
  on fetch(:docker_build_server_host) do
    if test " [ -f #{dockerbuild_plugin.docker_build_base_path}/HEAD ] "
      info t(:mirror_exists, at: dockerbuild_plugin.docker_build_base_path.to_s)
    else
      within dockerbuild_plugin.docker_build_base_path.dirname do
        execute :git, :clone, "--mirror", repo_url, dockerbuild_plugin.docker_build_base_path.to_s
      end
    end
  end
end

desc "Update the repo mirror to reflect the origin state"
task update_mirror: :'docker:clone' do
  on fetch(:docker_build_server_host) do
    within dockerbuild_plugin.docker_build_base_path do
      execute :git, :remote, :update, "--prune"
    end
  end
end

desc "build and push docker image on remote host"
task :build => [:'docker:update_mirror'] do
  on fetch(:docker_build_server_host) do
    within dockerbuild_plugin.docker_build_base_path do
      timestamp = Time.now.to_i
      worktree_dir_name = "worktree-#{fetch(:docker_tag)}-#{timestamp}"

      execute(:git, :worktree, :add, worktree_dir_name, fetch(:branch))

      begin
        within worktree_dir_name do
          execute(*fetch(:docker_build_cmd))
        end
      ensure
        execute(:rm, "-rf", worktree_dir_name)
        execute(:git, :worktree, :prune)
        # Execute "git gc" manually to avoid "There are too many unreachable loose objects" warning
        execute(:git, :gc, "--auto", "--prune=3.days.ago")
      end
    end
  end
end

task :push => [:'docker:build'] do
  on fetch(:docker_build_server_host) do
    execute(:docker, :tag, fetch(:docker_tag_full), fetch(:docker_remote_tag_full))
    execute(:docker, :push, fetch(:docker_remote_tag_full))
  end
end

task :cleanup_local_images do
  on fetch(:docker_build_server_host) do
    local_images = []
    capture(:docker, "images --format='{{.ID}}\t{{.Repository}}\t{{.CreatedAt}}'").split("\n").map do |line|
      id, repository, created_at = line.split("\t")
      if repository == fetch(:docker_repository_name)
        local_images << { id: id, created_at: created_at }
      end
    end
    local_images.uniq!  # Same image could exist in different repository.
    if local_images.size > fetch(:keep_docker_image_count)
      deleting_image_ids = local_images.sort_by { |i| i[:created_at] }.first(local_images.size - fetch(:keep_docker_image_count)).map { |i| i[:id] }
      execute(:docker, "rmi -f #{deleting_image_ids.join(" ")}")
    end
  end
end

end