-jraphical = require 'jraphical'
-
-JAccount = require '../account'
-JUser = require '../user'
-JVM = require '../vm'
+jraphical   = require 'jraphical'
 KodingError = require '../../error'
-{argv}   = require 'optimist'
-KONFIG = require('koding-config-manager').load("main.#{argv.c}")
-
+
+JAccount    = require '../account'
+JUser       = require '../user'
+
+{argv}      = require 'optimist'
+KONFIG      = require('koding-config-manager').load("main.#{argv.c}")
 
 module.exports = class JReferral extends jraphical.Message
 

    username = client.connection.delegate.profile.nickname
    JAccount.some { referrerUsername : username }, options, callback

  @redeem = secure (client, data, callback)->
    {vmName, size, type} = data
    return callback new KodingError "Request is not valid" unless vmName and size

    # get redeemable referals
    @fetchRedeemableReferrals client, {type}, (err, referrals)=>
      return callback err if err

      # check user has enough credit
      # for loop also checks for 0 length referrals
      totalCredit = 0
      totalCredit += referral.amount for referral in referrals

      # if not return an error
      return callback new KodingError "You dont have enough credit to redeem" if size > totalCredit

      # fetch user's vmName which will be upgraded
      @fetchUserVM client, vmName, (err, vm)=>
        return callback err if err
        options =
          referrals :referrals
          vm        :vm
          size      :size
          type      :type

        @relateReferalsToJVM options, callback

  @createUpdateQueryForRedeem = (type, amount) ->
    switch type
      when "disk" then return 'diskSizeInMB': amount
      else
        return console.error "Invalid type provided"

  @relateReferalsToJVM = (options, callback) ->
    {referrals, vm, size, type} = options
    # generate the referals to be used for upgrade process
    referralsToBeUsed = []
    addedSize = 0
    for referral in referrals
      break if addedSize >= size
      addedSize += referral.amount
      referralsToBeUsed.push referral

    # wrap the callback
    kallback = (err)=>
      return callback err if err

      returnValue =
        addedSize    : addedSize
        vm           : vm.hostnameAlias
        type         : type
        unit         : referrals.first.unit

      updateQuery = @createUpdateQueryForRedeem type, addedSize

      vm.update { $inc: updateQuery }, (err) ->
        return callback err if err
        callback null, returnValue

    queue = referralsToBeUsed.map (ref)=>=>
      ref.addRedeemedOn vm, (err)->
        return kallback err if err
        queue.fin()

    dash queue, kallback

  @fetchUserVM = (client, vmName, callback)->
    account = client.connection.delegate

    # get the user to fetch his/her VMs
    account.fetchUser (err, user) ->
      return callback err  if err
      selector =
        users:
          $elemMatch:
            id: user.getId()
        hostnameAlias: vmName
      # get user's vms
      JVM.one selector, (err, vm)->
        return callback err  if err
        return callback new KodingError "#{vm} is not found" unless vm
        callback null, vm

  @addExtraReferral: secure (client, options, callback)->
    {delegate} = client.connection


  @share()

  @set

    sharedMethods     :

      static          :
        addExtraReferral:
          (signature Object, Function)
        fetchReferredAccounts:
          (signature Object, Object, Function)

    sharedEvents      :
      static          : []
      instance        : []

    schema            :
      # for now we only have disk space
      type            :
        type          : String
      unit            :
        type          : String
      amount          :
        type          : Number
      sourceCampaign  :
        type          : String
        default       : "register"
      createdAt       :
        type          : Date
        default       : -> new Date


  @fetchReferredAccounts$ = secure (client, query, options, callback)->
    @fetchReferredAccounts client, query, options, callback
