import ModalBase from 'ember-cli-dunlop/mixins/modal-base'

import lookupValidator from 'ember-changeset-validations'
import Changeset from 'ember-changeset'
import ModelValidations from 'ember-panda/validations/workflow-action-definition'
import add_business_day_computations from 'ember-panda/utils/business-day-computations'
import { value_type_options } from 'ember-panda/models/panda/workflow-action-definition'
ESC_KEY = 27
Component =
  _initEscListener: ->
    closeOnEscapeKey = (ev) =>
      @send 'rollback_and_close' if ev.keyCode is ESC_KEY
    Ember.$('body').on('keyup.modal-dialog', closeOnEscapeKey)
  value_type_options: value_type_options
  constraint_types: Ember.A(['warn', 'restrict'])
  lastSelectedWorkflowGroup: null
  lastSelectedWorkflowActionDefinition: null
  selectedConstraintType: 'warn'
  possible_organizations: []
  connection_types: ['info', 'constraint'] # could be warning in future as well

  new_workflow_action_constraint_warning: ''
  new_workflow_action_offset_warning: ''
  #new_workflow_action_offset_offset_value: 0
  #new_workflow_action_offset_offset_unit: 'day'
  #new_workflow_action_offset_offset_business_days: (-> [ 1, 2, 3, 4, 5 ]).property()
  #new_workflow_action_offset_batch_element_threshold_value: 0
  #new_workflow_action_offset_batch_element_threshold_unit: 'businessday'
  #new_workflow_action_offset_batch_element_threshold_business_days: (-> [ 1, 2, 3, 4, 5 ]).property()
  #select_action_offset_base_alert: ''

  attached_to_workflow_action: null
  attached_to_workflow_action_workflow_group: null
  possible_attached_to_workflow_action_workflow_action_definitions: []
  attached_to_connection_conditional_base_value: ''
  attached_to_connection_warning: ''

  working_workflow_action_offsets: Ember.A()
  non_deleted_working_workflow_action_offsets: Ember.computed 'working_workflow_action_offsets.@each.isDeleted', -> @get('working_workflow_action_offsets').rejectBy('isDeleted')

  working_pointing_workflow_action_connections: Ember.A()
  non_deleted_working_pointing_workflow_action_connections: Ember.computed 'working_pointing_workflow_action_connections.@each.isDeleted', -> @get('working_pointing_workflow_action_connections').rejectBy('isDeleted')

  #working_workflow_action_constraints: Ember.A()
  #used_workflow_action_definitions_for_offset: Ember.computed 'working_workflow_action_offsets.@each.isDeleted', ->
  #  @get('working_workflow_action_offsets').rejectBy('isDeleted').mapBy('base_workflow_action_definition.id')
  #used_workflow_action_definitions_for_constraint: Ember.computed 'working_workflow_action_constraints.@each.isDeleted', ->
  #  @get('working_workflow_action_constraints').rejectBy('isDeleted').mapBy('constraint_workflow_action_definition.id')

  offset_type_none:      Ember.computed.equal 'model.changeset.offset_type', 'none'
  offset_type_attached: Ember.computed.equal 'model.changeset.offset_type', 'attached'
  offset_type_configured:    Ember.computed.equal 'model.changeset.offset_type', 'configured'

  willOpenModal: ->
    @_initEscListener()
    @get('model.workflow_group').then (workflow_group) =>
      @set 'lastSelectedWorkflowGroup', workflow_group
    @set 'possible_organizations', @store.peekAll('panda/organization')

    # CONNECTION SETUP
    if workflow_action_connection = @get('model.workflow_action_connections').findBy('connection_type', 'attached')
      @set 'attached_to_workflow_action', workflow_action_connection.get('base_workflow_action_definition.content')
      @set 'attached_to_workflow_action_workflow_group', @get('attached_to_workflow_action.workflow_group.content')
      @set 'attached_to_connection_conditional_base_value', workflow_action_connection.get('conditional_base_value')
    else # same group of configuring action
      @set 'attached_to_workflow_action_workflow_group', @get('model.workflow_group.content')
    unless @get('attached_to_workflow_action_workflow_group') # fallback to first available group
      @set 'attached_to_workflow_action_workflow_group', @get('model.project.workflow_groups.firstObject')
    if connection_group = @get('attached_to_workflow_action_workflow_group')
      @set 'possible_attached_to_workflow_action_workflow_action_definitions', connection_group.get('sorted_workflow_action_definitions').rejectBy('id', @get('model.id'))


    changeset = new Changeset(@get('model'), lookupValidator(ModelValidations), ModelValidations)
    add_business_day_computations changeset, 'offset'
    add_business_day_computations changeset, 'batch_element_threshold'
    @set 'model.changeset', changeset
    model_id = @get('model.id')
    @get('model.workflow_action_offsets').then (workflow_action_offsets) =>
      @set('working_workflow_action_offsets', workflow_action_offsets.toArray())
      workflow_action_offsets.forEach (workflow_action_offset) ->
        if selector_workflow_group = workflow_action_offset.get('base_workflow_action_definition.workflow_group.content')
          workflow_action_offset.set 'selector_workflow_group', selector_workflow_group
          workflow_action_offset.set 'filtered_workflow_action_definitions', selector_workflow_group.get('sorted_workflow_action_definitions').rejectBy('id', model_id)
        base_action = workflow_action_offset.get('base_workflow_action_definition.content')
        workflow_action_offset.set 'x_based', !base_action
        workflow_action_offset.set 'original_base_workflow_action_definition', base_action
    @get('model.pointing_workflow_action_connections').then (pointing_workflow_action_connections) =>
      @set('working_pointing_workflow_action_connections', pointing_workflow_action_connections.toArray())
      pointing_workflow_action_connections.forEach (pointing_workflow_action_connection) ->
        if selector_workflow_group = pointing_workflow_action_connection.get('workflow_action_definition.workflow_group.content')
          pointing_workflow_action_connection.set 'selector_workflow_group', selector_workflow_group
          pointing_workflow_action_connection.set 'filtered_workflow_action_definitions', selector_workflow_group.get('sorted_workflow_action_definitions').rejectBy('id', model_id)
        original_action = pointing_workflow_action_connection.get('workflow_action_definition.content')
        pointing_workflow_action_connection.set 'original_workflow_action_definition', original_action
    #@get('model.workflow_action_constraints').then => @set('working_workflow_action_constraints', arguments[0].toArray())

  actions:
    #newWorkflowActionConstraint: (constraint_workflow_action_definition, event) ->
    #  @set 'new_workflow_action_constraint_warning', ''
    #  return unless constraint_workflow_action_definition
    #  $(event.target).val('')
    #  if @get('used_workflow_action_definitions_for_constraint').includes(constraint_workflow_action_definition.get('id'))
    #    @set 'new_workflow_action_constraint_warning',
    #      t('workflow_action_definition.edit_workflow_action_definition.workflow_action_definition_already_used', constraint_workflow_action_definition.toJSON?())
    #    return
    #  constraint = @store.createRecord 'panda/workflow-action-constraint',
    #    type: @get('selectedConstraintType')
    #    workflow_action_definition: @get('model')
    #    constraint_workflow_action_definition: constraint_workflow_action_definition
    #  @get('working_workflow_action_constraints').addObject constraint

    #newWorkflowActionOffset: (base_workflow_action_definition, event) ->
    #  base_workflow_action_definition = @get('attached_to_workflow_action')
    #  offset_value = parseInt(@get('new_workflow_action_offset_offset_value')) || 0
    #  if @get('offset_type_workflow_action_definition') and not base_workflow_action_definition
    #    @set 'new_workflow_action_offset_warning',
    #      t('workflow_action_definition.edit_workflow_action_definition.no_action_offset_base_given_alert')
    #    return
    #  if @get('used_workflow_action_definitions_for_offset').includes(base_workflow_action_definition.get('id'))
    #    @set 'new_workflow_action_offset_warning',
    #      t('workflow_action_definition.edit_workflow_action_definition.workflow_action_definition_already_used', base_workflow_action_definition.toJSON?())
    #    @set 'attached_to_workflow_action', null
    #    return
    #  @set 'new_workflow_action_offset_warning', ''
    #  offset = @store.createRecord 'workflow-action-offset',
    #    offset_value: offset_value
    #    offset_unit: @get('new_workflow_action_offset_offset_unit')
    #    offset_business_days: @get('new_workflow_action_offset_offset_business_days')
    #    batch_element_threshold_value: @get('new_workflow_action_offset_batch_element_threshold_value')
    #    batch_element_threshold_unit: @get('new_workflow_action_offset_batch_element_threshold_unit')
    #    batch_element_threshold_business_days: @get('new_workflow_action_offset_batch_element_threshold_business_days')
    #    workflow_action_definition: @get('model')
    #    base_workflow_action_definition: base_workflow_action_definition
    #  @get('working_workflow_action_offsets').addObject offset
    #  @set 'attached_to_workflow_action', null # required for empty validation

    add_workflow_action_offset: ->
      @set 'new_workflow_action_offset_warning', ''
      workflow_action_offset = @store.createRecord 'panda/workflow-action-offset',
        workflow_action_definition: @get('model')
        x_based: true
      @actions.set_selector_workflow_group.bind(@) workflow_action_offset, @get('model.workflow_group'), force_refresh: true
      @get('working_workflow_action_offsets').pushObject workflow_action_offset

    set_base_workflow_action_definition: (workflow_action_offset, workflow_action_definition) ->
      workflow_action_offset.set 'base_workflow_action_definition_warning', ''
      workflow_action_offset.set 'base_workflow_action_definition', workflow_action_definition

    set_connection_workflow_action_definition: (connection, workflow_action_definition) ->
      connection.set 'workflow_action_definition_warning', ''
      connection.set 'workflow_action_definition', workflow_action_definition

    add_workflow_action_connection: ->
      connection = @store.createRecord 'panda/workflow-action-connection',
        base_workflow_action_definition: @get('model')
        connection_type: @get('connection_types.firstObject')
      @actions.set_connection_selector_workflow_group.bind(@) connection, @get('model.workflow_group'), force_refresh: true
      @get('working_pointing_workflow_action_connections').pushObject connection


    workflow_group_change: (workflow_group) ->
      @set 'lastSelectedWorkflowGroup', workflow_group
      @set 'lastSelectedWorkflowActionDefinition', null

    #destroyWorkflowActionConstraint: (workflow_action_constraint) ->
    #  if workflow_action_constraint.get('isNew')
    #    workflow_action_constraint.rollbackAttributes()
    #    @get('working_workflow_action_constraints').removeObject workflow_action_constraint
    #  else
    #    workflow_action_constraint.deleteRecord()
    #  @set 'new_workflow_action_constraint_warning', ''
    destroy_workflow_action_definition: ->
      project = @get('model.project')
      @modal 'confirm',
        title_path: @get('modal_options.destroy_text_path') || 'general.destroy.are_you_sure'
        model: @get('model')
        ok: ->
          model = @get("model")
          model = model.get("_content") if model.__changeset__
          model.destroyRecord().then -> project.incrementProperty('update_revision')
          @send 'closeModal' unless @preventClose


    destroyWorkflowActionOffset: (workflow_action_offset) ->
      if workflow_action_offset.get('isNew')
        @get('working_workflow_action_offsets').removeObject workflow_action_offset
        workflow_action_offset.rollbackAttributes()
      else
        workflow_action_offset.deleteRecord()
      #@set 'new_workflow_action_offset_warning', ''

    destroyWorkflowActionConnection: (connection) ->
      if connection.get('isNew')
        @get('working_pointing_workflow_action_connections').removeObject connection
        connection.rollbackAttributes()
      else
        connection.deleteRecord()

    selectOrganization: (organization) -> @set('model.organization', organization)
    selectProjectScenario: (project_scenario) -> @set('model.project_scenario', project_scenario)

    saveRecord: ->
      changeset = @get('model.changeset')
      changeset.validate()
      if @get('offset_type_configured')
        ##if action_offset_base = @get('attached_to_workflow_action')
        ##  @set 'model.action_offset_base', action_offset_base
        ##else
        ##  @set 'select_action_offset_base_alert', t('workflow_action_definition.edit_workflow_action_definition.no_action_offset_base_given_alert')
        ##  return
        #if action_offset_base = @get('attached_to_workflow_action')
        #  @set 'new_workflow_action_offset_warning', t('workflow_action_definition.edit_workflow_action_definition.chosen_but_non_added_offset_workflow_action_definition')
        #  return
        unless @get('non_deleted_working_workflow_action_offsets.length')
          @set 'new_workflow_action_offset_warning', t('workflow_action_definition.edit_workflow_action_definition.offset_type_configured_but_no_offsets')
          return
        all_workflow_action_definitions_valid = true
        @get('non_deleted_working_workflow_action_offsets').forEach (workflow_action_offset) ->
          workflow_action_offset.set 'base_workflow_action_definition_warning', ''
          if !workflow_action_offset.get('x_based') and  !workflow_action_offset.get('base_workflow_action_definition.id')
            workflow_action_offset.set 'base_workflow_action_definition_warning', t('workflow_action_definition.edit_workflow_action_definition.base_workflow_action_definition_not_present')
            all_workflow_action_definitions_valid = false
        return unless all_workflow_action_definitions_valid
      else
        @get('model.workflow_action_offsets').invoke 'rollbackAttributes' # only offsets if offset_type is 'configured'
        #@set 'model.action_offset_base', null
        #@set 'select_action_offset_base_alert', ''

      if @get('offset_type_attached')
        unless @get('attached_to_workflow_action')
          @set 'attached_to_connection_warning', t('workflow_action_definition.edit_workflow_action_definition.offset_type_attached_but_no_connection')
          return
      else
        @set 'attached_to_connection_warning', ''
        @set 'attached_to_workflow_action', null

      all_connections_valid = true
      @get('working_pointing_workflow_action_connections').forEach (pointing_connection) ->
        pointing_connection.set 'workflow_action_definition_warning', ''
        unless pointing_connection.get('workflow_action_definition.content')
          pointing_connection.set 'workflow_action_definition_warning', t('workflow_action_definition.edit_workflow_action_definition.workflow_action_definition_not_present')
          all_connections_valid = false
      return unless all_connections_valid

      # This was validation phase, now perform persisting in proper order
      return unless changeset.get('isValid')
      changeset.save().then (workflow_action_definition) =>
        if @get('offset_type_configured')
          @get('working_workflow_action_offsets').invoke 'save'
        else
          @get('working_workflow_action_offsets').invoke 'destroyRecord'

        @get('working_pointing_workflow_action_connections').invoke 'save'

        existing_attached_connection = @get('model.workflow_action_connections').findBy('connection_type', 'attached')
        if @get('offset_type_attached')
          if existing_attached_connection
            existing_attached_connection.setProperties
              base_workflow_action_definition: @get('attached_to_workflow_action')
              conditional_base_value:          @get('attached_to_connection_conditional_base_value')
            existing_attached_connection.save()
          else
            new_attached_connection = @store.createRecord 'panda/workflow-action-connection',
              workflow_action_definition:      @get('model')
              base_workflow_action_definition: @get('attached_to_workflow_action')
              conditional_base_value:          @get('attached_to_connection_conditional_base_value')
              connection_type:                 'attached'
            new_attached_connection.save()
        else if existing_attached_connection # cleanup
          if existing_attached_connection.get('isNew')
            existing_attached_connection.rollbackAttributes()
          else
            existing_attached_connection.destroyRecord()

        #@get('working_workflow_action_constraints').invoke 'save'
        @incrementProperty 'model.project.update_revision'
        @send 'close'

    rollback_and_close: ->
      #@set 'select_action_offset_base_alert', ''
      @get('working_workflow_action_offsets').invoke 'rollbackAttributes'
      @get('working_pointing_workflow_action_connections').invoke 'rollbackAttributes'
      #@get('working_workflow_action_constraints').invoke 'rollbackAttributes'
      @_super arguments...

    close: ->
      Ember.$('body').off('keyup.modal-dialog')
      @_super arguments...
    set_batch_element_threshold_unit: (unit) -> @set 'model.changeset.batch_element_threshold_unit', unit
    positionInProject: ->
      @modal 'project/position-workflow-action-definition-in-project',
        model: @get('model')
    set_offset_type_none: ->
      @set 'model.changeset.offset_type', 'none'
    set_offset_type_attached: ->
      @set 'model.changeset.offset_type', 'attached'
    set_offset_type_configured: ->
      @set 'model.changeset.offset_type', 'configured'
      # Add an initial offset if activated and none are present yet
      @send 'add_workflow_action_offset' unless @get('model.workflow_action_offsets.length')

    set_attached_to_workflow_action_workflow_group: (workflow_group) ->
      @set 'attached_to_workflow_action_workflow_group', workflow_group
      @set 'attached_to_workflow_action', null
      @set 'possible_attached_to_workflow_action_workflow_action_definitions', workflow_group.get('sorted_workflow_action_definitions').rejectBy('id', @get('model.id'))
      false

    set_connection_selector_workflow_group: (workflow_action_offset, workflow_group, options = {}) ->
      if workflow_action_offset.get('connection_type') is 'attached'
        return if workflow_action_offset.get('base_workflow_action_definition.workflow_group.id') is workflow_group.get('id') and not options.force_refresh # do not clear unchanged select trigger
        workflow_action_offset.set 'base_workflow_action_definition', null
      else
        return if workflow_action_offset.get('workflow_action_definition.workflow_group.id') is workflow_group.get('id') and not options.force_refresh # do not clear unchanged select trigger
        workflow_action_offset.set 'workflow_action_definition', null
      workflow_action_offset.set 'selector_workflow_group', workflow_group
      workflow_action_offset.set 'filtered_workflow_action_definitions', workflow_group.get('sorted_workflow_action_definitions').rejectBy('id', @get('model.id'))

    set_selector_workflow_group: (workflow_action_offset, workflow_group, options = {}) ->
      return if workflow_action_offset.get('base_workflow_action_definition.workflow_group.id') is workflow_group.get('id') and not options.force_refresh # do not clear unchanged select trigger
      workflow_action_offset.set 'base_workflow_action_definition', null
      workflow_action_offset.set 'selector_workflow_group', workflow_group
      workflow_action_offset.set 'filtered_workflow_action_definitions', workflow_group.get('sorted_workflow_action_definitions').rejectBy('id', @get('model.id'))

    toggle_offset_x_based: (offset, x_based) ->
      if x_based
        offset.set 'base_workflow_action_definition', null
      else
        # do not loose original on back and forth toggle
        offset.set 'base_workflow_action_definition', offset.get('original_base_workflow_action_definition')
      offset.set 'x_based', x_based
      false

    set_attached_to_workflow_action: (workflow_action_definition) ->
      @set 'attached_to_workflow_action', workflow_action_definition
      @set 'attached_to_connection_conditional_base_value', ''
      false
    #toggle_week_day_presence: (target, week_day, selected) ->
    #  #target = target.get('batch_element_threshold_business_days') unless Ember.isArray(target)
    #  if selected
    #    target.addObject week_day.index
    #  else
    #    target.removeObject week_day.index
add_business_day_computations Component, 'new_workflow_action_offset_batch_element_threshold'
export default  ModalBase.extend(Component)
