#!/usr/bin/env ruby

# Copyright (C) 2004, 2005  National Institute of Advanced Industrial Science and Technology
#
# This file is part of msgcab.
#
# msgcab is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# msgcab is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with msgcab; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

# Usage:
#   ./msgcab-estraier [OPTIONS] RANGES

require 'msgcab/cli/common'
require 'msgcab/entity'
require 'msgcab/logger'
require 'msgcab/progressbar'
require 'estraier'

module Estraier
  class Document
    def add_text_from_mime(entity)
      if entity.multipart?
        entity.each do |part|
          add_text_from_mime(part)
        end
      else
        add_text(entity.decode_body)
      end
    end

    public
    def self.new_from_mime(uri, data)
      doc = new
      doc.add_attr('@uri', uri)
      doc.add_attr('@type', 'message/rfc822')
      doc.add_text_from_mime(::MsgCab::Entity.parse(data))
      doc
    end
  end
end

module MsgCab
  module CLI
    class Estraier < Common
      include Logging

      def add_documents(numbers)
        numbers = (0 .. CLI.database.max).to_a if numbers.empty?
        index_path = MsgCab::Config['estraier', 'index_path'] ||
          './estraier'
        index_path = MsgCab::Config.absolute_path(index_path)
        index_path.mkdir unless index_path.exist?
        database = ::Estraier::Database.new
        unless database.open(index_path.to_s,
                             ::Estraier::Database::DBWRITER |
                               ::Estraier::Database::DBCREAT)
          log(2, database.err_msg(database.error))
          return
        end
        pbar = ProgressBar.new('estraier', numbers.length) unless opts[:quiet]
        numbers.each do |number|
          uri = 'file://' + CLI.mailtree.number_to_path(number)
          next if database.uri_to_id(uri) > -1
          data = CLI.mailtree.fetch(number)
          document = ::Estraier::Document.new_from_mime(uri, data)
          folder, = CLI.database.to_folder_number(number)
          document.add_attr('folder', folder)
          unless database.put_doc(document, ::Estraier::Database::PDCLEAN)
            raise ArgumentError, "put_doc failed"
          end
          pbar.inc unless opts[:quiet]
        end
        database.close
        pbar.finish unless opts[:quiet]
      end
    end
  end
end

require 'pathname'
require 'optparse'

path = Pathname.new($0).realpath.dirname
$LOAD_PATH.unshift((path + 'lib').to_s)
$KCODE = 'UTF8'

require 'msgcab/config'

MsgCab::FLAVOR = 'cli'
MsgCab::Config.load(path + 'config.yml')

opt_quiet = false
opts = OptionParser.new do |opts|
  opts.banner = <<"End"
Usage: #{$0} [OPTIONS] RANGES
where RANGES is a comma separated list of global numbers assigned by import
command.  If it is -, #{File.basename($0)} reads a message from
standard input.
End
  opts.on('--quiet', '-q', 'Suppress all normal output.') do
    opt_quiet = true
  end
  opts.on_tail('--help', '-h', 'Show this message.') do
    $stdout.print(opts.to_s)
    exit(0)
  end
end

begin
  opts.parse!(ARGV)
rescue OptionParser::ParseError
  $stderr.print(opts.to_s)
  exit(1)
end

begin
  cli = MsgCab::CLI::Estraier.new({:quiet => opt_quiet})

  if ARGV.empty?
    numbers = Array.new
  else
    ranges = ARGV.shift
    ranges = $stdin.read if ranges == '-'
    numbers = MsgCab::CLI.uncompress_numbers(ranges)
  end
  cli.add_documents(numbers)
rescue Exception => e
  $stderr.puts("Error: #{e}\n#{e.backtrace.join("\n")}")
  exit(1)
ensure
  MsgCab::CLI.database.disconnect
end
