// Generated by CoffeeScript 1.12.5
var OffsetNode, RecordNode, WorkflowActionDefinitionOffsetNodes,
  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

import Ember from 'ember';

RecordNode = Ember.Object.extend({
  resolved: false,
  title: Ember.computed('record.title', 'value_shift', function() {
    var title, value_shift;
    title = this.get('record.title');
    if (value_shift = this.get('value_shift')) {
      title = " " + title + " (" + value_shift + "d)";
    }
    return title;
  })
});

OffsetNode = Ember.Object.extend({
  record: null,
  total_offset: 0,
  value_shift: 0,
  resulting_absolute_value: 0
});

WorkflowActionDefinitionOffsetNodes = Ember.Object.extend({
  iteration_context_counter: 0,
  workflow_action_definitions: [],
  reference_date: null,
  batch_size: 0,
  active_project_scenario: null,
  forEach: function() {
    var ref;
    return (ref = this.get('processed_workflow_action_definitions')).forEach.apply(ref, arguments);
  },
  filterBy: function() {
    var ref;
    return (ref = this.get('processed_workflow_action_definitions')).filterBy.apply(ref, arguments);
  },
  get_resolved: function() {
    return this.get('processed_workflow_action_definitions').filterBy('resolved');
  },
  init: function() {
    this.set('scope_workflow_action_definition_ids', this.get('workflow_action_definitions').mapBy('id').toArray());
    this.set('processed_workflow_action_definitions', []);
    this.set('working_workflow_action_definitions', []);
    return this.get_workflow_action_definition_offsets();
  },
  get_workflow_action_definition_offsets: function() {
    var active_scenario_identifier, base, first_loop_actions, resolve_level, scope_workflow_action_definition_ids, working_workflow_action_definitions;
    base = this;
    active_scenario_identifier = this.get('active_project_scenario.identifier');
    scope_workflow_action_definition_ids = this.get('scope_workflow_action_definition_ids');
    first_loop_actions = [];
    working_workflow_action_definitions = [];
    this.get('workflow_action_definitions').forEach(function(workflow_action_definition) {
      var action_added;
      action_added = false;
      if (workflow_action_definition.get('offset_type') === 'configured') {
        workflow_action_definition.get('workflow_action_offsets').forEach(function(workflow_action_offset) {
          var absolute_value, date, offset_date, offset_value, record_wrapper, ref, ref1, value_shift;
          if (action_added) {
            return;
          }
          if (active_scenario_identifier && workflow_action_offset.get('project_scenario.identifier') && workflow_action_offset.get('project_scenario.identifier') !== active_scenario_identifier) {
            return;
          }
          if (!workflow_action_offset.get('base_workflow_action_definition.content')) {
            ref = base.get_offset_for_target(workflow_action_offset, 0), offset_date = ref[0], offset_value = ref[1];
            ref1 = base.get_dynamic_offset_for_target(workflow_action_offset, offset_value), date = ref1[0], value_shift = ref1[1];
            absolute_value = offset_value + value_shift;
            record_wrapper = RecordNode.create({
              record: workflow_action_definition,
              record_id: workflow_action_definition.get('id'),
              offset_wrappers: [
                OffsetNode.create({
                  total_offset: absolute_value,
                  value_shift: value_shift
                })
              ],
              absolute_value: absolute_value,
              value_shift: value_shift,
              date: date,
              resolve_type: 'x',
              resolved: true,
              resolve_level: 0
            });
            first_loop_actions.push(record_wrapper);
            return action_added = true;
          }
        });
      }
      if (!action_added) {
        return working_workflow_action_definitions.push(workflow_action_definition);
      }
    });
    this.set('processed_workflow_action_definitions', first_loop_actions);
    this.set('working_workflow_action_definitions', working_workflow_action_definitions);
    this.incrementProperty('iteration_context_counter');
    this.run_critical_path_resolve_loop();
    resolve_level = this.get('iteration_context_counter');
    return this.get('working_workflow_action_definitions').forEach((function(_this) {
      return function(unresolved_workflow_action_definition) {
        var offset_wrappers;
        offset_wrappers = [];
        unresolved_workflow_action_definition.get('workflow_action_offsets').forEach(function(action_offset) {
          var ref;
          if (ref = action_offset.get('base_workflow_action_definition.id'), indexOf.call(scope_workflow_action_definition_ids, ref) < 0) {
            return;
          }
          return offset_wrappers.push(OffsetNode.create({
            total_offset: action_offset.get('offset_value'),
            record: action_offset
          }));
        });
        return _this.get('processed_workflow_action_definitions').push(RecordNode.create({
          record: unresolved_workflow_action_definition,
          record_id: unresolved_workflow_action_definition.get('id'),
          offset_wrappers: offset_wrappers,
          resolved: false,
          resolve_level: resolve_level,
          resolve_type: 'unresolved'
        }));
      };
    })(this));
  },
  get_dynamic_offset_for_target: function(target, absolute_value) {
    var base_date, batch_size, empty, offset_value, operation, period_unit, shifted_date, threshold, threshold_exceedance, value_shift;
    base_date = this.get('reference_date').clone().add(absolute_value, 'day');
    empty = [base_date, 0];
    if (!(batch_size = this.get('batch_size'))) {
      return empty;
    }
    if (!(threshold = target.get('batch_element_threshold_value'))) {
      return empty;
    }
    if (!(threshold_exceedance = Math.floor(batch_size / (0.1 + parseInt(threshold))))) {
      return empty;
    }
    period_unit = target.get('batch_element_threshold_unit');
    offset_value = target.get('offset_value');
    operation = offset_value < 0 ? 'subtract' : 'add';
    if (period_unit === 'businessday') {
      operation = "business" + (operation.capitalize());
      shifted_date = base_date.clone()[operation](threshold_exceedance, {
        business_days: target.get('batch_element_threshold_business_days')
      });
    } else {
      shifted_date = base_date.clone()[operation](threshold_exceedance, period_unit);
    }
    value_shift = shifted_date.diff(base_date, 'day');
    return [shifted_date, value_shift];
  },
  get_offset_for_target: function(target, absolute_value) {
    var base_date, empty, offset_value, operation, period_unit, shifted_date, value_shift;
    base_date = this.get('reference_date').clone().add(absolute_value, 'day');
    empty = [base_date, 0];
    if (!(offset_value = target.get('offset_value'))) {
      return empty;
    }
    period_unit = target.get('offset_unit');
    operation = offset_value < 0 ? 'subtract' : 'add';
    if (period_unit === 'businessday') {
      operation = "business" + (operation.capitalize());
      shifted_date = base_date.clone()[operation](Math.abs(offset_value), {
        business_days: target.get('offset_business_days')
      });
    } else {
      shifted_date = base_date.clone()[operation](Math.abs(offset_value), period_unit);
    }
    value_shift = shifted_date.diff(base_date, 'day');
    return [shifted_date, value_shift];
  },
  run_critical_path_resolve_loop: function() {
    var active_scenario_identifier, get_dynamic_offset_for_target, get_offset_for_target, processed_workflow_action_definitions, resolve_level, scope_workflow_action_definition_ids, working_indices_to_be_removed;
    working_indices_to_be_removed = [];
    active_scenario_identifier = this.get('active_project_scenario.identifier');
    processed_workflow_action_definitions = this.get('processed_workflow_action_definitions');
    scope_workflow_action_definition_ids = this.get('scope_workflow_action_definition_ids');
    get_dynamic_offset_for_target = this.get('get_dynamic_offset_for_target').bind(this);
    get_offset_for_target = this.get('get_offset_for_target').bind(this);
    resolve_level = this.get('iteration_context_counter');
    this.get('working_workflow_action_definitions').forEach(function(working_workflow_action_definition, working_index) {
      var all_offsets_resolved, date, farthest_absolute_value, farthest_absolute_value_value_shift, farthest_result_total_offset, record_wrapper, resolved_offset_wrappers;
      if (working_workflow_action_definition.get('offset_type') !== 'configured') {
        return;
      }
      farthest_absolute_value = 0;
      farthest_absolute_value_value_shift = 0;
      farthest_result_total_offset = 0;
      date = null;
      resolved_offset_wrappers = [];
      all_offsets_resolved = working_workflow_action_definition.get('workflow_action_offsets').every(function(workflow_action_offset) {
        var current_connection_absolute_value, current_connection_total_offset_value, current_connection_value_shift, offset_date, processed_absolute_value, processed_base_workflow_action_definition_wrapper, ref, ref1, ref2, working_offset_value;
        if (active_scenario_identifier && workflow_action_offset.get('project_scenario.identifier') && workflow_action_offset.get('project_scenario.identifier') !== active_scenario_identifier) {
          return true;
        }
        if (!(processed_base_workflow_action_definition_wrapper = processed_workflow_action_definitions.findBy('record_id', workflow_action_offset.get('base_workflow_action_definition.id')))) {
          if (ref = workflow_action_offset.get('base_workflow_action_definition.id'), indexOf.call(scope_workflow_action_definition_ids, ref) < 0) {
            return true;
          }
          return false;
        }
        processed_absolute_value = processed_base_workflow_action_definition_wrapper.get('absolute_value');
        ref1 = get_offset_for_target(workflow_action_offset, processed_absolute_value), offset_date = ref1[0], working_offset_value = ref1[1];
        ref2 = get_dynamic_offset_for_target(workflow_action_offset, processed_absolute_value + working_offset_value), date = ref2[0], current_connection_value_shift = ref2[1];
        current_connection_total_offset_value = current_connection_value_shift + working_offset_value;
        current_connection_absolute_value = processed_absolute_value + current_connection_total_offset_value;
        if (Math.abs(current_connection_absolute_value) > Math.abs(farthest_absolute_value)) {
          farthest_absolute_value = current_connection_absolute_value;
          farthest_absolute_value_value_shift = current_connection_value_shift;
          farthest_result_total_offset = current_connection_total_offset_value;
        }
        resolved_offset_wrappers.push(OffsetNode.create({
          record: workflow_action_offset,
          value_shift: current_connection_value_shift,
          total_offset: current_connection_total_offset_value,
          resulting_absolute_value: current_connection_absolute_value
        }));
        return true;
      });
      if (all_offsets_resolved && resolved_offset_wrappers.length) {
        record_wrapper = RecordNode.create({
          record: working_workflow_action_definition,
          record_id: working_workflow_action_definition.get('id'),
          offset_wrappers: resolved_offset_wrappers,
          value_shift: farthest_absolute_value_value_shift,
          absolute_value: farthest_absolute_value,
          date: date,
          resolved: true,
          resolve_level: resolve_level,
          resolve_type: 'critical-path'
        });
        processed_workflow_action_definitions.push(record_wrapper);
        return working_indices_to_be_removed.push(working_index);
      }
    });
    if (working_indices_to_be_removed.length) {
      while (working_indices_to_be_removed.length) {
        this.get('working_workflow_action_definitions').splice(working_indices_to_be_removed.pop(), 1);
      }
      return this.run_critical_path_resolve_loop();
    } else {
      this.incrementProperty('iteration_context_counter');
      return this.run_unresolved_tree_resolve_loop();
    }
  },
  run_unresolved_tree_resolve_loop: function() {
    var active_scenario_identifier, get_dynamic_offset_for_target, get_offset_for_target, processed_workflow_action_definitions, resolve_level, scope_workflow_action_definition_ids, working_indices_to_be_removed;
    working_indices_to_be_removed = [];
    active_scenario_identifier = this.get('active_project_scenario.identifier');
    processed_workflow_action_definitions = this.get('processed_workflow_action_definitions');
    scope_workflow_action_definition_ids = this.get('scope_workflow_action_definition_ids');
    get_offset_for_target = this.get('get_offset_for_target').bind(this);
    get_dynamic_offset_for_target = this.get('get_dynamic_offset_for_target').bind(this);
    resolve_level = this.get('iteration_context_counter');
    this.get('working_workflow_action_definitions').forEach(function(working_workflow_action_definition, working_index) {
      var date, farthest_absolute_value, farthest_absolute_value_value_shift, farthest_result_total_offset, record_wrapper, resolved_offset_wrappers;
      if (working_workflow_action_definition.get('offset_type') !== 'configured') {
        return;
      }
      farthest_absolute_value = 0;
      farthest_absolute_value_value_shift = 0;
      farthest_result_total_offset = 0;
      date = null;
      resolved_offset_wrappers = [];
      working_workflow_action_definition.get('workflow_action_offsets').forEach(function(workflow_action_offset) {
        var current_connection_absolute_value, current_connection_total_offset_value, current_connection_value_shift, offset_date, processed_absolute_value, processed_base_workflow_action_definition_wrapper, ref, ref1, ref2, working_offset_value;
        if (active_scenario_identifier && workflow_action_offset.get('project_scenario.identifier') && workflow_action_offset.get('project_scenario.identifier') !== active_scenario_identifier) {
          return;
        }
        if (ref = workflow_action_offset.get('base_workflow_action_definition.id'), indexOf.call(scope_workflow_action_definition_ids, ref) < 0) {
          return;
        }
        if (!(processed_base_workflow_action_definition_wrapper = processed_workflow_action_definitions.findBy('record_id', workflow_action_offset.get('base_workflow_action_definition.id')))) {
          return;
        }
        processed_absolute_value = processed_base_workflow_action_definition_wrapper.get('absolute_value');
        ref1 = get_offset_for_target(workflow_action_offset, processed_absolute_value), offset_date = ref1[0], working_offset_value = ref1[1];
        ref2 = get_dynamic_offset_for_target(workflow_action_offset, processed_absolute_value + working_offset_value), date = ref2[0], current_connection_value_shift = ref2[1];
        current_connection_total_offset_value = current_connection_value_shift + working_offset_value;
        current_connection_absolute_value = processed_absolute_value + current_connection_total_offset_value;
        if (Math.abs(current_connection_absolute_value) > Math.abs(farthest_absolute_value)) {
          farthest_absolute_value = current_connection_absolute_value;
          farthest_absolute_value_value_shift = current_connection_value_shift;
          farthest_result_total_offset = current_connection_total_offset_value;
        }
        return resolved_offset_wrappers.push(OffsetNode.create({
          record: workflow_action_offset,
          value_shift: current_connection_value_shift,
          total_offset: current_connection_total_offset_value,
          resulting_absolute_value: current_connection_absolute_value
        }));
      });
      if (resolved_offset_wrappers.length) {
        record_wrapper = RecordNode.create({
          record: working_workflow_action_definition,
          record_id: working_workflow_action_definition.get('id'),
          offset_wrappers: resolved_offset_wrappers,
          value_shift: farthest_absolute_value_value_shift,
          absolute_value: farthest_absolute_value,
          date: date,
          resolved: true,
          resolve_level: resolve_level,
          resolve_type: 'with-non-rooted-offsets'
        });
        processed_workflow_action_definitions.push(record_wrapper);
        return working_indices_to_be_removed.push(working_index);
      }
    });
    if (working_indices_to_be_removed.length) {
      while (working_indices_to_be_removed.length) {
        this.get('working_workflow_action_definitions').splice(working_indices_to_be_removed.pop(), 1);
      }
      return this.run_critical_path_resolve_loop();
    } else {
      return this.run_offset_forwarding_loop();
    }
  },
  run_offset_forwarding_loop: function() {
    var active_scenario_identifier, get_dynamic_offset_for_target, get_offset_for_target, processed_workflow_action_definitions, resolve_level, scope_workflow_action_definition_ids, working_indices_to_be_removed;
    working_indices_to_be_removed = [];
    active_scenario_identifier = this.get('active_project_scenario.identifier');
    processed_workflow_action_definitions = this.get('processed_workflow_action_definitions');
    scope_workflow_action_definition_ids = this.get('scope_workflow_action_definition_ids');
    get_offset_for_target = this.get('get_offset_for_target').bind(this);
    get_dynamic_offset_for_target = this.get('get_dynamic_offset_for_target').bind(this);
    resolve_level = this.get('iteration_context_counter');
    this.get('working_workflow_action_definitions').forEach(function(working_workflow_action_definition, working_index) {
      var date, farthest_absolute_value, farthest_absolute_value_value_shift, farthest_result_total_offset, record_wrapper, resolved_offset_wrappers;
      farthest_absolute_value = 0;
      farthest_absolute_value_value_shift = 0;
      farthest_result_total_offset = 0;
      date = null;
      resolved_offset_wrappers = [];
      working_workflow_action_definition.get('dependent_workflow_action_offsets').forEach(function(workflow_action_offset) {
        var current_connection_absolute_value, current_connection_total_offset_value, current_connection_value_shift, offset_date, processed_absolute_value, processed_base_workflow_action_definition_wrapper, ref, ref1, ref2, working_offset_value;
        if (active_scenario_identifier && workflow_action_offset.get('project_scenario.identifier') && workflow_action_offset.get('project_scenario.identifier') !== active_scenario_identifier) {
          return;
        }
        if (ref = workflow_action_offset.get('workflow_action_definition.id'), indexOf.call(scope_workflow_action_definition_ids, ref) < 0) {
          return;
        }
        if (!(processed_base_workflow_action_definition_wrapper = processed_workflow_action_definitions.findBy('record_id', workflow_action_offset.get('workflow_action_definition.id')))) {
          return;
        }
        processed_absolute_value = processed_base_workflow_action_definition_wrapper.get('absolute_value');
        ref1 = get_offset_for_target(workflow_action_offset, processed_absolute_value), offset_date = ref1[0], working_offset_value = ref1[1];
        ref2 = get_dynamic_offset_for_target(workflow_action_offset, processed_absolute_value + working_offset_value), date = ref2[0], current_connection_value_shift = ref2[1];
        current_connection_total_offset_value = current_connection_value_shift + working_offset_value;
        current_connection_absolute_value = processed_absolute_value - current_connection_total_offset_value;
        if (Math.abs(current_connection_absolute_value) > Math.abs(farthest_absolute_value)) {
          farthest_absolute_value = current_connection_absolute_value;
          farthest_absolute_value_value_shift = current_connection_value_shift;
          farthest_result_total_offset = current_connection_total_offset_value;
        }
        return resolved_offset_wrappers.push(OffsetNode.create({
          record: workflow_action_offset,
          value_shift: current_connection_value_shift,
          total_offset: current_connection_total_offset_value,
          resulting_absolute_value: current_connection_absolute_value
        }));
      });
      if (resolved_offset_wrappers.length) {
        record_wrapper = RecordNode.create({
          record: working_workflow_action_definition,
          record_id: working_workflow_action_definition.get('id'),
          offset_wrappers: resolved_offset_wrappers,
          value_shift: farthest_absolute_value_value_shift,
          absolute_value: farthest_absolute_value,
          date: date,
          resolved: true,
          resolve_level: resolve_level,
          resolve_type: 'offset-lookup-inversion'
        });
        processed_workflow_action_definitions.push(record_wrapper);
        return working_indices_to_be_removed.push(working_index);
      }
    });
    if (working_indices_to_be_removed.length) {
      while (working_indices_to_be_removed.length) {
        this.get('working_workflow_action_definitions').splice(working_indices_to_be_removed.pop(), 1);
      }
      return this.run_critical_path_resolve_loop();
    }
  }
});

export default WorkflowActionDefinitionOffsetNodes;
