class Object
  # GIVES US THE ABILITY TO ADD DYNMAIC CLASS METHODS TO THE STATUSES MODULE....
  # http://ryanangilly.com/post/234897271/dynamically-adding-class-methods-in-ruby
  def metaclass
    class << self; self; end
  end
end

module EntityStatus
  extend ActiveSupport::Concern
  module ClassMethods
    def entity_status(column_name="status",status_array = [], options = { destroyed_status: nil})
      status_array = (status_array.count > 0) ? status_array : %W(pending open closed)

      if options[:destroyed_status]
        status_array << options[:destroyed_status]
        self.set_default_scope(column_name, options[:destroyed_status])
        
        define_method 'destroyed_status' do
          options[:destroyed_status]
        end
      end
      
      self.create_statuses_method(column_name.to_s.pluralize,status_array)
      status_array.each do |st|
        self.create_finder_methods(column_name,st)
        # add dynamic state setters based on the status string
        # example: Post.first.pending #=> 'pending'
        define_method st do
          self.send("#{column_name}=".to_sym,st.to_s)
          self
        end
        
        # Add boolean state checks based on the status string
        # example: Post.first.pending? #=> true
        define_method "#{st}?" do
          (self.send(column_name) == st) ? true :false
        end
      end
      
    end
    
    def set_default_scope(column_name,destroyed_status)
      self.default_scope {where.not(column_name.to_sym => destroyed_status)}
      # klass = self.to_s
      # metaclass.instance_eval do
      #   default_scope where.not(column_name.to_sym => destroyed_status)
      # end
    end
    
    def create_statuses_method(name,statuses)
      klass = self.to_s
      metaclass.instance_eval do
        # attr_accessor :statuses        
        # @@statuses = statuses
        define_method(name){
          return statuses
        }
      end
    end

    def create_finder_methods(column_name,name)
      klass = self.to_s
      metaclass.instance_eval do
        define_method(name){
          where(column_name.to_sym => name)
        }
      end
    end
    
  end

  module InstanceMethods
    def dependant_state_update(state)
      self.update_attributes status: state
      self.reflections.each do |rel|
        if rel.last.klass.method_defined? :dependant_state_update
          if rel.last.options[:dependent] == :destroy
            items = [] + self.send(rel.last.name)
            items.each do |item|
              item.dependant_state_update state
            end
          end
        end
      end
    end
    
  end

  def self.included(receiver)
    receiver.extend         ClassMethods
    receiver.send :include, InstanceMethods
    receiver.entity_status if receiver.respond_to? :entity_status
      
    if receiver.method_defined?(:attr_accessible)
      receiver.attr_accessible :status
      receiver.attr_accessible :destroyed_status
      # receiver.after_create :default_status
    end
  end
end