module Agents
  class TwitterActionAgent < Agent
    include TwitterConcern

    cannot_be_scheduled!

    description <<-MD
      The Twitter Action Agent is able to retweet or favorite tweets from the events it receives.

      #{ twitter_dependencies_missing if dependencies_missing? }

      It expects to consume events generated by twitter agents where the payload is a hash of tweet information. The existing TwitterStreamAgent is one example of a valid event producer for this Agent.

      To be able to use this Agent you need to authenticate with Twitter in the [Services](/services) section first.

      Set `expected_receive_period_in_days` to the maximum amount of time that you'd expect to pass between Events being received by this Agent.
      Set `retweet` to either true or false.
      Set `favorite` to either true or false.
      Set `emit_error_events` to true to emit an Event when the action failed, otherwise the action will be retried.
    MD

    def validate_options
      unless options['expected_receive_period_in_days'].present?
        errors.add(:base, "expected_receive_period_in_days is required")
      end
      unless retweet? || favorite?
        errors.add(:base, "at least one action must be true")
      end
      if emit_error_events?.nil?
        errors.add(:base, "emit_error_events must be set to 'true' or 'false'")
      end
    end

    def working?
      last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
    end

    def default_options
      {
        'expected_receive_period_in_days' => '2',
        'favorite' => 'false',
        'retweet' => 'true',
        'emit_error_events' => 'false'
      }
    end

    def retweet?
      boolify(options['retweet'])
    end

    def favorite?
      boolify(options['favorite'])
    end

    def emit_error_events?
      boolify(options['emit_error_events'])
    end

    def receive(incoming_events)
      tweets = tweets_from_events(incoming_events)

      begin
        twitter.favorite(tweets) if favorite?
        twitter.retweet(tweets) if retweet?
      rescue Twitter::Error => e
        raise e unless emit_error_events?
        create_event :payload => {
          'success' => false,
          'error' => e.message,
          'tweets' => Hash[tweets.map { |t| [t.id, t.text] }],
          'agent_ids' => incoming_events.map(&:agent_id),
          'event_ids' => incoming_events.map(&:id)
        }
      end
    end

    def tweets_from_events(events)
      events.map do |e|
        Twitter::Tweet.new(id: e.payload["id"], text: e.payload["text"])
      end
    end
  end
end
