#!/usr/bin/ruby

DockerBinaryLocation = `which docker`.chomp

def cmd(*args)
  io = IO.popen(args, err: '/dev/null')
  io.read.split("\n")
end

def docker(*args)
  cmd(DockerBinaryLocation, *args)
end

output_format = (ARGV.delete('-f') or ARGV.delete('--full')) ? :name_and_tag : :tag
group_by_ref = (ARGV.delete('-g') or ARGV.delete('--group-by-ref'))

unless pattern_str = ARGV.shift
  prefix = "usage: #{$0}"
  spacer = " " * prefix.length
  $stderr.puts "#{prefix} image-name"
  $stderr.puts "#{spacer} image-name:tag"
  $stderr.puts "#{spacer} layer-id"
  Kernel.exit 1
end

if pattern_str.index(':')
  pattern_name, pattern_tag = pattern_str.split(':')
  pattern = {name: pattern_name, tag: pattern_tag}
elsif pattern_str =~ /^[0-9a-f]+$/i and [12, 64].include?(pattern_str.length)
  pattern = {ref: pattern_str}
else
  pattern = {name: pattern_str}
end

pattern[:effective_tag] = pattern[:tag] || 'latest'

images = docker('images', '-a', '--no-trunc')[1..-1].map do |ln|
  parts = ln.split(' ').map{ |part| part unless part == '<none>' }
  {name: parts[0], tag: parts[1], ref: parts[2]}
end


if pattern[:ref]
  ref_rxp = /^#{pattern[:ref]}([0-9a-f]{52})?$/
  pattern[:name] = images.find{ |image| image[:ref] =~ ref_rxp }[:name]
elsif pattern[:name]
  pattern[:ref] = images.find{ |image| image[:tag] == pattern[:effective_tag] }[:ref]
end

images = images.find_all{ |image| image[:name] == pattern[:name] }

if pattern[:explicit_tag]
  images = images.find_all{ |image| image[:tag] == pattern[:explicit_tag] }
end

format_tag = lambda do |tag|
  case output_format
  when :name_and_tag
    "#{pattern[:name]}:#{tag}"
  when :tag
    tag
  end
end

if group_by_ref
  image_groups = images.group_by{ |image| image[:ref] }.map{ |(_, v)| v }
  image_groups.each do |image_set|
    synonyms = image_set.map{ |image| image[:tag] }.sort
    synonym_strs = synonyms.map(&format_tag)

    main_name_str = synonym_strs.shift
    puts "#{main_name_str}: #{synonym_strs.join(', ')}"
  end
else
  images.map{ |image| image[:tag] }.each do |tag|
    puts format_tag.call(tag)
  end
end

