module ActionView
  module Helpers
    module FormHelper
      alias_method :orig_form_for, :form_for

      attr_accessor :_strong_form_permitted_attributes

      def form_for(record, options = {}, &block)
        # explicilty passed
        if options.key?(:permitted_attributes)
          self._strong_form_permitted_attributes = options.delete(:permitted_attributes)
          record.permitted_attributes =
            _strong_form_permitted_attributes if record.respond_to?(:permitted_attributes=)
        # assigned to object
        elsif record.respond_to?(:permitted_attributes)
          self._strong_form_permitted_attributes = record.permitted_attributes
        end

        orig_form_for(record, options, &block)
      end

      def assign_child_permitted_attributes!(
        record_name, record_object, parent_permitted_attributes
      )
        if parent_permitted_attributes == true # parent allowed everything
          record_object.permitted_attributes = parent_permitted_attributes
          return
        end

        # search for nested attributes

        # record_name is of the form `user[child_models_attributes][0]`
        # try to extract `child_models_attributes`
        permitted_name =
          record_name.match(/.*?\[([^\]\[]+)\](\[[0-9]+\])?$/)[1].to_sym

        # find the hash with the key `child_models_attributes`
        record_object.permitted_attributes =
          StrongForm::Finder.find_child_permitted_attributes(
            permitted_name, parent_permitted_attributes
          )
      end
      private :assign_child_permitted_attributes!

      # https://github.com/rails/rails/blob/4-2-stable/actionview/lib/action_view/helpers/form_helper.rb#L712
      def fields_for(record_name, record_object = nil, options = {}, &block)
        assign_child_permitted_attributes!(
          record_name, record_object, options[:parent_builder].object.permitted_attributes
        ) if _strong_form_permitted_attributes && record_object.respond_to?(:permitted_attributes=) && record_object.permitted_attributes.nil?

        builder = instantiate_builder(record_name, record_object, options)
        capture(builder, &block)
      end
    end
  end
end