class PinBall
  attr_accessor :x
  attr_accessor :y  
  attr_accessor :prev_x
  attr_accessor :prev_y    
  attr_accessor :velX
  attr_accessor :velY   
  attr_accessor :accX
  attr_accessor :accY   
  attr_accessor :forces
  attr_accessor :impulses
  attr_accessor :mass
  attr_accessor :non_collide
  attr_accessor :collision
  attr_accessor :collide_objects
  
  def initialize(mass , x,y,velX ,velY)
    @x = x
    @y = y
    @velX = velX
    @velY = velY
    @accX = 0.0
    @accY = 0.0  
    @prev_x = 0.0
    @prev_y = 0.0    
    @mass = mass
    @forces = [[0.0,0.0]]
    @impulses = [[0.0,0.0]]
    @non_collide = false
#~     @collision = false
    @collide_objects = []
  end
  
  def position
    [@x,@y]
  end   
  
  def vel
    [@velX,@velY]
  end  
  
  def update

    @prev_x = x
    @prev_y = y 
    if !@collide_objects.empty?
      @collide_objects.each do |edge| 
        newpoint = ball_position_after_collision(edge)
        @x = newpoint[0]
        @y = newpoint[1]

      end  
    else  
      @x += @velX 
      @y += @velY      
    end  
    update_acc
    update_vel 
    

    reflect_ball
#~     @collision = false
    clear_collide_objects
  end 
  def destination
    VectorCalc.add(position , vel)
  end    
  def clear_forces
    @forces = [[0.0,0.0]]
  end  


  def clear_impulses
    @impulses = [[0.0,0.0]]
  end   

  def clear_collide_objects
    @collide_objects = []
  end    
  
#~   
#~   # ● 辺と衝突しているか？
#~   def collide_edge?(edge)
#~     return false if @non_collide
#~     if @prev_x != @x
#~       (edge.y_value(@prev_x) - @prev_y) * (edge.y_value(@x) - @y) < 0
#~     else  
#~       (edge.x_value(@prev_y) - @prev_x) * (edge.x_value(@y) - @x) < 0
#~     end  
#~   end

  
  def reflect_ball
    @velX *= -1 if @x <= 20 && @velX < 0
    @velX *= -1 if @x >= 500 && @velX > 0    
    @velY *= -0.8 if @y >= 400 && @velY > 0 

  end  
  
  def update_acc
    @forces.each do |force|
      @accX = force[0] / @mass
      @accY = force[1] / @mass
    end
  end  
  def update_vel
    @velX += @accX
    @velY += @accY   
  
    @velX += inpulse_add_vel[0]
    @velY += inpulse_add_vel[1] 
  end   
  def inpulse_add
    VectorCalc.add2(@impulses)
  end  
  
  def inpulse_add_vel 
    VectorCalc.scalar_action( 1 / @mass , inpulse_add )
  end  
  #●軌道に対する法線ベクトルを求める 
  def normal_vector
    [@velY , - @velX] 
  end  
  
  #●軌道に対する法線ベクトルを求める (正規化)
  def normalized_normal_vector
    VectorCalc.normalize(normal_vector)
  end    
    
  # ● ボールと衝突した辺の位置
  def get_point_collision(edge)
    bconst = VectorCalc.inner_product(normal_vector , position)
    econst = VectorCalc.inner_product(edge.normal_vector , edge.vertex_position(0))
    det = normal_vector[0] * edge.normal_vector[1] - normal_vector[1] * edge.normal_vector[0] 
    x = (bconst * edge.normal_vector[1] - econst * normal_vector[1]) / det
    y = (econst * normal_vector[0] - bconst * edge.normal_vector[0]) / det
    return [x,y]
  end   

  
 # ● 辺と衝突した時間
  def collision_time(edge)
    cpoint = get_point_collision(edge)
    if @velX.abs >=  0.001 
      return ((@x - cpoint[0]) / @velX ).abs
    elsif @velY.abs >=  0.001 
      return ((@y - cpoint[1]) / @velY ).abs
    else  
      return 0
    end  
      
  end  
 # ● 辺と衝突した時間
  def collision_time_left(edge)
#~    sjofjeosfj if collision_time(edge) > 1
    1.0 - collision_time(edge)
  end    
  
  
  
  # ● 辺と衝突した後のボールの位置
  def ball_position_after_collision(edge)
    cpoint = get_point_collision(edge)
    d = VectorCalc.scalar_action(collision_time_left(edge) , inpulse_add_vel)
    new_point =  VectorCalc.add(cpoint ,d)
  end  
  
end  