angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, StatusMessage, Columns, SortOptions, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, VariantUnitManager, RequestMonitor) ->
  $scope.initialized = false
  $scope.RequestMonitor = RequestMonitor
  $scope.filteredLineItems = []
  $scope.confirmDelete = true
  $scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
  $scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
  $scope.bulkActions = [ { name: t("admin.orders.bulk_management.actions_delete"), callback: 'deleteLineItems' } ]
  $scope.selectedUnitsProduct = {}
  $scope.selectedUnitsVariant = {}
  $scope.sharedResource = false
  $scope.columns = Columns.columns
  $scope.sorting = SortOptions

  $scope.confirmRefresh = ->
    LineItems.allSaved() || confirm(t("unsaved_changes_warning"))

  $scope.resetSelectFilters = ->
    $scope.distributorFilter = 0
    $scope.supplierFilter = 0
    $scope.orderCycleFilter = 0
    $scope.quickSearch = ""

  $scope.refreshData = ->
    unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0
      $scope.startDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_open_at).format('YYYY-MM-DD')
      $scope.endDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_close_at).startOf('day').format('YYYY-MM-DD')

    formatted_start_date = moment($scope.startDate).format()
    formatted_end_date = moment($scope.endDate).add(1,'day').format()

    RequestMonitor.load $scope.orders = Orders.index(
      "q[state_not_eq]": "canceled",
      "q[completed_at_not_null]": "true",
      "q[completed_at_gteq]": formatted_start_date,
      "q[completed_at_lt]": formatted_end_date
    )

    RequestMonitor.load $scope.lineItems = LineItems.index(
      "q[order][state_not_eq]": "canceled",
      "q[order][completed_at_not_null]": "true",
      "q[order][completed_at_gteq]": formatted_start_date,
      "q[order][completed_at_lt]": formatted_end_date
    )

    unless $scope.initialized
      RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
      RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
      RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")

    RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise, $scope.suppliers.$promise, $scope.lineItems.$promise]).then ->
      Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID
      Dereferencer.dereferenceAttr $scope.orders, "order_cycle", OrderCycles.byID
      Dereferencer.dereferenceAttr $scope.lineItems, "supplier", Enterprises.byID
      Dereferencer.dereferenceAttr $scope.lineItems, "order", Orders.byID
      $scope.bulk_order_form.$setPristine()
      StatusMessage.clear()
      unless $scope.initialized
        $scope.initialized = true
        $timeout ->
          $scope.resetSelectFilters()

  $scope.$watch 'bulk_order_form.$dirty', (newVal, oldVal) ->
    if newVal == true
      StatusMessage.display 'notice', t('js.unsaved_changes')

  $scope.submit = ->
    if $scope.bulk_order_form.$valid
      StatusMessage.display 'progress', t('js.saving')
      $q.all(LineItems.saveAll()).then(->
        StatusMessage.display 'success', t('js.all_changes_saved')
        $scope.bulk_order_form.$setPristine()
      ).catch ->
        StatusMessage.display 'failure', t "unsaved_changes_error"
    else
      StatusMessage.display 'failure', t "unsaved_changes_error"

  $scope.deleteLineItem = (lineItem) ->
    if ($scope.confirmDelete && confirm(t "are_you_sure")) || !$scope.confirmDelete
      LineItems.delete lineItem, =>
        $scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1

  $scope.deleteLineItems = (lineItems) ->
    existingState = $scope.confirmDelete
    $scope.confirmDelete = false
    $scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
    $scope.confirmDelete = existingState

  $scope.allBoxesChecked = ->
    checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
      count + (if lineItem.checked then 1 else 0 )
    , 0
    checkedCount == $scope.filteredLineItems.length

  $scope.toggleAllCheckboxes = ->
    changeTo = !$scope.allBoxesChecked()
    lineItem.checked = changeTo for lineItem in $scope.filteredLineItems

  $scope.setSelectedUnitsVariant = (unitsProduct,unitsVariant) ->
    $scope.selectedUnitsProduct = unitsProduct
    $scope.selectedUnitsVariant = unitsVariant

  $scope.sumUnitValues = ->
    sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
      sum + lineItem.final_weight_volume
    , 0

  $scope.sumMaxUnitValues = ->
    sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
        sum + lineItem.max_quantity * lineItem.units_variant.unit_value
    , 0

  $scope.allFinalWeightVolumesPresent = ->
    for i,lineItem of $scope.filteredLineItems
      return false if !lineItem.hasOwnProperty('final_weight_volume') || !(lineItem.final_weight_volume > 0)
    true

  # How is this different to OptionValueNamer#name?
  # Should it be extracted to that class or VariantUnitManager?
  $scope.formattedValueWithUnitName = (value, unitsProduct, unitsVariant) ->
    # A Units Variant is an API object which holds unit properies of a variant
    if unitsProduct.hasOwnProperty("variant_unit") && (unitsProduct.variant_unit == "weight" || unitsProduct.variant_unit == "volume") && value > 0
      scale = VariantUnitManager.getScale(value, unitsProduct.variant_unit)
      Math.round(value/scale * 1000)/1000 + " " + VariantUnitManager.getUnitName(scale, unitsProduct.variant_unit)
    else
      ''

  $scope.fulfilled = (sumOfUnitValues) ->
    # A Units Variant is an API object which holds unit properies of a variant
    if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size") && $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
      $scope.selectedUnitsProduct.hasOwnProperty("variant_unit") &&
      ( $scope.selectedUnitsProduct.variant_unit == "weight" || $scope.selectedUnitsProduct.variant_unit == "volume" )
        Math.round( sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size * 1000)/1000
    else
      ''

  $scope.unitsVariantSelected = ->
    !angular.equals($scope.selectedUnitsVariant,{})

  $scope.weightAdjustedPrice = (lineItem) ->
    if lineItem.final_weight_volume > 0
      unit_value = lineItem.final_weight_volume / lineItem.quantity
      pristine_unit_value = LineItems.pristineByID[lineItem.id].final_weight_volume / LineItems.pristineByID[lineItem.id].quantity
      lineItem.price = LineItems.pristineByID[lineItem.id].price * (unit_value / pristine_unit_value)

  $scope.unitValueLessThanZero = (lineItem) ->
    if lineItem.units_variant.unit_value <= 0
      true
    else
      false

  $scope.updateOnQuantity = (lineItem) ->
    if lineItem.quantity > 0
      lineItem.final_weight_volume = LineItems.pristineByID[lineItem.id].final_weight_volume * lineItem.quantity / LineItems.pristineByID[lineItem.id].quantity
      $scope.weightAdjustedPrice(lineItem)

  $scope.refreshData()
