require File.join(File.dirname(__FILE__), "base.rb")

class BuildWise::SCM::SVN < BuildWise::SCM::Base

  def installed?
    puts "[DEBUG] installed #{@config.bin_path}"
    exec_successful? "#{@config.bin_path}svn --version"
  end

  def initial_checkout
    puts "[INFO] #{Time.now} Initial checkout SVN... #{@path}"
    FileUtils.rm_rf(@path) if test(?d, @path)
    encoded_url = (@config.scm_url.include?(' ') ? "\"#{@config.scm_url}\"" : @config.scm_url)
    puts "[DEBUG] SVN url => #{encoded_url}"
    checkout_cmd = "#{@config.bin_path}svn co #{auth_options()} #{encoded_url} \"#{@path}\""
    puts checkout_cmd
    @status = `#{checkout_cmd}`

    puts "[INFO] #{Time.now} checked out at #{@path} |#{@status}|"

    unless @status


      manual_command = "svn co #{encoded_url} #{@path}"
      puts "Manual checkout ==> #{manual_command}"
      system(manual_command)
    end

    return @status
  end


  def update!
    if test(?d, @path + '/.svn') #check first that it was not locked
      execute("cleanup") if locked?
      say "Could not unlock svn directory #{@encoded_path}. Please do it manually." if locked? #In case if we could not unlock from command line - ask user to do it
    end

    if test(?d, @path + '/.svn')
      @status = execute("update")
    else
      FileUtils.mkpath(@path) unless test(?d, @path)
      @status = execute("checkout", nil, @config.scm_url)
    end
  end

  def has_changes?
    @status =~ /[A-Z]\s+[\w\/]+/ ? true : false
  end


  def current_revision(full = true)
    info['Revision'].to_i
  end

  def url
    info['URL']
  end

  def last_commit_message
    message = execute("log", "--limit 1 -v")

    if (idx = message.index('-'*72))
      message[idx..-1]
    else
      message
    end
  end

  def last_author
    info['Last Changed Author']
  end



  def last_commit_changed_files
    scm_output = execute('log', "-v -r")
    changed_files = []





    return changed_files.join(",")
  end

  def determine_changesets(log_file)
    last_good_build_rev = last_successful_build_revision
    last_good_build_rev ||= 1

    puts "{XXXX} SVN last_good_rev_at: #{last_good_build_rev} | current rev=>#{current_revision}"



    execute('log', " --non-interactive -v -r#{last_good_build_rev}:#{current_revision} > \"#{log_file}\"") # turn off git-diff $PAGER by default
  end

  def extract_commit_info(commit=remote_head)
    begin

      commit_message = execute("log", "#{commit} -1 --pretty=\"format:%an(%ae)|%ai|%h|%s%n%b\"")
      message = commit_message.split("|")
      return {:author => message[0], :date => message[1], :revision => message[2], :message => message[3]}
    rescue => e
      puts "Error on extract commit info: #{e}"
      return {}
    end
  end

  def last_commit_message
    @message
  end

  def last_commit_date
    @date
  end

  def last_author
    @author
  end

  def output
    @status
  end

  private
  def locked?
    execute("st") =~ /^..L/
  end

  def info
    unless @info
      output = execute("info")
      @info = YAML.load(output)
      puts "XXX SVN Output => #{@info}"
      if not @info.is_a?(Hash) or @info['Repository UUID'].nil? #.size > 8
        say "Could not parse svn output. Seems source directory #{@encoded_path} is corrupted.\n#{output}"
      end
    end
    @info
  end

  def execute(command, parameters = nil, pre_parameters = nil)
    puts "[DEBUG] Executing SCM |" + "#{@config.bin_path}svn #{command} #{auth_options()} #{@encoded_path} #{parameters}"
    `#{@config.bin_path}svn #{command} #{auth_options()} #{@encoded_path} #{parameters}`
  end

  def auth_options
    auth = []
    auth << "--username #{@config.scm_user}" if @config.scm_user
    auth << "--password #{@config.scm_password}" if @config.scm_password

    auth.join(' ')
  end
end