#!/usr/bin/env ruby

require 'json'
require 'faraday'
require 'faraday_middleware'
require 'fileutils'

module Guru
  class Promote
    def initialize(release_channel, release_version, release_platform, guru_release_id, guru_addr, guru_access_key)
      @release_channel = release_channel
      @release_version = release_version
      @release_platform = release_platform
      @guru_release_id = guru_release_id
      @guru_addr = guru_addr
      @guru_access_key = guru_access_key

      begin
        @conn = Faraday.new(url: guru_addr) do |conn|
          conn.request :url_encoded
          conn.response :json, content_type: 'application/json'
          conn.adapter :net_http
          conn.headers = { 'UploadKey' => @guru_access_key }
        end
      rescue
        teamcity_status 1, "Initial: Could not connect to guru on #{guru_addr}"
      end
    end

    def submit
      begin
        resp = @conn.post("/release/#{@guru_release_id}/promote-release")
      rescue StandardError => e
        puts e
        teamcity_status 1, 'submit: Could not connect to guru'
      end

      if resp.status >= 300
        teamcity_status 1, "Got #{resp.status} from /release/#{@guru_release_id}/promote-release: #{resp.body}"
      else
        teamcity_message "Desktop release #{@release_channel} v#{@release_version} (#{@release_platform}) promoted to live"
        teamcity_status 0, "Desktop release #{@release_channel} v#{@release_version} (#{@release_platform}) promoted to live"
      end
    end

    # teamcity utility methods
    def teamcity_status(exit_code, message)
      puts "##teamcity[buildStatus status='#{exit_code.zero? ? 'Success' : 'Failed'}' text='#{message}']"
      exit exit_code
    end

    def teamcity_message(message, name = nil)
      puts "##teamcity[#{name || 'message'} text='#{message}']"
    end

    def teamcity_parameter(key, value)
      puts "##teamcity[setParameter name='#{key}' value='#{value}']"
    end
  end
end

# Need to set the content disposition name, and UploadIO/Multipart doesn't seem to support the correct format, hardcode it
module Parts
  module Part #:nodoc:
    def self.new(boundary, name, value, headers = {})
      headers ||= {} # avoid nil values
      if file?(value)
        FilePart.new(boundary, 'files', value, headers)
      else
        ParamPart.new(boundary, 'files', value, headers)
      end
    end
  end
end


guru_runner = Guru::Promote.new(ENV['RELEASE_CHANNEL'], ENV['RELEASE_VERSION'], ENV['RELEASE_PLATFORM'], ENV['GURU_RELEASE_ID'], ENV['GURU_ADDR'], ENV['GURU_ACCESS_KEY'])
guru_runner.submit
