# bugaifile.rb
# Copyright (C) by GFD-Dennou Club, 2002.  All rights reserved.

require 'numru/gpv/fortseqfile'

=begin
= class BugaiFile
気象庁部外提供ファイル形式
=end

module NumRu

  class BugaiFile < FortSeqFile

    class DataRecord

	def initialize (str, version = 0)
	    if (version == 0) then
		@id, @payload = str.unpack('a32a*')
	    else
		@id, @payload = str.unpack('a80a*')
	    end
	end

	attr_reader :id, :payload

	def decode
	    case code
	    when 'DGRB'
	        require 'numru/gpv/dgrb'
	        DGRB::new(@payload)
	    else
		@payload
	    end
	end

	def code
	    @payload[0,4]
	end

	def inspect
	    "<DataRecord id=#{@id.dump} code=#{code.dump}>"
	end

    end

    def initialize (filename, mode='r')
        super(filename, mode, 'N')
	nom, payload = get_record
	raise FormatError, "magic in 1st record" if nom != 'VREC'
	@creator, @version = payload.unpack('a80' + endian)
	if (@version == 0) then
	    nom, payload = get_record
    	    raise FormatError, "magic in 2nd record" if nom != 'CNTL'
	    @basetime = Time::utc(*payload.unpack('x16a4a2a2a2a2')\
		.collect{|x| x.to_i})
	else
	    @basetime = nil
	end
    end

    attr_reader :creator, :version, :basetime

=begin
--- f.read_record
    1レコード読んで、レコード名とデータ部からなる配列を返す。
    ファイル終了時には EOFError 例外を起こす。
--- f.get_record
    同上、ただしファイル終了時に空配列を返す。
=end

    def read_record
        rec = super
	nom, vrecl = rec.unpack('a4' + endian)
        payload = rec.unpack("x12a#{vrecl-12}")[0]
	payload = DataRecord::new(payload.slice(0, vrecl), @version) \
	    if nom == "DATA"
	[nom, payload]
    end

    def get_record
	begin
	    read_record
	rescue EOFError
	    []
	end
    end

=begin
--- f.each {|rec| ...}
    ファイル中のすべての 'DATA' レコードについて
    与えられた手続を呼び返す。
    ファイル終端または 'END ' レコードで終了。
=end

    def each
	while true do
	    nom, payload = get_record
	    break if (nom.nil? || nom == 'END ')
	    next if (nom != 'DATA')
	    yield payload
	end
    end

    def self::debug
	ARGV.each { |fnam|
	    fp = self::new(fnam, "r")
	    p fp.basetime if fp.version == 0
	    fp.each { |rec|
	        p rec, rec.decode
	    }
	    fp.close
	}
    end

    def self::extract
	fname = ARGV.shift
	indices = Hash::new
	if ARGV.empty? then
	    all_mode = true
        else
	    all_mode = false
	    ARGV.each { |n|
		indices[Integer(n)] = true
	    }
	end
	fp = self::new(fname, "r")
	i = 0
	fp.each { |rec|
	    # preprocess
	    i += 1
	    next if !(all_mode || indices[i])
	    # decode
	    id = rec.id.squeeze(' ').sub(/^ /, "").sub(/ $/, '').gsub(/ /, '.')
	    p id
	    File::open(id, 'w') { |ofp|
		 ofp.binmode
		 ofp.write rec.payload
            }
	    # postprocess
	    if (!all_mode) then
		indices.delete i
		break if indices.length == 0
	    end
	}
	fp.close
    end

  end
end







