module Castable
  extend ActiveSupport::Concern

  included do
    def self.cast_as_boolean(attribute, bit=false)
      define_method(attribute) do |*args|
        if bit
          super(*args) == "\u0001"
        else
          !super(*args).zero?
        end
      end

      define_method("#{attribute}=".to_sym) do |val|
        if bit
          super(val ? "\u0001" : "\u0000")
        else
          super(val ? 1 : 0)
        end
      end
    end

    private_class_method :cast_as_boolean

    def self.cast_as_date(attribute)
      define_method(attribute) do |*args|
        return if super(*args).nil?

        ActiveSupport::TimeZone['UTC'].at(super(*args)).to_date
      end

      define_method("#{attribute}=".to_sym) do |val|
        val.nil? ? super(nil) : super(val.to_time.to_i)
      end
    end

    private_class_method :cast_as_date

    def self.cast_as_editor_content(attribute)
      define_method(attribute) do |*args|
        return if super(*args).nil?

        super(*args).gsub('<a href', '<a target="_blank" href')
      end

      define_method("#{attribute}=".to_sym) do |val|
        super(val)
      end
    end

    private_class_method :cast_as_editor_content
  end
end
