class Rodauth::Feature

def self.define(name, constant=nil, &block)

def self.define(name, constant=nil, &block)
  feature = new
  feature.dependencies = []
  feature.routes = []
  feature.feature_name = name
  configuration = feature.configuration = FeatureConfiguration.new
  feature.module_eval(&block)
  configuration.def_configuration_methods(feature)
  # :nocov:
  if constant
  # :nocov:
    Rodauth.const_set(constant, feature)
    Rodauth::FeatureConfiguration.const_set(constant, configuration)
  end
  FEATURES[name] = feature
end

def additional_form_tags(name=feature_name)

def additional_form_tags(name=feature_name)
  auth_value_method(:"#{name}_additional_form_tags", nil)
end

def auth_cached_method(meth, iv=:"@#{meth}")

def auth_cached_method(meth, iv=:"@#{meth}")
  umeth = :"_#{meth}"
  define_method(meth) do
    if instance_variable_defined?(iv)
      instance_variable_get(iv)
    else
      instance_variable_set(iv, send(umeth))
    end
  end
  alias_method(meth, meth)
  auth_private_methods(meth)
end

def auth_value_method(meth, value)

def auth_value_method(meth, value)
  define_method(meth){value}
  auth_value_methods(meth)
end

def configuration_module_eval(&block)

def configuration_module_eval(&block)
  configuration.module_eval(&block)
end

def def_deprecated_alias(new, old)

def def_deprecated_alias(new, old)
  configuration_module_eval do
    define_method(old) do |*a, &block|
      warn("Deprecated #{old} method used during configuration, switch to using #{new}", *DEPRECATED_ARGS)
      send(new, *a, &block)
    end
  end
  define_method(old) do
    warn("Deprecated #{old} method called at runtime, switch to using #{new}", *DEPRECATED_ARGS)
    send(new)
  end
end

def depends(*deps)

def depends(*deps)
  dependencies.concat(deps)
end

def internal_request_method(name=feature_name)

def internal_request_method(name=feature_name)
  (@internal_request_methods ||= []) << name
end

def loaded_templates(v)

def loaded_templates(v)
  define_method(:loaded_templates) do
    super().concat(v)
  end
  private :loaded_templates
end

def redirect(name=feature_name, &block)

def redirect(name=feature_name, &block)
  meth = :"#{name}_redirect"
  block ||= DEFAULT_REDIRECT_BLOCK
  define_method(meth, &block)
  auth_value_methods meth
end

def route(name=feature_name, default=name.to_s.tr('_', '-'), &block)

def route(name=feature_name, default=name.to_s.tr('_', '-'), &block)
  route_meth = :"#{name}_route"
  auth_value_method route_meth, default
  define_method(:"#{name}_path"){|opts={}| route_path(send(route_meth), opts)}
  define_method(:"#{name}_url"){|opts={}| route_url(send(route_meth), opts)}
  handle_meth = :"handle_#{name}"
  internal_handle_meth = :"_#{handle_meth}"
  before route_meth
  define_method(internal_handle_meth, &block)
  define_method(handle_meth) do
    request.is send(route_meth) do
      check_csrf if check_csrf?
      _around_rodauth do
        before_rodauth
        send(internal_handle_meth, request)
      end
    end
  end
  routes << handle_meth
end

def session_key(meth, value)

def session_key(meth, value)
  define_method(meth){convert_session_key(value)}
  auth_value_methods(meth)
end

def translatable_method(meth, value)

def translatable_method(meth, value)
  define_method(meth){translate(meth, value)}
  auth_value_methods(meth)
end

def view(page, title, name=feature_name)

def view(page, title, name=feature_name)
  meth = :"#{name}_view"
  title_meth = :"#{name}_page_title"
  translatable_method(title_meth, title)
  define_method(meth) do
    view(page, send(title_meth))
  end
  auth_methods meth
end