#
# ISO-2022-JP compact filter
#
# Copyright (C) All right reserved by Kazuhiro NISHIYAMA <zn@mbf.nifty.com> 2001
# You can redistribute it and/or modify it under the same term as GPL2.
#
# http://homepage2.nifty.com/zn/jewel/JisCompactFilter.rb
# http://www.spc.gr.jp/mobiler/

module ISO_2022_JP
  MAP = {
    '♯' => '#',
    '、' => ',',
    '。' => '.',
  }
  '　！”＃＄％＆’（）＊＋，−．／０１２３４５６７８９：；＜＝＞？＠ＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰＱＲＳＴＵＶＷＸＹＺ［￥］＾＿｀ａｂｃｄｅｆｇｈｉｊｋｌｍｎｏｐｑｒｓｔｕｖｗｘｙｚ｛｜｝￣'.split(//).each_with_index do |ch,i|
    c = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'[i].chr
    MAP[c] = ch
    MAP[ch] = c
  end

  # iso-2022-jpでのバイト数を小さくする。
  def min(kcode_string)
    kcode_string.collect do |line|
      eol = '' # 行末を保存
      h = lasth = {''=>[0,:usascii]}
      line.sub(/\r?\n?\z/){eol=$&;''}.split(//).each do |ch|
        h = {}
        lasth.each do |laststr,(lastlen,lasttype)|
          if MAP.key?(ch) && (lasttype != :usascii || /^[\x00-\x7F]$/ =~ MAP[ch])
            [ch, MAP[ch]]
          else
            [ch]
          end.each do |c|
            if /^[\x00-\x7F]$/ === c
              chtype = :usascii
            else
              chtype = :other
            end
            len = c.size
            if lasttype != chtype && lasttype == :usascii
              len += 6
            end
            h[laststr+c] = [lastlen+len, chtype]
          end
        end
        lasth = h
      end
      if $DEBUG
        h.each do |str,(len,_)| #
          jis = NKF.nkf('-jE -m0', str)
          unless jis.size == len
            p '[BUG]',len,[str.size,str],[jis.size,jis]
          end
        end #
        #h.each{|k,v|
        #  puts "he:#{v[0]}\t#{k}"
        #}
      end
      h.keys.min{|a,b|h[a][0]<=>h[b][0]}+eol
    end.join('')
  end
  module_function :min
end

class JisCompactFilter < Filter
  def JisCompactFilter::description
    [
      'JisCompactFilter',
      '全角←→半角で小さくする',
      'iso-2022-jpでバイト数が少なくなるように英数字・記号を全角または半角にします。'
    ]
  end

  def body_filter( body )
    ISO_2022_JP.min( body )
  end
end


