#!/usr/bin/env ruby

require 'active_samba_ldap'
require 'active_samba_ldap/command'

include ActiveSambaLdap::GetTextSupport

argv, opts, options = ActiveSambaLdap::Command.parse_options do |opts, options|
  options.gid = nil
  options.allow_non_unique_gid_number = false
  options.new_group_name = nil
  options.members_to_add = nil
  options.members_to_delete = nil

  opts.banner += " GROUP_NAME"

  opts.on("-g", "--gid=GID", _("GID number")) {|options.gid|}
  opts.on("--[no-]allow-non-unique-gid",
          _("gid can be non unique"),
          "(#{options.allow_non_unique_gid_number})") do |bool|
    options.allow_non_unique_gid_number = bool
  end
  opts.on("-r", "--rename=NEW_NAME",
          _("new group name")) {|options.new_group_name|}
  opts.on("-a", "--add-members=MEMBER1,MEMBER2,MEBMER3", Array,
          _("add members (comma delimited)")) {|options.members_to_add|}
  opts.on("-d", "--delete-members=MEMBER1,MEMBER2,MEBMER3", Array,
          _("delete members (comma delimited)")) {|options.members_to_delete|}
end

name = nil
if argv.size == 1
  name = argv.first
else
  $stderr.puts opts
  exit 1
end

unless Process.uid.zero?
  $stderr.puts(_("need root authority."))
  exit 1
end

ActiveSambaLdap::Base.setup_connection("update")

class Group < ActiveSambaLdap::Group
  ldap_mapping
end

class User < ActiveSambaLdap::User
  ldap_mapping
end

class Computer < ActiveSambaLdap::Computer
  ldap_mapping
end

unless Group.exists?(name)
  $stderr.puts(_("group doesn't exist: %s") % name)
  exit 1
end
group = Group.find(name)

if options.gid
  begin
    group.change_gid_number(options.gid, options.allow_non_unique_gid_number)
  rescue ActiveSambaLdap::GidNumberAlreadyExists
    $stderr.puts $!.message
    exit 1
  end
end

if options.members_to_add and options.members_to_delete
  duplicated_members = options.members_to_add & options.members_to_delete
  unless duplicated_members.empty?
    format =
      n_("there is duplicated member in adding and deleting members: %s",
         "there are duplicated members in adding and deleting members: %s",
         duplicated_members.size)
    $stderr.puts(format % duplicated_members.join(", "))
    exit 1
  end
end

if options.members_to_add
  users = []
  computers = []
  options.members_to_add.each do |member|
    if /\$$/ =~ member
      computers << Computer.find(member)
    else
      users << User.find(member)
    end
  end
  group.users.concat(users)
  group.computers.concat(computers)
end

if options.members_to_delete
  users = []
  computers = []
  options.members_to_delete.each do |member|
    if /\$$/ =~ member
      computers << Computer.find(member)
    else
      users << User.find(member)
    end
  end
  group.users -= users
  group.computers -= computers
end

group.save!

if options.new_group_name
  if Group.exists?(options.new_group_name)
    $stderr.puts(_("group already exists: %s") % options.new_group_name)
    exit 1
  end

  new_group = Group.new(options.new_group_name)
  new_group.attributes = group.attributes.reject do |key, value|
    %w(cn).include?(key)
  end
  primary_members = group.primary_members
  group.gid_number = nil
  new_group.save!
  primary_members.each do |member|
    member.primary_group = new_group
    member.save!
  end
  group.destroy(:remove_members => true)
end

ActiveSambaLdap::Base.restart_nscd

ActiveSambaLdap::Base.clear_active_connections!
