#
# facade.rb
#
#   Copyright (c) 1998-2001 Minero Aoki <aamine@loveruby.net>
#
#   This program is free software.
#   You can distribute/modify this program under the terms of
#   the GNU Lesser General Public License version 2 or later.
#


module TMail

  class Mail

    ###
    ### attributes
    ###

    class << self
    
      def tmail_attr( mname, hname, part )
        module_eval %-
          def #{mname.id2name}( default = nil )
            if header = @header['#{hname}'] then
              header.#{part}
            else
              default
            end
          end
        -
      end
    
    end


    tmail_attr :date, 'date', 'date'

    def date=( t )
      store 'Date', ''
      @header['date'].date = t
    end

    def strftime( fmt )
      if t = date then
        t.strftime(fmt)
      else
        nil
      end
    end


    tmail_attr :to_addrs, 'to', 'addrs'
    tmail_attr :cc_addrs, 'cc', 'addrs'
    tmail_attr :bcc_addrs, 'bcc', 'addrs'

    def to( default = nil )
      addr, = to_addrs(nil)
      addr || default
    end

    def to=( addr )
      store 'To', addr
    end

    def to_addrs=( arr )
      store 'To', ''
      @header['to'].addrs.replace arr
    end


    tmail_attr :from_addrs, 'from', 'addrs'

    def from_addrs=( *arr )
      store 'From', arr.flatten.join(', ')
    end

    def from_addr( default = nil )
      addr, = from_addrs(nil)
      addr || default
    end

    def from_address( default = nil )
      if a = from_addr(nil) then
        a.address
      else
        default
      end
    end

    alias from_address= from_addrs=

    def from_phrase( default = nil )
      if a = from_addr(nil) then
        a.phrase
      else
        default
      end
    end

    def from( default = nil )
      if a = from_addr then
        a.phrase || a.address
      else
        default
      end
    end

    alias from= from_addrs=


    tmail_attr :reply_to_addrs, 'reply-to', 'addrs'


    tmail_attr :sender, 'sender', 'addr'

    def sender=( addr )
      store 'Sender', addr
    end


    tmail_attr :subject, 'subject', 'body'

    def subject=( str )
      if str then
        store 'Subject', str
      else
        @header.delete 'subject'
      end
      str
    end


    tmail_attr :message_id, 'message-id', 'msgid'

    def message_id=( str )
      if str then
        store 'Message-Id', str
      else
        @header.delete 'message-id'
      end
      str
    end

    alias msgid  message_id
    alias msgid= message_id=


    tmail_attr :references, 'references', 'refs'

    def references=( arr )
      if not arr or arr.empty? then
        @header.delete 'references'
      else
        store 'References', ''
        @header['references'].refs.replace arr
      end
      arr
    end


    tmail_attr :in_reply_to, 'in-reply-to', 'msgids'

    def in_reply_to=( arr )
      if not arr or arr.empty? then
        @header.delete 'in-reply-to'
      else
        store 'In-Reply-To', ''
        @header['in-reply-to'].refs.replace arr
      end
      arr
    end


    tmail_attr :mime_version, 'mime-version', 'version'

    def mime_version=( m, opt = nil )
      if opt then
        if f = @header['mime-version'] then
          f.major = m
          f.minor = opt
        else
          store 'Mime-Version', "#{m}.#{opt}"
        end
      else
        store 'Mime-Version', m
      end
      m
    end


    tmail_attr :main_type, 'content-type', 'main'
    tmail_attr :sub_type, 'content-type', 'sub'

    def set_content_type( str, sub = nil, param = nil )
      if sub then
        main, sub = str, sub
      else
        main, sub = str.split('/', 2)
      end
      if f = @header['content-type'] then
        f.main = main
        f.sub  = sub
      else
        store 'Content-Type', "#{main}/#{sub}"
      end
      @header['content-type'].params.replace param if param

      str
    end

    alias content_type= set_content_type

    tmail_attr :charset, 'content-type', "params['charset']"

    def charset=( str )
      if str then
        if f = @header[ 'content-type' ] then
          f.params['charset'] = str
        else
          store 'Content-Type', "text/plain; charset=#{str}"
        end
      end
      str
    end


    tmail_attr :encoding, 'content-transfer-encoding', 'encoding'

    def encoding=( str )
      if str then
        store 'Content-Transfer-Encoding', str
      else
        @header.delete 'content-transfer-encoding'
      end
      str
    end


    tmail_attr :disposition, 'content-disposition', 'disposition'

    def disposition=( str )
      store 'Content-Disposition', str
      str
    end

    def set_content_disposition( str, params = nil )
      if f = @header['content-disposition'] then
        f.disposition = str
      else
        f = store( 'Content-Disposition', str )
      end
      f.params.replace params if params
    end


    ###
    ### utils
    ###

    def create_reply
      mail = TMail::Mail.parse('')
      mail.subject = 'Re: ' + subject('').sub( /\A(?:\[[^\]]+])?(?:\s*Re:)*\s*/i, '' )
      mail.to_addrs = reply_addresses([])
      mail.in_reply_to = [message_id(nil)].compact
      mail.references = references([]) + [message_id(nil)].compact
      mail.mime_version = '1.0'
      mail
    end

    def base64_encode
      store 'Content-Transfer-Encoding', 'Base64'
      self.body = Base64.folding_encode(self.body)
    end

    def base64_decode
      if /base64/i === (@header['content-transfer-encoding'] || '') then
        store 'Content-Transfer-Encoding', '8bit'
        self.body = Base64.decode(self.body)
      end
    end


    def destinations
      ret = []
      %w( to cc bcc ).each do |nm|
        if head = @header[nm] then
          head.addrs.each {|i| ret.push i.address }
        end
      end
      ret
    end

    def each_destination( &block )
      destinations.each do |i|
        if Address === i then
          yield i
        else
          i.each( &block )
        end
      end
    end

    alias each_dest each_destination


    def reply_addresses( default = nil )
      reply_to_addrs(nil) or from_addrs(nil) or default
    end

    def error_reply_addresses
      if s = sender(nil) then
        [s]
      else
        from_addrs(nil)
      end
    end

    def multipart?
      main_type('').downcase == 'multipart'
    end

  end   # class Mail

end   # module TMail
