module RulesEngine
  module Rule
    class <%=rule_class%> < RulesEngine::Rule::Definition

      attr_reader :match_words
      attr_reader :match_type
      
      WORD_MATCH_ANY         = 0 unless defined? WORD_MATCH_ANY
      WORD_MATCH_WORD        = 1 unless defined? WORD_MATCH_WORD
      WORD_MATCH_BEGIN_WITH  = 2 unless defined? WORD_MATCH_BEGIN_WITH
      WORD_MATCH_END_WITH    = 3 unless defined? WORD_MATCH_END_WITH
      
      ##################################################################
      # class options
      self.options = 
        {
          :group => 'Twitter',
          :display_name => 'Twitter Word Filter',    
          :help_partial => '/re_rules/<%=rule_name%>/help',
          :new_partial => '/re_rules/<%=rule_name%>/new',
          :edit_partial => '/re_rules/<%=rule_name%>/edit'
        } 
  
      ##################################################################
      # set the rule data
      def data= data
        if data.nil?
          @title = nil
          @match_words = nil
          @match_type = WORD_MATCH_ANY
        else
          @title, @match_words, tmp_match_type = ActiveSupport::JSON.decode(data)
          @match_type =tmp_match_type.to_i
        end  
      end
  
      ##################################################################
      # get the rule attributes
      def title
        @title
      end

      def summary
        "Filter out tweets with the #{match_words.size == 1 ? 'word' : 'words'} #{match_words.join(', ')}"
      end
  
      def data
        [title, match_words, match_type.to_s].to_json
      end
  
      def expected_outcomes
          [{:outcome => RulesEngine::Rule::Outcome::NEXT}]
      end
  
      ##################################################################
      # set the rule attributes
      def attributes=(params)
        param_hash = params.symbolize_keys

        @title = param_hash[:<%=rule_name%>_title]
    
        @match_words = []
        return if param_hash[:<%=rule_name%>_match_words].nil?
        param_hash[:<%=rule_name%>_match_words].each do |key, values| 
          if values.is_a?(Hash)
            word_hash = values.symbolize_keys
            @match_words << word_hash[:word].downcase unless word_hash[:word].blank? || word_hash[:_delete] == '1'
          end  
        end
        
        @match_type = param_hash[:match_type].to_i
      end
  
      ##################################################################
      # validation and errors
      def valid?
        @errors = {}
        @errors[:<%=rule_name%>_title] = "Title required" if title.blank?    
        @errors[:<%=rule_name%>_match_words] = "At least one word must be defined" if match_words.nil? || match_words.empty?
        return @errors.empty?
      end

      ##################################################################
      # callbacks when the rule is added and removed from a workflow
      def before_create()
      end
  
      def before_update()
      end
      
      def before_destroy()
      end
  
      ##################################################################
      # execute the rule
      # if a match is found procees to the expected outcome
      # it gets the data parameter :tweet
      # it sets the data parameter :match
      def process(process_id, plan, data)
        tweet_words = data[:tweet_words]
        if tweet_words.nil? || tweet_words.empty?
          return RulesEngine::Rule::Outcome.new(RulesEngine::Rule::Outcome::NEXT) 
        end
      
        data[:tweet_words] = tweet_words.select do | tweet |
          !match_words.any? do |word|
            case match_type
            when RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_ANY
              tweet =~ /#{word}/i
            when RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_WORD
              tweet =~ /^#{word}$/i
            when RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_BEGIN_WITH
              (tweet =~ /^#{word}/i) != nil
            when RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_END_WITH
              tweet =~ /#{word}$/i
            end
          end
        end  
        
        RulesEngine::Rule::Outcome.new(RulesEngine::Rule::Outcome::NEXT)
      end      
    end
  end
end