# frozen_string_literal: true

# Redmine - project management software
# Copyright (C) 2006-  Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

module MembersHelper
  def render_principals_for_new_members(project, limit=100)
    scope = Principal.active.visible.sorted.not_member_of(project).like(params[:q])
    principal_count = scope.count
    principal_pages = Redmine::Pagination::Paginator.new principal_count, limit, params['page']
    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).to_a
    s =
      content_tag(
        'div',
        content_tag(
          'div',
          principals_check_box_tags('membership[user_ids][]', principals),
          :id => 'principals'
        ),
        :class => 'objects-selection'
      )
    links =
      pagination_links_full(principal_pages,
                            principal_count,
                            :per_page_links => false) do |text, parameters, options|
        link_to(
          text,
          autocomplete_project_memberships_path(
            project,
            parameters.merge(:q => params[:q], :format => 'js')
          ),
          :remote => true)
      end
    s + content_tag('span', links, :class => 'pagination')
  end

  def member_status_options
    [
      [l(:label_all), ''],
      [l(:status_active), User::STATUS_ACTIVE.to_s],
      [l(:status_locked), User::STATUS_LOCKED.to_s]
    ]
  end

  # Returns the scope of the members of project matching the filters
  # set in the request params
  def members_scope(project)
    scope =
      project.memberships.
        like(params[:member_name]).
        with_role(params[:member_role_id])
    if User.current.allowed_to?(:manage_members, project)
      scope.status(params[:member_status])
    else
      scope.active
    end
  end

  # limit/offset on Member.sorted would paginate role join rows, not members
  def paginate_members(scope)
    ordered_ids = scope.sorted.pluck("#{Member.table_name}.id").uniq
    member_count = ordered_ids.size
    member_pages = Redmine::Pagination::Paginator.new(member_count, per_page_option, params['members_page'], 'members_page')
    page_ids = ordered_ids[member_pages.offset, member_pages.per_page] || []
    members_by_id = scope.where(:id => page_ids).preload(:project, :principal, :roles).index_by(&:id)
    members = page_ids.filter_map {|id| members_by_id[id]}
    [members, member_pages, member_count]
  end

  # Returns the params that define the members list currently displayed
  # (pagination and filters), so that they can be preserved across the member
  # creation, edition and deletion requests
  def members_list_params
    {
      :members_page => params[:members_page],
      :member_name => params[:member_name],
      :member_role_id => params[:member_role_id],
      :member_status => params[:member_status]
    }.select {|_, value| value.present?}
  end

  # Returns inheritance information for an inherited member role
  def render_role_inheritance(member, role)
    content = member.role_inheritance(role).filter_map do |h|
      if h.is_a?(Project)
        l(:label_inherited_from_parent_project)
      elsif h.is_a?(Group)
        l(:label_inherited_from_group, :name => h.name.to_s)
      end
    end.uniq

    if content.present?
      content_tag('em', content.join(", "), :class => "info")
    end
  end

  def members_to_csv(members)
    Redmine::Export::CSV.generate(encoding: params[:encoding]) do |csv|
      # csv headers
      csv << [l(:field_principal), l(:field_type), l(:label_role), l(:label_project)]

      # csv lines
      members.each do |member|
        member.roles.each do |role|
          csv << [
            member.principal.name,
            member.principal.is_a?(Group) ? l(:label_group) : l(:label_user),
            role.name,
            member.project.name
          ]
        end
      end
    end
  end
end
