require "old_vector.rb"

class Body

  TAG = "particle"

  attr_accessor :mass, :pos, :vel, :acc, :type

  def initialize(mass = 0, pos = Vector[0,0,0], vel = Vector[0,0,0])
    @mass, @pos, @vel = mass, pos, vel
    @type = nil
  end

  def to_s(precision = 16, base_indentation = 0, additional_indentation = 2)
    subtag = if @type then " "+@type else "" end
    indent = base_indentation + additional_indentation
    return " " * base_indentation + "begin " + TAG + subtag + "\n" +
      f_to_s("mass", mass, precision, indent) +
      f_v_to_s("position", pos, precision, indent) +
      f_v_to_s("velocity", vel, precision, indent) +
      " " * base_indentation + "end" + "\n"
  end

  def f_to_s(name, value, precision, indentation)  # from floating-point number
    " " * indentation +
      name + " = " + sprintf(" %#{precision+8}.#{precision}e\n", value)
  end

  def f_v_to_s(name, value, precision, indentation)   # from floating-pt vector
    " " * indentation + name + " = " + 
      value.map{|x| sprintf(" %#{precision+8}.#{precision}e", x)}.join + "\n"
  end

  def write(file = $stdout, precision = 16,
            base_indentation = 0, additional_indentation = 2)
    file.print to_s(precision, base_indentation, additional_indentation)
  end

  def read(header, file = $stdin)                                            
    raise unless header =~ /^\s*begin\s+particle/
    a = header.split
    if a.size > 2
      a.shift
      a.shift
      @type = a.join(" ")
    end
    loop {
      s = file.gets
      name = s.split[0]
      case name
        when /^mass/
          @mass = s_to_f(s)
        when /^position/
          @pos = s_to_f_v(s)
        when /^velocity/
          @vel = s_to_f_v(s)
        when "begin"
          subread(file, s)
        when "end"
          break
        else                                                                 
          raise                                                              
      end
    }
  end

  def subread
  end

  def s_to_f(s)                               # string to floating-point number
    s.split("=")[1].to_f
  end

  def s_to_f_v(s)                             # string to floating-point vector
    s.split("=")[1].split.map{|x| x.to_f}.to_v
  end

end