     operation = $set : { status: 'accepted' }
     @update operation, callback
 
+
+  # some selects result set for invitations, it adds group name automatically
+  @some$:  permit 'send invitations',
+    success: (client, selector, options, callback) ->
+      groupName = client.context.group or 'koding'
+
+      selector or= {}
+      selector.groupName = groupName # override group name in any case
+      selector.status  or= "pending"
+
+      { limit }       = options
+      options.sort  or= createdAt : -1
+      options.limit or= 25
+      options.limit   = Math.min options.limit, 25 # admin can fetch max 25 record
+      options.skip    = 0
+
+      console.log selector, options
+      JInvitation.some selector, options, callback
+
+  @search$:  permit 'send invitations',
+    success: (client, query, options, callback) ->
+      selector = { $or : [ {'name' : ///^#{query}/// }, {'email' : ///^#{query}/// } ]}
+
+      JInvitation.some$ client, selector, options, callback
+
+  # create creates JInvitation documents for all given invitations and
+  # triggers sendInvitationEmail
+  @create: permit 'send invitations',
+    success: (client, options, callback) ->
+
+      { delegate }        = client.connection
+      { invitations }     = options
+      groupName           = client.context.group or 'koding'
+      name                = getName delegate
+
+      queue = invitations.map (invitation) -> ->
+        { email, firstName, lastName } = invitation
+
+        code = generateInvitationCode email, groupName
+
+        data = {
+          code
+          email
+          groupName
+        }
+        # firstName and lastName are optional
+        data.firstName = firstName  if firstName
+        data.lastName  = lastName  if lastName
+
+        invite = new JInvitation data
+        invite.save (err) ->
+          return callback err   if err
+
+          JInvitation.sendInvitationEmail client, invite, -> queue.fin()
+
+      dash queue, callback
+
+
+
+  # byCode fetches an invitation by its code
   @byCode: (code, callback) ->
     @one {code}, callback
 
+  # sendInvitationByCode sends email according to data stored in
+  # JInvitation selected by given code
+  @sendInvitationByCode: permit 'send invitations',
+    success: (client, code, callback) ->
+
+      JInvitation.byCode code, (err, invitation)->
+        return callback err  if err
+
+        JInvitation.sendInvitationEmail client, invitation, callback
+
+  # sendInvitationEmail sends email according to given JInvitation
+  @sendInvitationEmail: (client, invitation, callback) ->
+    invitee      = getName client.connection.delegate
+
+    options =
+      to      : invitation.email,
+      subject : Email.types.INVITE
+
+    properties =
+      groupName: invitation.groupName
+      invitee  : invitee
+      link     : "#{protocol}//#{invitation.groupName}.#{hostname}/Invitation/#{encodeURIComponent invitation.code}"
+
+    Email.queue invitation.email, options, properties, callback
+
+
+  getName = (delegate) ->
+    { nickname, firstName, lastName } = delegate.profile.nickname
+
+    name = nickname
+
+    if "#{firstName}" is not ""
+      name = firstName
+
+    if "#{lastName}" is not ""
+      name = "#{name} #{lastName}"
+
+    return name
+
   # TODO - generate a better invitation code
-  @generateInvitationCode = (email, group) ->
+  generateInvitationCode = (email, group) ->
     code = crypto.createHmac 'sha1', 'kodingsecret'
     code.update email
     code.update group
     code.digest 'hex'
-
-  @create: secure (client, options, callback) ->
-
-    { groupName, delegate } = client.connection
-    { invitations }         = options
-    groupName             or= 'koding'
-    name                    = getName delegate
-
-    queue = invitations.map (invitation) => =>
-      { email, firstName, lastName } = invitation
-
-      code = @generateInvitationCode email, groupName
-
-      invite = new JInvitation {
-        code
-        email
-        groupName
-        firstName
-        lastName
-      }
-
-      invite.save (err) ->
-        return callback err   if err
-
-        options =
-          to      : email,
-          subject : Email.types.INVITE
-
-        properties =
-          groupName: groupName
-          invitee  : name
-          link     : "#{protocol}//#{groupName}.#{hostname}/Invitation/#{encodeURIComponent code}"
-
-        Email.queue email, options, properties, -> queue.fin()
-
-    dash queue, callback
-
-  getName = (delegate) ->
-    { nickname, firstName, lastName } = delegate.profile.nickname
-
-    name = nickname
-
-    if "#{firstName}" is not ""
-      name = firstName
-
-    if "#{lastName}" is not ""
-      name = "#{name} #{lastName}"
-
-    return name

    sharedMethods   :

      instance:
        remove:
          (signature Function)

      static:
        create:
          (signature Object, Function)
        byCode:
          (signature String, Function)

    sharedEvents    :
      static        : []

        type        : Date
        default     : -> new Date

  # remove deleted invitation from database
  remove$: permit 'send invitations',
    success: (client, callback) ->
      @remove callback
