#!/usr/bin/env ruby

require 'digest'

class ReleaseIndexer
  attr_reader :name, :sources_url, :version, :revision, :workdir
  attr_reader :index_file, :checksum_file
  attr_reader :files, :created_at

  def initialize(name, sources_url, version, revision, workdir)
    @name = name
    @sources_url = sources_url
    @version = version
    @revision = revision
    @workdir = workdir

    @index_file = "#{workdir}/index.html"
    @checksum_file = "#{workdir}/release.sha256"

    @created_at = Time.now.strftime("%Y-%m-%dT%H:%M:%S%:z")
  end

  def generate!
    prepare_files
    generate_checksums
    generate_index
  end

  private

  def prepare_files
    @files = []
    search_files.each do |file|
      add_file(file)
    end
  end

  def search_files
    files_cmd = `find #{workdir}/ -type f | sort`
    files_cmd.split("\n").select{ |f| f != index_file && f != checksum_file }
  end

  def add_file(file)
    @files << {
        name: file.gsub("#{workdir}/", ''),
        checksum: Digest::SHA256.file(file).hexdigest,
        size: File.stat(file).size.to_f
    }
  end

  def generate_checksums
    File.open(checksum_file, 'w') do |f|
      f.puts files.map{ |file| "#{file[:checksum]}\t#{file[:name]}" }.join("\n")
    end
    add_file(checksum_file)
  end

  def generate_index
    title = "#{name} :: Release for #{version}"

    File.open(index_file, 'w') do |f|
      f.puts <<EOS
<html>
    <head>
        <meta charset="utf-8/">
        <title>#{title}</title>
        <style type="text/css">
            body {font-family: monospace; font-size: 14px; margin: 40px; padding: 0;}
            h1 {border-bottom: 1px solid #aaa; padding: 10px;}
            p {font-size: 0.85em; margin: 5px 10px;}
            p span {display: inline-block; font-weight: bold; width: 100px;}
            p a {color: #000; font-weight: bold; text-decoration: none;}
            p a:hover {text-decoration: underline;}
            ul {background: #eee; border: 1px solid #aaa; border-radius: 3px; box-shadow: 0 0 5px #aaa inset; list-style-type: none; margin: 10px 0; padding: 10px;}
            li {margin: 5px 0; padding: 5px; font-size: 12px;}
            li:hover {background: #dedede;}
            .file_name {display: inline-block; font-weight: bold; width: calc(100% - 600px);}
            .file_name a {color: #000; display: inline-block; text-decoration: none; width: calc(100% - 10px);}
            .file_checksum {display: inline-block; width: 500px;}
            .file_size {display: inline-block; width: 90px;}
        </style>
    </head>
    <body>
        <h1>#{title}</h1>
        <p><span>Sources:</span> <a href="#{sources_url}" target="_blank">#{sources_url}</a></p>
        <p><span>Revision:</span> #{revision}</p>
        <p><span>Created at:</span> #{created_at}</p>
        <ul>
EOS

      files.each do |file|
        line = "<li>"
        line += "<span class=\"file_name\"><a href=\"./#{file[:name]}\">#{file[:name]}</a></span>"
        line += "<span class=\"file_checksum\">#{file[:checksum]}</span>"
        line += "<span class=\"file_size\">%.2f MiB</span>" % (file[:size] / 1048576)
        line += '</li>'
        f.puts line
      end

      f.puts <<EOS
        </ul>
    </body>
</html>
EOS
    end
  end
end

ReleaseIndexer.new('GitLab Runner',
                   "#{ENV['CI_PROJECT_URL']}/tree/#{ENV['CI_COMMIT_REF_NAME']}",
                   ENV['VERSION'],
                   ENV['CI_COMMIT_SHA'],
                   'out').generate!
