module Stream
  module Fires
    def self.included(klass)
      klass.send(:extend, ClassMethods)
    end

    module ClassMethods
      def fires(activity_type, opts)
        raise ArgumentError, "Argument :on is mandatory" unless opts.has_key?(:on)

        # Array provided, set multiple callbacks
        if opts[:on].kind_of?(Array)
          opts[:on].each { |on| fires(activity_type, opts.merge({:on => on})) }
          return
        end

        opts[:subject] = :self unless opts.has_key?(:subject)

        method_name = :"fire_#{activity_type}_after_#{opts[:on]}"
        define_method(method_name) do
          create_options = [:actor, :subject, :secondary_subject].inject({}) do |memo, sym|
            if opts[sym]
              if opts[sym].respond_to?(:call)
                memo[sym] = opts[sym].call(self)
              elsif opts[sym] == :self
                memo[sym] = self
              else
                memo[sym] = send(opts[sym])
              end
            end
            memo
          end
          
          create_options[:activity_type] = activity_type.to_s
          
          transaction do
            activity = ActivityItem.new(create_options)
            if activity_type.to_s.eql?'new_message'
              activity.subject.recipient.activity_items << activity
            elsif activity_type.to_s.eql?'new_photo'
              
              gallery = activity.subject.gallery
              photo = activity.subject
              # Find recent photo activity
              last_activity = ActivityItem.find(:first, :conditions => ["subject_type = ? AND subject_id = ? AND DATE(updated_at) = current_date",
                                                photo.class,photo.id])

              unless last_activity && (gallery.eql?(last_activity.subject.gallery))
                ([activity.actor] + gallery.allowed_contacts).each do |p| 
                  activity.is_hidden = activity.subject.approval_status==true ? true : false 
                  activity.photos << activity.subject
                  activity.save
                  p.activity_items << activity
                  send(:"after_#{opts[:on]}", method_name, :if => opts[:if])
                end
              else
                last_activity.photos << activity.subject
                last_activity.save
              end
            else
              activity.save  
              ([activity.actor] + activity.actor.contacts).each{|p| p.activity_items << activity }
              send(:"after_#{opts[:on]}", method_name, :if => opts[:if])
            end
          end
        end

      end
    end
  end
end