module ScrivitoEditors
  # This module includes helpers that render the HTML for specfic CMS
  # attributes and their JS editors. These special methods are needed
  # because the editors need additional information that is not provided
  # by the Scrivito SDK's ++scrivito_tag++ method.
  module ScrivitoTagHelper

    # Allows you to edit a CMS ++enum++ attribute using a dropdown
    #
    # @param [Obj, Widgegt] object
    # @param [String, Symbol] attribute_name
    # @param [Hash] options passed to the ++scrivito_tag++ helper
    def scrivito_edit_enum(object, attribute_name, options = {})
      values = object.obj_class.attributes[attribute_name].values
      values |= [object[attribute_name].to_s]

      options.reverse_merge!({
        data: {
          values: values,
          min: values.min,
          max: values.max,
        }
      })

      scrivito_tag(:div, object, attribute_name, options)
    end

    # Allows you to edit a CMS ++multienum++ attribute using a multi-select.
    #
    # @param [Obj, Widget] object
    # @param [String, Symbol] attribute_name
    # @param [Hash] options passed to the ++scrivito_tag++ helper
    def scrivito_edit_multienum(object, attribute_name, options = {})
      values = object.obj_class.attributes[attribute_name].values

      options.reverse_merge!({
        multiple: true,
        data: {
          values: values,
        }
      })

      scrivito_tag(:div, object, attribute_name, options) do |tag|
        (object[attribute_name] || []).join(', ')
      end
    end

    # Allows you to edit a CMS ++reference++ attribute using the resource
    # browser.
    #
    # @param [Obj, Widget] object
    # @param [String, Symbol] attribute_name
    # @param [Hash] options passed to the ++scrivito_tag++ helper
    def scrivito_edit_reference(object, attribute_name, options = {})
      reference = object[attribute_name]

      scrivito_tag(:div, object, attribute_name, options) do
        if reference
          reference.description_for_editor
        end
      end
    end

    # Allows you to edit a CMS ++referencelist++ attribute using the resource
    # browser.
    #
    # @param [Obj, Widget] object
    # @param [String, Symbol] attribute_name
    # @param [Hash] options passed to the ++scrivito_tag++ helper
    def scrivito_edit_referencelist(object, attribute_name, options = {})
      reference_list = object[attribute_name]

      scrivito_tag(:div, object, attribute_name, options) do
        if reference_list.present?
          content_tag(:ul) do
            html = ''.html_safe

            reference_list.each do |reference|
              html << content_tag(:li, data: { name: reference.name, id: reference.id }) do
                content_tag(:span, reference.description_for_editor, class: 'list-content')
              end
            end

            html
          end
        end
      end
    end

    # Allows you to edit a CMS ++linklist++ attribute
    #
    # @param [Obj, Widget] object
    # @param [String, Symbol] attribute_name
    # @param [Hash] options passed to the ++scrivito_tag++ helper
    def scrivito_edit_linklist(object, attribute_name, options = {})
      linklist = object[attribute_name]

      scrivito_tag(:div, object, attribute_name, options) do
        if linklist
          content_tag(:ul) do
            html = ''.html_safe

            linklist.each do |link|
              html << _edit_link_li(link)
            end

            html
          end
        end
      end
    end

    # Allows you to edit a CMS ++link++ attribute
    #
    # @param [Obj, Widget] object
    # @param [String, Symbol] attribute_name
    # @param [Hash] options passed to the ++scrivito_tag++ helper
    def scrivito_edit_link(object, attribute_name, options = {})
      link = object[attribute_name]

      scrivito_tag(:div, object, attribute_name, options) do
        content_tag(:ul) { _edit_link_li(link) } if link
      end
    end

    private

    def _edit_link_li(link)
      query = link.query.present? ? "?#{link.query}" : ""
      url = link.internal? ? scrivito_path(link).sub(/\?.*/, query) : link.url
      description = link.internal? ? link.obj.description_for_editor : link.url
      data = { title: link.title, url: url }
      data[:id] = link.obj.id if link.internal?

      content_tag(:li, data: data) do
        content_tag(:span, class: 'list-content') do
          "#{link.title} #{link_to(description, url, target: :_blank)}".html_safe
        end
      end
    end
  end
end