#!/usr/bin/env ruby
$LOAD_PATH.unshift '/srv/whimsy/lib'

require 'wunderbar'
require 'whimsy/asf/config'
require 'whimsy/asf/svn'

module ASF
  # Handle subscribe and unsubscribe requests
  #
  # This is a two part process (so the request can be shown to the user before committing  if required)
  # user = ASF::Person.new(person)
  # request = ASF::Subreq.create_request(user, email, list)
  # ASF::Subreq.queue_request(reqtype, request, wunderbar, options)
  module Subreq
    FORMAT_NUMBER = 3 # json format number

    # Create the request hash
    # Params:
    # user: ASF::Person instance
    # email: the email to unsubscribe
    # list: listname@domain
    # Returns: hash suitable for saving as a JSON file
    def self.create_request(user, email, list)
      {
        version: FORMAT_NUMBER,
        availid: user.id,
        addr: email,
        listkey: list,
        member_p: user.asf_member?, # does not appear to be used
        chair_p: ASF.pmc_chairs.include?(user), # does not appear to be used
      }
    end

    # Queue the update request
    # Params:
    # - reqtype: 'sub'|'unsub'
    # - request: hash generated by create_request
    # - wbar: wunderbar context (or nil)
    # - credentials: has containing credentials; may also contain options, e.g. verbose: true
    def self.queue_request(reqtype, request, wbar, credentials)
      raise Exception.new("Unexpected reqtype: #{reqtype}") unless %w{sub unsub}.include? reqtype

      queue_url = ASF::SVN.svnpath!('subreq') # only this URL is defined
      queue_url.sub! '/subreq', '/unsubreq' if reqtype == 'unsub'

      # subreq/unsubreq now accept name@dom
      # Keep the key for the file name
      list = request[:listkey]
      listkey = ASF::Mail.listdom2listkey(list)
      userid = request[:availid]

      content = JSON.pretty_generate(request) + "\n"

      # Each user can only (un)subscribe once to each list in each timeslot
      fn = "#{userid}-#{listkey}.json"

      Dir.mktmpdir do |tmpdir|

        if wbar
          ASF::SVN.svn_!('checkout', [queue_url, tmpdir], wbar, credentials)
        else
          ASF::SVN.svn!('checkout', [queue_url, tmpdir], credentials)
        end
        path = File.join(tmpdir, fn)
        if File.exist? path
          File.write(path, content) # overwrite
        else
          File.write(path, content) # new
          ASF::SVN.svn('add', path)
        end

        if reqtype == 'unsub'
          message = "#{list} -= #{userid}"
        else
          message = "#{list} += #{userid}"
        end

        options = credentials.merge({msg: message})
        if wbar
          ASF::SVN.svn_!('commit', path, wbar, options)
        else
          ASF::SVN.svn!('commit', path, options)
        end
      end
      return nil
    end
  end
end

if __FILE__ == $0
  list = ARGV.shift or raise Exception.new('need list')
  person = ARGV.shift or raise Exception.new('need id')
  email = ARGV.shift or raise Exception.new('need email')
  dryrun = ARGV.shift != 'nodryrun'
  require 'whimsy/asf'
  user = ASF::Person.new(person)
  request = ASF::Subreq.create_request(user, email, list)
  puts request
  rc,err = ASF::Subreq.queue_request('unsub', request, nil, {dryrun: dryrun, verbose: true})
  puts rc
  p err
end
