module Reap

  class Project

    # Make a release announcement. Generates and can email release
    # announcements. The announcement if built from the README file
    # unless another file is specified.
    #
    # This will subsititue the first line mathing /please see notes/i
    # for the notelog. And /please see change/i for the changelog.
    #
    # The following settings apply:
    #
    #     title        Project title.
    #     subtitle     Brief one-line description.
    #     version      Project version.
    #     description  Long description of project.
    #     homepage     Project homepage web address.
    #     slogan       Motto for you project.
    #     memo         File that contains announcement message.
    #     template     Announcement template file, rather then README.
    #     mail_to      Email address(es) to send announcemnt.
    #
    # If <em>mail_to</em> is set then these also apply:
    #
    #     from         Message FROM address [email].
    #     subject      Subject of email message ([ANN] title verison).
    #     server       Email server to route message.
    #     port         Email server's port.
    #     domain       Email server's domain name.
    #     account      Email account name [email].
    #     login        Login type: plain, cram_md5 or login.
    #     secure       Uses TLS security, true or false?
    #
    # A template file can be specified that uses "$setting" as
    # substitutes for poject information.

    def announce(options=nil)
      options = configure_options(options, 'announce', 'mail')

      message = announce_message(options)

      options = options.to_ostruct

      mail_to     = options.mail_to
      mail_from   = options.mail_from
      subject     = options.subject         # Subject line (default is "ANN: project version").
      server      = options.server          # Email server
      port        = options.port            # Emails server port (default is usually correct).
      account     = options.account         # Email account name (defaults to mail_from).
      domain      = options.domain          # User domain (not sure why SMTP requires this?)
      login       = options.login           # Login type (plain, login)
      secure      = options.secure          # Use TLS/SSL true or false?
      password    = options.password || ENV['EMAIL_PASSWORD']

      title       = options.title    || metadata.title
      version     = options.versoin  || metadata.version

      # defaults
      subject ||= "%s, v%s release"
      account ||= mail_from

      subject = subject % [title, version]

      if dryrun?
        puts "email '#{subject}'"
        puts "\n#{message}\n\n" if verbose?
      else
        puts "\n#{message}\n\n"
        if mail_to
          ans = ask("Would you like to email this announcement?", "yN")
          case ans.downcase
          when 'y', 'yes'
            email(message,
              :to       => mail_to,
              :from     => mail_from,
              :subject  => subject,
              :server   => server,
              :port     => port,
              :domain   => domain,
              :account  => account,
              :login    => login,
              :secure   => secure,
              :password => password
            )
          end
        end
      end
    end

    # Make a release announcement. Generates and can email a release
    # announcements. These are nicely formated message and can
    # email the message to the specified address(es).
    #
    # The following settings apply:
    #
    #     template     Announcement file/template.
    #     cutoff       Max number of lines of changelog to show.
    #
    # A template file can be specified that uses "$setting" as
    # substitutes for poject information.

    def announce_message(options={})
      config  = settings['announce'] || {}
      options = config.merge(options).to_ostruct

      cutoff   = options.cutoff    || 30
      template = options.template  || "{ANNOUNCE}{,.txt}"

      #config['mail_to'] = nil if keys['mail_to'].empty?

      # Build message

      # template
      template = Dir.glob(options.template.to_s, File::FNM_CASEFOLD).first

      if template
        readme = File.read(template)
        readme = unfold_paragraphs(readme)
      else
        readme = ''
        readme << "= #{metadata.title} v#{metadata.version}\n\n"
        readme << "    #{metadata.homepage}\n\n"
        readme << "#{metadata.description}\n\n"
        readme << "Please see the NOTES file.\n\n"
        readme << "== CHANGES\n\n"
        readme << "Please see the CHANGES file.\n"
      end

      # changelog
      file   = Dir.glob('change{s,log}{,.txt}', File::FNM_CASEFOLD)[0]
      changelog = file ? File.read(file).strip : ''
      #changelog = unfold_paragraphs(changelog)
      changelog = changelog.split("\n")[0..cutoff].join("\n")

      # noteslog
      file = Dir.glob('note{s,log}{,.txt}', File::FNM_CASEFOLD)[0]
      notelog  = file ? File.read(file).strip : ''
      notelog  = unfold_paragraphs(notelog)

      # Strip tiny version zero.
      #if keys['version'] =~ /[.].*?[.]/
      #  keys['version'] = keys['version'].chomp('.0')
      #end

      # Make announcement message
      message = readme.dup

      #message.gsub!('$readme$', readme || '')
      message.sub!(/^\s*please\ see(\ the)?\ notes(.*?)$/i, "\n" + notelog) if notelog
      message.sub!(/^\s*please\ see(\ the)?\ change(.*?)$/i, "\n" + changelog) if changelog

      template = message.dup

      template.scan(/\$(\w+?)\$/m) do |key|
        #key   = key.strip
        name  = $1.strip #key[1..-1]
        if metadata.respond_to?(name.downcase)
          value = metadata.send(name.downcase)
          message.gsub!("$#{name}$", value.to_s.strip)
        else
          puts "Warning: Unknown project field -- #{name}."
        end
      end

      message.gsub!(/(^|[ ])[$].*?(?=[ ]|$)/,'') # remove unused vars
      message.gsub!(/\n\s*\n\s*\n/m,"\n\n")      # remove any triple blank lines
      message.rstrip!

      return message
    end

    def unfold_paragraphs(string)
      blank = false
      text  = ''
      string.split(/\n/).each do |line|
        if /\S/ !~ line
          text << "\n\n"
          blank = true
        else
          if /^(\s+|[*])/ =~ line 
            text << (line.rstrip + "\n")
          else
            text << (line.rstrip + " ")
          end
          blank = false
        end
      end
      return text
    end

  end

end

  #       keys = {}
  #       keys['from'] = info.email
  #       keys.update info.gather('mail')
  #       keys.update info.gather('announce')
  #       keys.update info.select(
  #         :project, :version, :title, :subtitle, :description,
  #         :homepage, :download, :slogan
  #       )
  #       keys.update override if override