'use strict'

Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScope", "$state", '$uibModal', 'Auth', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers'
, ($scope, $rootScope, $state, $uibModal, Auth, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) ->



    ### PUBLIC SCOPE ###

    ## list of groups
    $scope.groups = groupsPromise

    ## default : do not show the group changing form
    ## group ID of the current/selected user
    $scope.group =
        change: false
        id: null

    ## list of plans, classified by group
    $scope.plansClassifiedByGroup = []
    for group in groupsPromise
      groupObj = { id: group.id, name: group.name, plans: [] }
      for plan in plansPromise
        groupObj.plans.push(plan) if plan.group_id == group.id
      $scope.plansClassifiedByGroup.push(groupObj)

    ## user to deal with
    $scope.ctrl =
      member: null
      member_id: null

    ## already subscribed plan of the current user
    $scope.paid =
        plan: null

    ## plan to subscribe (shopping cart)
    $scope.selectedPlan = null

    ## Discount coupon to apply to the basket, if any
    $scope.coupon =
      applied: null

    ## Storage for the total price (plan price + coupon, if any)
    $scope.cart =
      total: null

    ## text that appears in the bottom-right box of the page (subscriptions rules details)
    $scope.subscriptionExplicationsAlert = subscriptionExplicationsPromise.setting.value

    ##
    # Callback to deal with the subscription of the user selected in the dropdown list instead of the current user's
    # subscription. (admins only)
    ##
    $scope.updateMember = ->
      $scope.selectedPlan = null
      $scope.paid.plan = null
      $scope.group.change = false
      Member.get {id: $scope.ctrl.member.id}, (member) ->
        $scope.ctrl.member = member
        $scope.group.id = $scope.ctrl.member.group_id




    ##
    # Add the provided plan to the shopping basket
    # @param plan {Object} The plan to subscribe to
    ##
    $scope.selectPlan = (plan) ->
      if $scope.isAuthenticated()
        if $scope.selectedPlan != plan
          $scope.selectedPlan = plan
          updateCartPrice()
        else
          $scope.selectedPlan = null
      else
        $scope.login()



    ##
    # Callback to trigger the payment process of the subscription
    ##
    $scope.openSubscribePlanModal = ->
      Wallet.getWalletByUser {user_id: $scope.ctrl.member.id}, (wallet) ->
        amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount)
        if $scope.currentUser.role isnt 'admin' and amountToPay > 0
          payByStripe()
        else
          if $scope.currentUser.role is 'admin' or amountToPay is 0
            payOnSite()



    ##
    # Return the group object, identified by the ID set in $scope.group.id
    ##
    $scope.getUserGroup = ->
      for group in $scope.groups
        if group.id == $scope.group.id
          return group



    ##
    # Change the group of the current/selected user to the one set in $scope.group.id
    ##
    $scope.selectGroup = ->
      Member.update {id: $scope.ctrl.member.id}, {user: {group_id: $scope.group.id}}, (user) ->
        $scope.ctrl.member = user
        $scope.group.change = false
        if $scope.currentUser.role isnt 'admin'
          $rootScope.currentUser = user
          Auth._currentUser.group_id = user.group_id
          growl.success(_t('your_group_was_successfully_changed'))
        else
          growl.success(_t('the_user_s_group_was_successfully_changed'))
      , (err) ->
        if $scope.currentUser.role isnt 'admin'
          growl.error(_t('an_error_prevented_your_group_from_being_changed'))
        else
          growl.error(_t('an_error_prevented_to_change_the_user_s_group'))
        console.error(err)


    ##
    # Return an enumerable meaninful string for the gender of the provider user
    # @param user {Object} Database user record
    # @return {string} 'male' or 'female'
    ##
    $scope.getGender = (user) ->
      if user and user.profile
        if user.profile.gender == "true" then 'male' else 'female'
      else 'other'



    ##
    # Test if the provided date is in the future
    # @param dateTime {Date}
    # @return {boolean}
    ##
    $scope.isInFuture = (dateTime)->
      if moment().diff(moment(dateTime)) < 0
        true
      else
        false



    ### PRIVATE SCOPE ###

    ##
    # Kind of constructor: these actions will be realized first when the controller is loaded
    ##
    initialize = ->
      if $scope.currentUser
        if $scope.currentUser.role isnt 'admin'
          $scope.ctrl.member = $scope.currentUser
          $scope.paid.plan = $scope.currentUser.subscribed_plan
          $scope.group.id = $scope.currentUser.group_id

      $scope.$on 'devise:new-session', (event, user)->
        $scope.ctrl.member = user

      # watch when a coupon is applied to re-compute the total price
      $scope.$watch 'coupon.applied', (newValue, oldValue) ->
        unless newValue == null and oldValue == null
          updateCartPrice()



    ##
    # Compute the total amount for the current reservation according to the previously set parameters
    # and assign the result in $scope.reserve.amountTotal
    ##
    updateCartPrice = ->
      # first we check that a user was selected
      if Object.keys($scope.ctrl.member).length > 0
        $scope.cart.total = $scope.selectedPlan.amount
        # apply the coupon if any
        if $scope.coupon.applied
          if $scope.coupon.applied.type == 'percent_off'
            discount = $scope.cart.total * $scope.coupon.applied.percent_off / 100
          else if $scope.coupon.applied.type == 'amount_off'
            discount =  $scope.coupon.applied.amount_off
          $scope.cart.total -= discount
      else
        $scope.reserve.amountTotal = null


    ##
    # Open a modal window which trigger the stripe payment process
    ##
    payByStripe = ->
      $uibModal.open
        templateUrl: '<%= asset_path "stripe/payment_modal.html" %>'
        size: 'md'
        resolve:
          selectedPlan: -> $scope.selectedPlan
          member: -> $scope.ctrl.member
          price: -> $scope.cart.total
          wallet: ->
            Wallet.getWalletByUser({user_id: $scope.ctrl.member.id}).$promise
          coupon: -> $scope.coupon.applied
        controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'price', 'Subscription', 'CustomAsset', 'wallet', 'helpers', '$filter', 'coupon',
        ($scope, $uibModalInstance, $state, selectedPlan, member, price, Subscription, CustomAsset, wallet, helpers, $filter, coupon) ->
          # User's wallet amount
          $scope.walletAmount = wallet.amount

          # Final price to pay by the user
          $scope.amount = helpers.getAmountToPay(price, wallet.amount)

          # The plan that the user is about to subscribe
          $scope.selectedPlan = selectedPlan

          # Used in wallet info template to interpolate some translations
          $scope.numberFilter = $filter('number')

          # retrieve the CGV
          CustomAsset.get {name: 'cgv-file'}, (cgv) ->
            $scope.cgv = cgv.custom_asset

          ##
          # Callback for click on the 'proceed' button.
          # Handle the stripe's card tokenization process response and save the subscription to the API with the
          # card token just created.
          ##
          $scope.payment = (status, response) ->
            if response.error
              growl.error(response.error.message)
            else
              $scope.attempting = true
              Subscription.save
                coupon_code: (coupon.code if coupon)
                subscription:
                  plan_id: selectedPlan.id
                  user_id: member.id
                  card_token: response.id
              , (data, status) -> # success
                $uibModalInstance.close(data)
              , (data, status) -> # failed
                $scope.alerts = []
                $scope.alerts.push({msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' })
                $scope.attempting = false
        ]
      .result['finally'](null).then (subscription)->
        $scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
        Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
        $scope.paid.plan = angular.copy($scope.selectedPlan)
        $scope.selectedPlan = null
        $scope.coupon.applied = null



    ##
    # Open a modal window which trigger the local payment process
    ##
    payOnSite = ->
      $uibModal.open
        templateUrl: '<%= asset_path "plans/payment_modal.html" %>'
        size: 'sm'
        resolve:
          selectedPlan: -> $scope.selectedPlan
          member: -> $scope.ctrl.member
          price: -> $scope.cart.total
          wallet: ->
            Wallet.getWalletByUser({user_id: $scope.ctrl.member.id}).$promise
          coupon: -> $scope.coupon.applied
        controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'price', 'Subscription', 'wallet', 'helpers', '$filter', 'coupon',
        ($scope, $uibModalInstance, $state, selectedPlan, member, price, Subscription, wallet, helpers, $filter, coupon) ->
          # user wallet amount
          $scope.walletAmount = wallet.amount

          # subcription price, coupon subtracted if any
          $scope.price = price

          # price to pay
          $scope.amount = helpers.getAmountToPay($scope.price, wallet.amount)

          # Used in wallet info template to interpolate some translations
          $scope.numberFilter = $filter('number')

          # The plan that the user is about to subscribe
          $scope.plan = selectedPlan

          # The member who is subscribing a plan
          $scope.member = member

          # Button label
          if $scope.amount > 0
            $scope.validButtonName = _t('confirm_payment_of_html', {ROLE:$scope.currentUser.role, AMOUNT:$filter('currency')($scope.amount)}, "messageformat")
          else
            if price.price > 0 and $scope.walletAmount == 0
              $scope.validButtonName = _t('confirm_payment_of_html', {ROLE:$scope.currentUser.role, AMOUNT:$filter('currency')(price.price)}, "messageformat")
            else
              $scope.validButtonName = _t('confirm')

          ##
          # Callback for the 'proceed' button.
          # Save the subscription to the API
          ##
          $scope.ok = ->
            $scope.attempting = true
            Subscription.save
              coupon_code: (coupon.code if coupon)
              subscription:
                plan_id: selectedPlan.id
                user_id: member.id
            , (data, status) -> # success
              $uibModalInstance.close(data)
            , (data, status) -> # failed
              $scope.alerts = []
              $scope.alerts.push({msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' })
              $scope.attempting = false

          ##
          # Callback for the 'cancel' button.
          # Close the modal box.
          ##
          $scope.cancel = ->
            $uibModalInstance.dismiss('cancel')
        ]
      .result['finally'](null).then (reservation)->
        $scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
        Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
        $scope.ctrl.member = null
        $scope.paid.plan = angular.copy($scope.selectedPlan)
        $scope.selectedPlan = null
        $scope.coupon.applied = null



    ## !!! MUST BE CALLED AT THE END of the controller
    initialize()
]
