#Copyright (C) 2003 Gimite »ÔÀî <gimite@mx12.freecom.ne.jp>

#ÆüËÜ¸ìÊ¸»ú¥³¡¼¥ÉÈ½ÄêÍÑ¥³¥á¥ó¥È
$KCODE= "EUC"
require 'kconv'
require 'jcode'
require $REUDY_DIR+'/reudy_common'


module Gimite


#¸Ä¡¹¤ÎÈ¯¸À
class Message

  def initialize(fromNick_, body_)
    @fromNick= fromNick_
    @body= body_
  end

  attr_accessor :fromNick
  attr_accessor :body

end


#È¯¸À¥í¥°
class MessageLog
  
  include(Gimite)
  
  @enable_update_check= true
  class << self
    attr_accessor(:enable_update_check)
  end
  
  def initialize(innerFileName)
    @innerFileName= innerFileName
    @observers= []
    @msgPoses= [] #¥Õ¥¡¥¤¥ë¾å¤Î³Æ¹Ô¤ÎÀèÆ¬¤Î°ÌÃÖ¡£
    @outerFile= nil
    @sync= true
    addHeadNoticeToInnerFile() if !File.exist?(@innerFileName)
    loadFromInnerFile()
    #È¯¸À¤ÎÄÉ²Ã¤ËÈ÷¤¨¤Æ¡¢ÆâÉô¥Õ¥¡¥¤¥ë¤ò³«¤±¤Ã¤Ñ¤Ê¤·¤Ë¤¹¤ë¡£
    @innerFile= Kernel.open(@innerFileName, File::RDWR | File::APPEND)
    @innerFile.sync= sync
  end
  
  #´Ñ»¡¼Ô¤òÄÉ²Ã¡£
  def addObserver(*observers)
    @observers+= observers
  end
  
  #³°Éô¥Õ¥¡¥¤¥ë¤òÅÐÏ¿¤·¡¢³°Éô¥Õ¥¡¥¤¥ë¤ÎÆâÍÆ¤òÆâÉô¥Ç¡¼¥¿¤ËÈ¿±Ç¤¹¤ë¡£
  def updateByOuterFile(outerFileName)
    msg= nil
    isAdded= false
    if size()==0
      msg= @innerFileName+" ¤¬Í­¤ê¤Þ¤»¤ó¡£ºîÀ®¤·¤Þ¤¹...\n"
      isAdded= true
    elsif MessageLog.enable_update_check && File.mtime(outerFileName) > File.mtime(@innerFileName)
      msg= outerFileName+" ¤¬ÊÑ¹¹¤µ¤ì¤¿¤è¤¦¤Ç¤¹¡£Ä´ººÃæ...\n"
    end
    if msg
      jprint_to($stderr, msg)
      syncBak= sync
      sync= false
      #³°Éô¥Õ¥¡¥¤¥ë¤ÈÆâÉô¥Ç¡¼¥¿¤òÈæ³Ó¤·¡¢ÄÉ²Ã¤¬Í­¤ì¤ÐÄÉ²Ã¤¹¤ë¡£
      n= 0
      eachMsgInFile(outerFileName) do |fromNick, body|
        if n>=size()
          if !isAdded
            jprint_to($stderr, outerFileName+" ¤ËÄÉ²Ã¤µ¤ì¤¿¥í¥°¤òÆÉ¤ß¹þ¤ßÃæ...\n")
            isAdded= true
          end
          jprint_to($stderr, (n+1).to_s()+"¹ÔÌÜ...\n") if (n+1)%100==0
          addMsg(fromNick, body, false)
        else
          jprint_to($stderr, (n+1).to_s()+"¹ÔÌÜ...\n") if (n+1)%10000==0
          break if fromNick!=self[n].fromNick || body!=self[n].body
        end
        n+= 1
      end
      #ÅÓÃæ¤¬ÊÔ½¸¤µ¤ì¤Æ¤¿¤é¡¢ÆâÉô¥Ç¡¼¥¿¤ò°ì¤«¤éºî¤êÄ¾¤¹¡£
      if n<size()
        jprint_to($stderr, outerFileName \
          +" ¤ÎÅÓÃæ¤¬ÊÑ¹¹¤µ¤ì¤Æ¤¤¤Þ¤¹¡£ÆâÉô¥Ç¡¼¥¿¤òºî¤êÄ¾¤·¤Þ¤¹...\n")
        clear()
        n= 0
        eachMsgInFile(outerFileName) do |fromNick, body|
          jprint_to($stderr, (n+1).to_s()+"¹ÔÌÜ...\n") if (n+1)%100==0
          addMsg(fromNick, body, false)
          n+= 1
        end
      end
      sync= syncBak
    end
    #È¯¸À¤ÎÄÉ²Ã¤ËÈ÷¤¨¤Æ¡¢³°Éô¥Õ¥¡¥¤¥ë¤ò³«¤±¤Ã¤Ñ¤Ê¤·¤Ë¤¹¤ë¡£
    @outerFile= open(outerFileName, "a")
    @outerFile.sync= true
  end
  
  #nÈÖÌÜ¤ÎÈ¯¸À
  def [](n)
    if @msgPoses[n]
      @innerFile.pos= @msgPoses[n]
      line= @innerFile.gets()
      @innerFile.seek(0, IO::SEEK_END)
      if line && line.chomp()=~/(.*)\t(.*)/
        return Message.new($1, $2)
      end
    end
    return nil
  end
  
  #È¯¸À¤Î¿ô
  def size()
    return @msgPoses.size()
  end
  
  #È¯¸À¤òÄÉ²Ã
  def addMsg(fromNick, body, toOuter= true)
    @innerFile.seek(0, IO::SEEK_END)
    @msgPoses.push(@innerFile.pos)
    @outerFile.print(fromNick+"\t"+body+"\n") if toOuter && @outerFile
    @innerFile.print(fromNick+"\t"+body+"\n")
    for observer in @observers
      observer.onAddMsg()
    end
  end
  
  #ÆâÉô¥Õ¥¡¥¤¥ë¤Î½ÐÎÏÆ±´ü¥â¡¼¥É¡£
  def sync
    return @sync
  end
  
  #ÆâÉô¥Õ¥¡¥¤¥ë¤Î½ÐÎÏÆ±´ü¥â¡¼¥É¤òÊÑ¹¹¤¹¤ë¡£
  def sync=(s)
    @sync= s
    @innerFile.sync= s if @innerFile
  end
  
  #¥í¥°¥Õ¥¡¥¤¥ë¤ò¥¯¥í¡¼¥º
  def close()
    @file.close()
  end
  
  private
  
  #ÆâÉô¥Õ¥¡¥¤¥ë¤ÎÀèÆ¬¤ËÃí°Õ½ñ¤­¤ò½ñ¤¤¤È¤¯¡£
  def addHeadNoticeToInnerFile()
    Kernel.open(@innerFileName, "a") do |f|
      f.print("¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨\n")
      f.print("¢¨¢¨¢¨¢¨¤³¤Î¥Õ¥¡¥¤¥ë¤Ï¥í¥¤¥Ç¥£ÆâÉô¤Ç»È¤ï¤ì¤ë¥Ç¡¼¥¿¤Ç¤¹¡£                      ¢¨¢¨¢¨¢¨\n")
      f.print("¢¨¢¨¢¨¢¨¥í¥°¤òÊÔ½¸¤¹¤ë¤Ë¤Ï¡¢¤³¤Î¥Õ¥¡¥¤¥ë¤Ç¤Ï¤Ê¤¯¡¢log.txt¤òÊÔ½¸¤·¤Æ¤¯¤À¤µ¤¤¡£ ¢¨¢¨¢¨¢¨\n")
      f.print("¢¨¢¨¢¨¢¨¤³¤Î¥Õ¥¡¥¤¥ë¤òÊÔ½¸¤¹¤ë¤È¡¢¥Ç¡¼¥¿¤¬²õ¤ì¤Þ¤¹¡£                          ¢¨¢¨¢¨¢¨\n")
      f.print("¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨¢¨\n")
    end
  end
  
  #¥í¥°¤òÆâÉô¥Õ¥¡¥¤¥ë¤«¤é¥í¡¼¥É¡£
  def loadFromInnerFile()
    Kernel.open(@innerFileName, "a").close() #¥Õ¥¡¥¤¥ë¤¬Ìµ¤±¤ì¤ÐºîÀ®¡£
    Kernel.open(@innerFileName, "r") do |file|
      pos= 0
      while line= file.gets()
        @msgPoses.push(pos) if line.chomp()=~/(.*)\t(.*)/
        pos= file.pos
      end
    end
  end
  
  #¥í¥°¥Õ¥¡¥¤¥ëÆâ¤Î³ÆÈ¯¸À¤Ë¤Ä¤¤¤Æ·«¤êÊÖ¤¹¡£
  #¥Ö¥í¥Ã¥¯¤ËÅÏ¤µ¤ì¤ë°ú¿ô¤Ï (È¯¸À¼Ô,ÆâÍÆ)
  def eachMsgInFile(fileName, &block)
    return if !File.exist?(fileName)
    Kernel.open(fileName, "r") do |file|
      file.each_line() do |line|
        block.call($1, $2) if line.chomp()=~/(.*)\t(.*)/
      end
    end
  end
  
  #ÆâÉô¥Ç¡¼¥¿¤ò¥¯¥ê¥¢
  def clear()
    for observer in @observers
      observer.onClearLog()
    end
    @msgPoses= []
    @innerFile.close() if @innerFile
    @innerFile= open(@innerFileName, File::RDWR | File::CREAT | File::TRUNC)
    @innerFile.sync= sync
  end
  
end


end #module Gimite


