#!/usr/bin/env ruby

require 'fileutils'
require 'pathname'
require 'tempfile'
require 'securerandom'
require 'minitar'
require 'zlib'
require 'find'
require 'net/http'
require 'net/http/post/multipart'
require 'uri'
require 'listen'

# Work in progress theme watcher for Discourse
#
# Monitor a theme directory locally and automatically keep it in sync with Discourse

def usage
  puts "Usage: theme-watcher DIR SITE"
  exit 1
end

$api_key = ENV['DISCOURSE_API_KEY']
$dir = ARGV[0]
$site = ARGV[1]

if !$api_key
  puts "No API key found in DISCOURSE_API_KEY env var enter your API key: "
  $api_key = gets
end

if !File.exist?("#{$dir}/about.json")
  puts "No about.json file found in #{dir}!"
  puts
  usage
end

def compress_dir(gzip, dir)
  sgz = Zlib::GzipWriter.new(File.open(gzip, 'wb'))
  tar = Archive::Tar::Minitar::Output.new(sgz)

  Dir.chdir(dir + "/../") do
    Find.find(File.basename(dir)) do |x|
      Find.prune if File.basename(x)[0] == ?.
      next if File.directory?(x)

      Minitar.pack_file(x, tar)
    end
  end
ensure
  tar.close
  sgz.close
end

def upload_full_theme(dir, site)
  filename = "#{Pathname.new(Dir.tmpdir).realpath}/bundle_#{SecureRandom.hex}.tar.gz"
  compress_dir(filename, dir)

  # new full upload endpoint
  uri = URI.parse(site + "/admin/themes/import.json?api_key=#{$api_key}")
  http = Net::HTTP.new(uri.host, uri.port)
  File.open(filename) do |tgz|

    request = Net::HTTP::Post::Multipart.new(
      uri.request_uri,
      "bundle" => UploadIO.new(tgz, "application/tar+gzip", "bundle.tar.gz"),
    )
    response = http.request(request)
    p response.code
  end

ensure
  FileUtils.rm_f filename
end

upload_full_theme($dir, $site)

listener = Listen.to($dir) do |modified, added, removed|
  puts "Change detected"
  upload_full_theme($dir, $site)
end

listener.start
sleep