module Logical 
  class Showtime < ActionWebService::Struct 
    def self.get_by_zip_theatre_movie(zip_code, theatre_ids, movie_ids)
      conditions_sql = Array.new 
      conditions_vars = Array.new

      if !zip_code.empty? 
        conditions_sql << "miles_between_lat_long( 
          (select latitude from zip_codes where zip = ?), 
          (select longitude from zip_codes where zip = ?), 
          latitude, longitude) < 15" 

        conditions_vars.concat [zip_code]*2 
      end 

      if !theatre_ids.empty? 
        conditions_sql << "theatre_id in (#{bind_for_array(theatre_ids)})" 
        conditions vars.concat theatre_ids 
      end

      if !movie_ids.empty? 
        conditions_sql <<"movie_id in (#{bind_for_array(movie_ids)})" 
        conditions vars.concat movie_ids 
      end

      conditions_sql << "current is true and sold_out is false" 
      psts = Physical::MovieShowtimeWithCurrentAndSoldOut.find(:all, 
        :select => [:id, :movie_id, :theatre_id, :latitude, :longtitude], 
        :include => [:movie, :theatre], 
        :conditions => [conditions_sql.join(" and "), *conditions_vars]) 
    
      m_hash = Hash.new 
      t_hash = Hash.new 
      st_array = Array.new 
    
      for pst in psts do 
        m_hash[pst.movie_id] ||= Movie.get(pst.movie_id) 
        t_hash[pst.theatre_id] ||= Theatre.get(pst.theatre_id) 
        st_array << ShowtimeLight.new( 
          :movie_id => pst.movie_id, 
          :theatre_id => pst.theatre_id, 
          :start_time => pst.start_time, 
          :auditorium => pst.room 
        ) 
      end 

      ShowtimesResult.new( 
        :movies => m_hash.values, 
        :theatres => t_hash.values, 
        :showtimes_light => st_array 
      ) 
    end 

    def self.bind_for_array(array) 
      (['?']*array.size).join(",") 
    end 
  end 
end 

