<!DOCTYPE html>
<html>

  <head>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" data-semver="3.1.1" data-require="bootstrap-css@3.1.1" />
    <script data-require="jquery@2.0.1" data-semver="2.0.1" src="https://code.jquery.com/jquery-2.0.1.min.js"></script>
    <link data-require="animate.css@1.0.0" data-semver="1.0.0" rel="stylesheet" href="//rawgithub.com/daneden/animate.css/master/animate.min.css" />
    <script data-require="lodash.js@*" data-semver="2.4.1" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular-animate.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js"></script>
    <script src="controller.js"></script>
    <script src="service.js"></script>
    <script src="directive.js"></script>
  </head>

  <body ng-app="app">
    <br />
    <div class="container">
      <div class="main-container" ng-controller="MainController">
        <ul ng-class="{'is-dragging': isDragging, 'is-dragging-just-finished': isDraggingJustFinished}">
          <segment-builder-group class="li-group level-0" level="1" data="dataMainGroup"></segment-builder-group>
        </ul>
      </div>
    </div>
    
    
    <script id="segmentBuilderGroupTpl" type="text/ng-template">
            <li>
                <div class="options">
                    <span ng-hide="level == 1" class="btn btn-warning glyphicon glyphicon-move"></span>
                    <p>Relation: <span><select ng-model="data.relation" ng-options="item.value as item.name for item in listRelation" class="form-control input-sm"></select></span></p>
                    <button ng-click="addElement('criterion')" class="btn btn-xs btn-primary">+CRITERE</button>
                    <button ng-click="addElement('segment')" class="btn btn-xs btn-primary">+SEGMENT</button>
                    <button ng-click="addElement('group')" class="btn btn-xs btn-primary">+GROUP</button>
                    <span>{{ data.id }}</span>
                    <button ng-click="deletePlease({id: data.id})" class="btn btn-xs btn-danger align-right" ng-if="level > 1"><span class="glyphicon glyphicon-trash"></span></button>
                    <button ng-click="duplicatePlease({id: data.id})" class="btn btn-xs btn-primary align-right" ng-if="level > 1"><span class="glyphicon glyphicon-tags"></span></button>
                </div>
                
                <ul ng-show="data.elements.length > 0">
                    
                    <li ng-repeat="element in data.elements | orderBy:'position' as filteredData track by element.id"
                        class="level-{{ level }}"
                        ng-class="{true:'li-group', false:'li-condition'}[element.type == 'group']">
                        
                        <drop-target ng-if="$index == 0"
                                     my-class="first-inside-group" 
                                     position="0"
                                     hide-when-id-after="{{ element.id }}"></drop-target>
                        
                        <div ng-switch="element.type">
                        
                            <div ng-switch-when="segment">
                                <segment-builder-segment data="element"
                                                         parent-id="data.id"
                                                         delete-please="deleteElement(id)"
                                                         duplicate-please="duplicateElement(id)"></segment-builder-segment>
                                <drop-target my-class="after-elem"
                                             position="{{ $index + 1 }}"
                                             hide-when-id-before="{{ element.id }}"
                                             hide-when-id-after="{{ filteredData[$index+1]['id'] }}"></drop-target>
                            </div>
                            
                            <div ng-switch-when="criterion">
                                <segment-builder-criterion data="element"
                                                           parent-id="data.id"
                                                           delete-please="deleteElement(id)"
                                                           duplicate-please="duplicateElement(id)"></segment-builder-criterion>
                                
                                <drop-target my-class="after-elem"
                                             position="{{ $index + 1 }}"
                                             hide-when-id-before="{{ element.id }}"
                                             hide-when-id-after="{{ filteredData[$index+1]['id'] }}"></drop-target>
                            </div>
                            
                            <div ng-switch-when="group">
                                <segment-builder-element data="element"
                                                         parent-id="data.id"
                                                         level="level+1"
                                                         delete-please="deleteElement(id)" 
                                                         duplicate-please="duplicateElement(id)"></segment-builder-element>
                                
                                <drop-target my-class="after-group"
                                             position="{{ $index + 1 }}"
                                             hide-when-id-before="{{ element.id }}"
                                             hide-when-id-after="{{ filteredData[$index+1]['id'] }}"></drop-target>
                            </div>
                            
                        </div>
                    </li>
                </ul>
                
                <div ng-if="data.elements.length == 0">
                    <h4 class="empty-group">Please add a criterion, a segment, or a group.</h4>
                    <drop-target my-class="group-empty" position="0"></drop-target>
                </div>
            </li>
        </script>
  </body>

</html>

$border_radius_custom: 0px;

@mixin animation($properties) {
    -webkit-animation: $properties;
    -moz-animation: $properties;
    -ms-animation: $properties;
    -o-animation: $properties;
    animation: $properties;
}

@mixin transition($properties...) {
    -webkit-transition: $properties;
    -moz-transition: $properties;
    -ms-transition: $properties;
    -o-transition: $properties;
    transition: $properties;
}

@mixin box-shadow($properties...) {
    -moz-box-shadow: $properties;
    -webkit-box-shadow: $properties;
    -o-box-shadow: $properties;
    box-shadow: $properties;
}


/***********************************************************************/

h4 {
  color: #ffffff;
}

.container {
    width: 100%;
}

select,
input,
.btn {
  border-radius: 0 !important;
}

.main-container {
    display: block;
    width: 100%;
    padding: 10px;
    
    select {
      width: 60px !important;
      padding: 2px;
      height: 25px;
    }
    
    input {
      width: 150px !important;
      padding: 2px;
      height: 22px;
    }
    
    ul {
        list-style: none;
        padding: 0;
        margin: 0 0 0 20px;
    }
    & > ul {
      margin: 0;
    }
    
    .li-group {
        position: relative;
        display: block;
        min-height: 60px;
        border-radius: $border_radius_custom;
        margin: 8px 5px;
        padding: 5px;
        
        $color_start: #f5f3f4;
        $color_hover_start: #F4F4F4;
        @for $i from 0 through 15 {
            $darken_value: min(($i + 1) * 6, 100);
            $darken_value_more: min($darken_value + 8, 100);
            $darken_value_more_more: min($darken_value + 20, 100);
            
            &.level-#{$i} {
                background: darken($color_start, $darken_value);
                border: 1px solid darken($color_start, $darken_value_more);
                @include box-shadow(inset 0px 0px 10px 0px darken($color_start, $darken_value_more_more));
		        
    		        &:hover {
                    //border-color: #666666;
    		        }
                    
                .options {
                    border-bottom: 1px solid darken($color_start, $darken_value_more);
                }
            }
        }
        
        span.btn-warning {
            cursor: move;
        }
        
        .empty-group {
            text-align: center;
        }
    }
    
    .options {
        p,
        button {
            display: inline-block;
        }
        
        select {
            width: 100px;
            display: inline-block;
        }
    }
    
    .segment,
    .criterion {
        display: block;
        margin: 8px 5px;
        padding: 5px;
        border-radius: $border_radius_custom;
        color: #ffffff;
        
        input {
          display: inline-block;
        }
    }
    
    .segment {
        border: 1px solid darken(#8686BA, 15);
        background: #8686BA;
    }
    .criterion {
        border: 1px solid darken(#BA8686, 15);
        background: #BA8686;
    }
    
    button.align-right {
        float: right;
        margin-left: 5px;
    }
       
    .drag-in-progress {
        opacity: .2;
        pointer-events: none;
        //outline: 4px solid #000000;
    }
    
    .drop-zone {
      display: none;
      position: absolute;
      width: 100%;
      height: 24px;
      z-index: 1;
      color: black;
      margin: 0;
      padding: 0;
      line-height: 24px;
      font-size: 24px;
      //opacity: .5;
      
      &.first-inside-group {
        top: -20px;
        left: -20px;
      }
      &.group-empty {
        top: auto;
        bottom: -12px;
        width: 100%;
        height: 38px;
        border: 5px dashed black;
        
        &.drag-hover {
          opacity: 1;
          border-color: red;
        }
        
        .glyphicon {
          display: none;
        }
      }
      &.after-elem {
        left: -20px;
        bottom: -14px;
      }
      &.after-group {
        left: -26px;
        bottom: -15px;
      }
      
      &.drag-hover {
        opacity: 1;
        color: red;
      }
      
      .glyphicon {
        pointer-events: none;
      }
    }
    
    .is-dragging .drop-zone {
      display: block;
    }
    .drag-in-progress .drop-zone {
      display: none;
    }
    
    
    li {
        position: relative;
    }
    
    .li-condition {
        &.ng-enter {
            @include animation(pulse 0.4s);
        }
        &.ng-leave {
            @include animation(zoomOut 0.4s);
        }
        &.ng-move {
            @include animation(zoomIn 0.4s);
        }
    }
    
    .li-group {
        &.ng-enter {
            @include animation(flipInX 0.4s);
        }
        &.ng-leave {
            @include animation(zoomOut 0.4s);
        }
        &.ng-move {
            @include animation(zoomIn 0.4s);
        }
    }
    
    .is-dragging-just-finished {
        .li-condition,
        .li-group {
            &.ng-enter {
                @include animation(zoomIn 0.4s);
            }
        }
    }
}


var app = angular.module('app', ['ngAnimate']);

app.controller('MainController', function($scope, $rootScope, SegmentBuilder) {
    $scope.dataMainGroup = SegmentBuilder.currentSegment;
});

app.directive("segmentBuilderGroup", function() {
    return {
        restrict: "E",
        replace: true,
        scope: {
            data: '=',
            parentId: '=',
            level: '=',
            duplicatePlease: '&',
            deletePlease: '&'
        },
        templateUrl:  'segmentBuilderGroupTpl',
        controller: function($scope, $rootScope, SegmentBuilder) {
            
            var getPositionNewElement = function() {
                var maxPositionValue = 0;
                angular.forEach($scope.data.elements, function(value, key) {
                    if(value.position > maxPositionValue) maxPositionValue = value.position;
                });
                return maxPositionValue + 1;
            }
            
            var getElement = function(id) {
                var elem = null;
                angular.forEach($scope.data.elements, function(value, key) {
                    if(value.id == id) elem = value;
                });
                return elem;
            }
            
            $scope.addElement = function(type) {
                var newElem,
                    newPosition = getPositionNewElement();
                
                $rootScope.isDraggingJustFinished = false;
                
                switch(type) {
                    case 'criterion':
                        newElem = SegmentBuilder.getNewCriterion(newPosition);
                        break;
                    case 'segment':
                        newElem = SegmentBuilder.getNewSegment(newPosition);
                        break;
                    case 'group':
                        newElem = SegmentBuilder.getNewGroup(newPosition);
                        break;
                }
                $scope.data.elements.push(newElem);
            }
            
            // id could be a criterion, segment, or group
            $scope.duplicateElement = function(id) {
                var element = getElement(id);
                
                if(element) {
                    var duplicate_element = SegmentBuilder.duplicateElement(element, getPositionNewElement());
                    $scope.data.elements.push(duplicate_element);
                }
            }
            
            // id could be a criterion, segment, or group
            $scope.deleteElement = function(id) {
                var start = $scope.data.elements.length - 1;
                for(var i = start; i >= 0; i--) {
                    if($scope.data.elements[i].id === id) {
                        $scope.data.elements.splice(i, 1);
                    }
                }
            }
            
            $scope.listRelation = SegmentBuilder.groupInfo.relation;
        },
    };
});

app.directive("segmentBuilderElement", function($compile) {
    return {
        restrict: "E",
        replace: true,
        scope: {
            data: '=',
            parentId: '=',
            level: '=',
            duplicatePlease: '&',
            deletePlease: '&'
        },
        template: '',
        link: function (scope, element, attrs) {
            var subElementsString = '<segment-builder-group drag\
                                                            data="data"\
                                                            parent-id="parentId"\
                                                            level="level"\
                                                            delete-please="deletePlease({id: data.id})"\
                                                            duplicate-please="duplicatePlease({id: data.id})"></segment-builder-group>';
            
            if (angular.isArray(scope.data.elements)) {       
                $compile(subElementsString)(scope, function(cloned, scope) {
                    element.append(cloned); 
                });
            }
        },
        controller: function($scope) {}
    };
});


app.directive('segmentBuilderCriterion', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            data: '=',
            parentId: '=',
            duplicatePlease: '&',
            deletePlease: '&'
        },
        template:  '<div drag class="criterion form-inline">\
                        <span class="btn btn-warning btn-xs"><span class="glyphicon glyphicon-move"></span></span>\
                        <span>{{ data.id }}</span>\
                        <span><input type="text" class="form-control input-sm" name="name" ng-model="data.criterion"/></span>\
                        <button ng-click="deletePlease({id: data.id})" class="btn btn-xs btn-danger align-right"><span class="glyphicon glyphicon-trash"></span></button>\
                        <button ng-click="duplicatePlease({id: data.id})" class="btn btn-xs btn-primary align-right"><span class="glyphicon glyphicon-tags"></span></button>\
                    </div>',
        controller: function($scope) {},
        link: function(scope, element, attrs) {}
    };
});


app.directive('segmentBuilderSegment', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            data: '=',
            parentId: '=',
            duplicatePlease: '&',
            deletePlease: '&'
        },
        template:  '<div drag class="segment form-inline">\
                        <span class="btn btn-warning btn-xs"><span class="glyphicon glyphicon-move"></span></span>\
                        <span>{{ data.id }}</span>\
                        <input type="text" class="form-control input-sm" name="name" ng-model="data.segment"/>\
                        <button ng-click="deletePlease({id: data.id})" class="btn btn-xs btn-danger align-right"><span class="glyphicon glyphicon-trash"></span></button>\
                        <button ng-click="duplicatePlease({id: data.id})" class="btn btn-xs btn-primary align-right"><span class="glyphicon glyphicon-tags"></span></button>\
                    </div>',
        controller: function($scope) {},
        link: function(scope, element, attrs) {}
    };
});


app.directive("drag", function($rootScope, $timeout) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs)  {
      attrs.$set('draggable', 'true');
      var dragStyle = 'drag-in-progress';
      
      /*var handle = element.find('.btn-warning')[0];
      var target = false;
      element.bind('mousedown', function(event) {
        target = event.target;
      });*/
      
      element.bind('dragstart', function(event) {
        //if(!handle.contains(target)) {
        
          $rootScope.isDragging = true;
          
         	$rootScope.draggedElement = {
         	  id: scope.data.id,
         	  parent_id: scope.parentId
         	};
          
          $timeout(function() {
            element.addClass(dragStyle);
          });
          
          event.originalEvent.dataTransfer.setData('text/plain', 'go');
          event.originalEvent.dataTransfer.effectAllowed = 'move';
        //}
        //else {
          //event.preventDefault();
        //}
        event.stopPropagation();
      });
      
      element.bind('dragend', function(event) {
        $timeout(function() {
          $rootScope.isDragging = false;
          $rootScope.isDraggingJustFinished = true;
          $rootScope.draggedElement = null;
          
          element.removeClass(dragStyle);
        });
        
        $timeout(function() {
          $rootScope.isDraggingJustFinished = false;
        }, 1000);
        
        event.stopPropagation();
      });
    }
  }
});

app.directive("dropTarget", function($rootScope, $timeout, SegmentBuilder) {
  return {
    restrict: 'E',
    replace: true,
    scope: true,
    template: '<div ng-hide="checkIfHide()" class="drop-zone">\
                  <span class="glyphicon glyphicon-arrow-right"></span>\
               </div>',
    link: function(scope, element, attrs) {
        element.addClass(attrs.myClass);
        
        scope.checkIfHide = function() {
            return (
                      $rootScope.draggedElement && 
                      (
                        (attrs.hideWhenIdBefore && $rootScope.draggedElement.id == attrs.hideWhenIdBefore) ||
                        (attrs.hideWhenIdAfter && $rootScope.draggedElement.id == attrs.hideWhenIdAfter)
                      )
                  );
        }
        
        var dropStyle = 'drag-hover';
        
        element.bind('dragenter', function(event) {
            event.preventDefault();
            event.stopPropagation();
            
            // why? because http://stackoverflow.com/questions/14203734/dragend-dragenter-and-dragleave-firing-off-immediately-when-i-drag
            $timeout(function() { element.addClass(dropStyle); });
        });
      
        element.bind('dragleave', function(event) {
            event.stopPropagation();
            
            $timeout(function() { element.removeClass(dropStyle); });
        });
      
        element.bind('dragover', function(event) {
            event.preventDefault();
            event.stopPropagation();
        });
        
        element.bind('drop', function(event) {
            event.preventDefault();
            event.stopPropagation();
            
            $timeout(function() { element.removeClass(dropStyle); });
            
            SegmentBuilder.moveElement(
                $rootScope.draggedElement.id,
                $rootScope.draggedElement.parent_id,
                scope.data.id,
                attrs.position
            );
        });
    }
  }
});


app.factory('SegmentBuilder', function() {
    
    var groupInfo = {
      relation: [
          {value:'and',    name:'And'},
          {value:'or',     name:'Or'},
          {value:'none',   name:'None'}
      ]
    };
    
    var new_element = {
        criterion: {
            position: -1,
            type: 'criterion',
            id: '-1',
            criterion: ''
        },
        segment: {
            position: -1,
            type: 'segment',
            id: '-1',
            segment: ''
        },
        group: {
            position: -1,
            type: 'group',
            id: '-1',
            relation: 'and',
            elements: []
        }
    };
    
    var data = {
        position: 1,
        type: 'group',
        id: 'gr35848',
        relation: 'and',
        elements: [
            {
                position: 1,
                type: 'criterion',
                id: 'cr65848',
                criterion: 'I-Robot'
            },
            {
                position: 4,
                type: 'group',
                id: 'gr8979',
                relation: 'or',
                elements: [
                    {
                        position: 6,
                        type: 'group',
                        id: 'gr2316',
                        relation: 'and',
                        elements: []
                    },
                    {
                        position: 4,
                        type: 'segment',
                        id: 'se871528',
                        segment: 'Germinal'
                    },
                    {
                        position: 1,
                        type: 'group',
                        id: 'gr21384',
                        relation: 'or',
                        elements: [
                            {
                                position: 1,
                                type: 'segment',
                                id: 'se819954',
                                segment: 'Malcolm'
                            },
                            {
                                position: 3,
                                type: 'criterion',
                                id: 'cr87195',
                                criterion: 'Le Fils De l\'Homme'
                            }
                        ]
                    }
                ]
            },
            {
                position: 2,
                type: 'segment',
                id: 'se8944',
                segment: 'Mon Voisin Totoro'
            },
            {
                position: 3,
                type: 'group',
                id: 'gr54614',
                relation: 'and',
                elements: []
            },
            {
                position: 12,
                type: 'criterion',
                id: 'cr68789',
                criterion: 'Limitless'
            },
        ]
    };
    
    
    var getNewCriterion = function(position) {
        var criterion = angular.copy(new_element.criterion);
        criterion.id = 'cr' + Math.floor((Math.random()*100000)+1);
        criterion.position = position;
        return criterion;
    };
    
    var getNewSegment = function(position) {
        var segment = angular.copy(new_element.segment);
        segment.id = 'se' + Math.floor((Math.random()*100000)+1);
        segment.position = position;
        return segment;
    };
    
    var getNewGroup = function(position) {
        var group = angular.copy(new_element.group);
        group.id = 'gr' + Math.floor((Math.random()*100000)+1);
        group.position = position;
        return group;
    };
    
    
    var resetAllIdInThisGroup = function(elements) {
        angular.forEach(elements, function(element, key){
            element.id = element.type + Math.floor((Math.random()*100000)+1);
            
            if(element.type == 'group') {
                resetAllIdInThisGroup(element.elements);
            }
        });
    };
    
    
    var duplicateElement = function(element, position) {
        var duplicate_element = angular.copy(element);
        duplicate_element.id = duplicate_element.type.substr(0, 2) + Math.floor((Math.random()*100000)+1);
        duplicate_element.position = position;
        
        if(duplicate_element.type == 'group') {
            resetAllIdInThisGroup(duplicate_element.elements);
        }
        
        return duplicate_element;
    };
    
    
    var removeElementFromGroup = function (elements_array, element_id, parent_id) {
        if(elements_array) {
            for(var i = 0; i < elements_array.length; i++) {
                if(elements_array[i].id == parent_id) {
                    var removed = _.remove(elements_array[i].elements, function(elem) { return elem.id === element_id; });
                    if(removed.length == 1) {
                        return removed[0];
                    }
                    else {
                        console.error('removeElementFromGroup - BIG FAIL..');
                    }
                }
                var found = removeElementFromGroup(elements_array[i].elements, element_id, parent_id);
                if(found) return found;
            }
        }
    };
    
    var addElementToGroup = function(elements_array, element_to_add, new_parent_id, new_position) {
        if(elements_array) {
            for(var i = 0; i < elements_array.length; i++) {
                if(elements_array[i].id == new_parent_id) {
                  
                    if(elements_array[i].elements.length > 0) {
                        var ordered_array = _.sortBy(_.map(elements_array[i].elements, function(elem) { return {id: elem.id, position: elem.position}; }), 'position');
                        
                        // should be the first
                        if(new_position == 0) {
                            element_to_add.position = ordered_array[0]['position'] - 1;
                        }
                        // should be the last
                        else if(new_position >= ordered_array.length) {
                            element_to_add.position = ordered_array[ordered_array.length-1]['position'] + 1;
                        }
                        // should be in the middle
                        else {
                            var previous_position = ordered_array[new_position-1]['position'];
                            var next_position = ordered_array[new_position]['position'];
                            element_to_add.position = (previous_position + next_position)/2;
                        }
                    }
                    else {
                        element_to_add.position = 1;
                    }
                    
                    elements_array[i].elements.push(element_to_add);
                    return true;
                }
                var done = addElementToGroup(elements_array[i].elements, element_to_add, new_parent_id, new_position);
                if(done) return done;
            }
        }
    }
    
    var moveElementInsideGroup = function(elements_array, element_id, parent_id, new_position) {
        if(elements_array) {
            for(var i = 0; i < elements_array.length; i++) {
                if(elements_array[i].id == parent_id) {
                    
                    // recupere tous les id ordonnés par position
                    var ordered_array = _.sortBy(_.map(elements_array[i].elements, function(elem) { return {id: elem.id, position: elem.position}; }), 'position');
                    var new_position_value;
                    
                    // verif si on déplace elem a une position superieure à l'actuelle
                    for(var j = 0; j < ordered_array.length; j++) {
                        if(ordered_array[j]['id'] == element_id) {
                            var current_position = j;
                            
                            // si oui on decrémente la position cible
                            if(new_position > current_position && new_position > 0) {
                                new_position--;
                            }
                            break;
                        }
                    }
                    _.remove(ordered_array, function(elem) { return elem.id === element_id; });
                    
                    // should be the first
                    if(new_position == 0) {
                        new_position_value = ordered_array[0]['position'] - 1;
                    }
                    // should be the last
                    else if(new_position >= ordered_array.length) {
                        new_position_value = ordered_array[ordered_array.length-1]['position'] + 1;
                    }
                    // should be in the middle
                    else {
                        var previous_position = ordered_array[new_position-1]['position'];
                        var next_position = ordered_array[new_position]['position'];
                        new_position_value = (previous_position + next_position)/2;
                    }
                    
                    _.forEach(elements_array[i].elements, function(elem) {
                        if(elem.id == element_id) {
                            elem.position = new_position_value;
                            console.log('UPDATE > ',new_position,' (elem.position=',new_position_value,') > ', elem);
                        }
                    });
                }
                var done = moveElementInsideGroup(elements_array[i].elements, element_id, parent_id, new_position);
                if(done) return done;
            }
        }
    };
    
    // adapt all recursive with:
    // http://blog.wax-o.com/2014/01/how-to-find-deep-and-get-parent-in-javascript-nested-objects-with-recursive-functions-and-the-reference-concept-level-beginner/
    
    var moveElement = function(element_id, parent_id, new_parent_id, new_position) {
        var is_ok;
        
        console.log('Move element id ', element_id, ' from group ', parent_id, ' into the group ', new_parent_id, ' at the position ', new_position);
        
        if(new_parent_id == parent_id) {
          // trouve le groupe parent et change la position de l'element
          is_ok = moveElementInsideGroup([data], element_id, parent_id, new_position);
        }
        else {
          // retrouver l'element dans le segment et le retirer du groupe ou il est
          var element_removed = removeElementFromGroup([data], element_id, parent_id, new_parent_id, new_position);
          
          // trouver son nouveau groupe, calculer sa nouvelle position et l'inserer
          is_ok = addElementToGroup([data], element_removed, new_parent_id, new_position);
        }
        
        
    };
    
    

    return {
        getNewCriterion: getNewCriterion,
        getNewSegment: getNewSegment,
        getNewGroup: getNewGroup,
        duplicateElement: duplicateElement,
        moveElement: moveElement,
        groupInfo: groupInfo,
        currentSegment: data
    };
});