#!/usr/bin/env ruby

require 'rubygems'
require 'highline/import'
require 'yaml'
require 'trollop'
require "sup"

$opts = Trollop::options do
  version "sup-config (sup #{Redwood::VERSION})"
  banner <<EOS
Interactive configuration tool for Sup. Won't destroy existing
configuration.

Usage:
  sup-config

No options.
EOS
end

def axe q, default=nil
  ans = if default && !default.empty?
    ask "#{q} (enter for \"#{default}\"): "
  else
    ask "#{q}: "
  end
  ans.empty? ? default : ans
end

def axe_yes q, default="n"
  axe(q, default) =~ /^y|yes$/i
end

def build_cmd cmd
  (ENV["RUBY_INVOCATION"] ? ENV["RUBY_INVOCATION"] + " " : "") + File.join(File.dirname($0), cmd)
end

def add_source
  type = nil

  say "Ok, adding a new source."
  choose do |menu|
    menu.prompt = "What type of mail source is it? "
    menu.choice("mbox file") { type = :mbox }
    menu.choice("maildir directory") { type = :maildir }
    menu.choice("Get me out of here!") { return }
  end

  while true do
    say "Ok, now for the details."

    default_labels, components = case type
    when :mbox
      $last_fn ||= ENV["MAIL"]
      fn = axe "What's the full path to the mbox file?", $last_fn
      return if fn.nil? || fn.empty?

      $last_fn = fn
      [Redwood::MBox.suggest_labels_for(fn),
       { :scheme => "mbox", :path => fn }]
    when :maildir
      $last_fn ||= ENV["MAIL"]
      fn = axe "What's the full path to the maildir directory?", $last_fn
      return if fn.nil? || fn.empty?

      $last_fn = fn
      [Redwood::Maildir.suggest_labels_for(fn),
       { :scheme => "maildir", :path => fn }]
    end

    uri = begin
      URI::Generic.build components
    rescue URI::Error => e
      say "Whoopsie! I couldn't build a URI from that: #{e.message}"
      if axe_yes("Try again?") then next else return end
    end

    say "I'm going to add this source: #{uri}"
    unless axe("Does that look right?", "y") =~ /^y|yes$/i
      if axe_yes("Try again?") then next else return end
    end

    usual = axe_yes "Does this source ever receive new messages?", "y"
    archive = usual ? axe_yes("Should new messages be automatically archived? (I.e. not appear in your inbox, though still be accessible via search.)") : false

    labels_str = axe("Enter any labels to be automatically added to all messages from this source, separated by spaces (or 'none')", default_labels.join(","))

    labels = if labels_str =~ /^\s*none\s*$/i
      nil
    else
      labels_str.split(/\s+/)
    end

    cmd = build_cmd "sup-add"
    cmd += " --unusual" unless usual
    cmd += " --archive" if archive
    cmd += " --labels=#{labels.join(',')}" if labels && !labels.empty?
    cmd += " #{uri}"

    puts "Ok, trying to run \"#{cmd}\"..."

    system cmd
    if $?.success?
      say "Great! Added!"
      break
    else
      say "Rats, that failed. You may have to do it manually."
      if axe_yes("Try again?") then next else return end
    end
  end
end

$terminal.wrap_at = :auto
Redwood::start
index = Redwood::Index.init
Redwood::SourceManager.load_sources

say <<EOS
Howdy neighbor! This here's sup-config, ready to help you jack in to
the next generation of digital cyberspace: the text-based email
program. Get ready to be the envy of everyone in your internets
with your amazing keyboarding skills! Jump from email to email with
nary a click of the mouse!

Just answer these simple questions and you'll be on your way.

EOS

account = $config[:accounts][:default]

name = axe "What's your name?", account[:name]
email = axe "What's your (primary) email address?", account[:email]

say "Ok, your from header will look like this:"
say "  From: #{name} <#{email}>"

say "\nDo you have any alternate email addresses that also receive email?"
say "If so, enter them now, separated by spaces."
alts = axe("Alternate email addresses", account[:alternates].join(" ")).split(/\s+/)

sigfn = axe "What file contains your signature?", account[:signature]
editor = axe "What editor would you like to use?", $config[:editor]

$config[:accounts][:default][:name] = name
$config[:accounts][:default][:email] = email
$config[:accounts][:default][:alternates] = alts
$config[:accounts][:default][:signature] = sigfn
$config[:editor] = editor

done = false
until done
  say "\nNow, we'll tell Sup where to find all your email."
  Redwood::SourceManager.load_sources
  say "Current sources:"
  if Redwood::SourceManager.sources.empty?
    say "  No sources!"
  else
    Redwood::SourceManager.sources.each { |s| puts "* #{s}" }
  end

  say "\n"
  choose do |menu|
    menu.prompt = "Your wish? "
    menu.choice("Add a new source.") { add_source }
    menu.choice("Done adding sources!") { done = true }
  end
end

say "\nSup needs to know where to store your sent messages."
say "Only sources capable of storing mail will be listed.\n\n"

Redwood::SourceManager.load_sources
if Redwood::SourceManager.sources.empty?
  say "\nUsing the default sup://sent, since you haven't configured other sources yet."
  $config[:sent_source] = 'sup://sent'
else
  # this handles the event that source.yaml already contains the SentLoader
  # source.
  have_sup_sent = false

  choose do |menu|
    menu.prompt = "Store my sent mail in? "

    menu.choice('Default (an mbox in ~/.sup, aka sup://sent)') { $config[:sent_source] = 'sup://sent'} unless have_sup_sent

    valid_sents = Redwood::SourceManager.sources.each do |s|
      have_sup_sent = true if s.to_s.eql?('sup://sent')
      menu.choice(s.to_s) { $config[:sent_source] = s.to_s } if s.respond_to? :store_message
    end
  end
end

Redwood::save_yaml_obj $config, Redwood::CONFIG_FN, false, true

say "Ok, I've saved you up a nice lil' #{Redwood::CONFIG_FN}."

say <<EOS

The final step is to import all your messages into the Sup index.
Depending on how many messages are in the sources, this could take
quite a while.

EOS

if axe_yes "Run sup-sync to import all messages now?"
  while true
    cmd = build_cmd("sup-sync") + " --all-sources"
    puts "Ok, trying to run \"#{cmd}\"..."
    system cmd
    if $?.success?
      say "Great! It worked!"
      break
    else
      say "Rats, that failed. You may have to do it manually."
      if axe_yes("Try again?") then next else break end
    end
  end
end

index.load

say <<EOS

Okee doke, you've got yourself an index of #{index.size} messages. Looks
like you're ready to jack in to cyberspace there, cowboy.

Just one last command:

  #{build_cmd "sup"}

Have fun!
EOS
