require "uri"

module Web
  class Agent
    class LIRS
      include Enumerable
      def initialize
        @records = []
      end
      attr_accessor :records

      def each
        @records.each {|record|
          yield record
        }
      end

      def to_s
        s = ''
        @records.each {|record|
          s << record.to_s
        }
        s
      end

      def <<(rec)
        @records << rec
        self
      end

      def delete_older(limit)
        t = Time.now.utc.to_i - limit
        @records.delete_if {|rec|
          rec.last_modified < t
        }
      end

      def merge(lirs)
        lirs.each {|rec|
          my_rec = @records.find {|r|
            rec.url.downcase == r.url.downcase
          }
          if my_rec
            if rec.author != "0" && !rec.author.empty?
              my_rec.author = rec.author
            end
            if rec.last_modified >= my_rec.last_modified
              my_rec.url            = rec.url
              my_rec.last_modified  = rec.last_modified
              my_rec.last_detected  = rec.last_detected
              my_rec.gmt_diff       = rec.gmt_diff
              my_rec.content_length = rec.content_length
              my_rec.title          = rec.title
              my_rec.from           = rec.from
            end
          else
            @records << rec
          end
        }
      end

      def parse(io,site)
        io.each {|text|
          text.chomp!
          next unless text=~/\ALIRS,/e
          values = []
          value = ''
          prev = 0
          text.each_byte {|c|
            case c
            when ?,
              if prev==?\\
                value << c
              else
                values << value
                value = ''
              end
              prev = c
            when ?\\
              if prev==?\\
                value << c
                prev = 0
              else
                prev = c
              end
            else
              value << c
              prev = c
            end
          }
          #
          rec = Record.new
          values.shift                           # LIRS
          rec.last_modified  = values.shift.to_i # Last-Modfied
          rec.last_detected  = values.shift.to_i # Last-Detected
          rec.gmt_diff       = values.shift.to_i # GMT Diff
          rec.content_length = values.shift.to_i # content_length
          uri = URI.parse(values.shift).normalize
          rec.url            = uri.to_s          # URL
          rec.title          = values.shift      # title
          rec.author         = values.shift      # author
          rec.from           = values.shift      # data from
          if rec.from !~ /\Ahttp:/
            rec.from=site
          end
          @records << rec
        }
        @records
      end
      
      class Record
        def initialize
          @last_modified  = nil
          @last_detected  = nil
          @gmt_diff       = nil
          @content_length = nil
          @url            = nil
          @title          = nil
          @author         = nil
          @from           = nil
        end
        attr_accessor :last_modified, :last_detected, :gmt_diff
        attr_accessor :content_length, :url, :title, :author, :from

        def to_s
          values = []
          values << "LIRS"
          values << @last_modified.to_s
          values << @last_detected.to_s
          values << @gmt_diff.to_s
          values << @content_length.to_s
          values << escape(@url)
          values << escape(@title)
          values << escape(@author)
          values << escape(@from)
          values << ",\n"
          values.join(",")
        end

        def escape(str)
          str.gsub(/\\/,'\\\\\\').gsub(/,/,'\\,')
        end
      end # Record
    end # LIRS
  end # Agent
end # Web
