# workaround for https://github.com/einzige/date_time_attribute/issues/14
require 'date_time_attribute'

module DateTimeAttributeValidate
  extend ActiveSupport::Concern
  include DateTimeAttribute

  module ClassMethods
    def date_time_attribute(*attributes)
      super

      attributes.each do |attribute|
        validate -> { self.send("#{attribute}_datetime_value_valid") }

        # allow resetting the field to nil
        before_validation do
          if self.instance_variable_get("@#{attribute}_is_set")
            date = self.instance_variable_get("@#{attribute}_date_value")
            time = self.instance_variable_get("@#{attribute}_time_value")
            if date.blank? && time.blank?
              self.send("#{attribute}=", nil)
            end
          end
        end

        # remember old date and time values
        define_method("#{attribute}_date_value=") do |val|
          self.instance_variable_set("@#{attribute}_is_set", true)
          self.instance_variable_set("@#{attribute}_date_value", val)
          self.send("#{attribute}_date=", val) rescue nil
        end
        define_method("#{attribute}_time_value=") do |val|
          self.instance_variable_set("@#{attribute}_is_set", true)
          self.instance_variable_set("@#{attribute}_time_value", val)
          self.send("#{attribute}_time=", val) rescue nil
        end

        # fallback to field when values are not set
        define_method("#{attribute}_date_value") do
          self.instance_variable_get("@#{attribute}_date_value") || self.send("#{attribute}_date").try { |e| e.strftime('%Y-%m-%d') }
        end
        define_method("#{attribute}_time_value") do
          self.instance_variable_get("@#{attribute}_time_value") || self.send("#{attribute}_time").try { |e| e.strftime('%H:%M') }
        end

        private

        # validate date and time
        define_method("#{attribute}_datetime_value_valid") do
          date = self.instance_variable_get("@#{attribute}_date_value")
          unless date.blank? || (Date.parse(date) rescue nil)
            errors.add(attribute, "is not a valid date") # @todo I18n
          end
          time = self.instance_variable_get("@#{attribute}_time_value")
          unless time.blank? || (Time.parse(time) rescue nil)
            errors.add(attribute, "is not a valid time") # @todo I18n
          end
        end
      end
    end
  end
end