(function(window) {
    'use strict';

    angular.module('stockflux.tearout')
        .directive('tearable', ['geometryService', 'hoverService', 'currentWindowService', 'configService',
            (geometryService, hoverService, currentWindowService, configService) => {
                return {
                    restrict: 'C',
                    link: (scope, element, attrs) => {
                        // Finding the tear element is tightly coupled to the HTML layout.
                        var dragElement = element[0],
                            tearElement = dragElement.parentNode.parentNode,
                            tileWidth = tearElement.clientWidth || 230,
                            tileHeight = tearElement.clientHeight || 100,
                            store;

                        var windowService = window.windowService;
                        var tearoutWindow = windowService.createTearoutWindow(window.name);

                        var myDropTarget = tearElement.parentNode,
                            parent = myDropTarget.parentNode,
                            myHoverArea = parent.getElementsByClassName('hover-area')[0],
                            offset = { x: 0, y: 0 },
                            currentlyDragging = false,
                            insideFavouritesPane = true,
                            dragService;

                        hoverService.add(myHoverArea, scope.stock.code);

                        function setOffset(x, y) {
                            offset.x = x;
                            offset.y = y;
                        }

                        function setCurrentlyDragging(dragging) {
                            currentlyDragging = dragging;
                        }

                        function moveTearoutWindow(x, y) {
                            var tileTopPadding = 5,
                                tileRightPadding = 5,
                                tearElementWidth = 16;

                            tearoutWindow.moveTo(
                                x - tileWidth + (tearElementWidth - offset.x + tileRightPadding),
                                y - (tileTopPadding + offset.y));
                        }

                        function displayTearoutWindow() {
                            tearoutWindow.show();
                            tearoutWindow.setAsForeground();
                        }

                        function appendToOpenfinWindow(injection, openfinWindow) {
                            openfinWindow.contentWindow.document.body.appendChild(injection);
                        }

                        function returnFromTearout() {
                            myDropTarget.appendChild(tearElement);
                            tearoutWindow.hide();
                        }

                        function clearIncomingTearoutWindow() {
                            var document = tearoutWindow.getNativeWindow().document;
                            document.body = document.createElement('body');
                        }

                        function handleMouseDown(e) {
                            if (e.button !== 0) {
                                // Only process left clicks
                                return false;
                            }

                            if (dragElement.classList.contains('single')) {
                                // There is only one favourite card so don't allow tearing out
                                return false;
                            }

                            dragService = windowService.registerDrag(tearoutWindow, currentWindowService.getCurrentWindow());

                            setCurrentlyDragging(true);
                            setOffset(e.offsetX, e.offsetY);
                            moveTearoutWindow(e.screenX, e.screenY);
                            clearIncomingTearoutWindow();
                            appendToOpenfinWindow(tearElement, tearoutWindow);
                            displayTearoutWindow();
                        }

                        function handleMouseMove(e) {
                            if (currentlyDragging) {
                                moveTearoutWindow(e.screenX, e.screenY);
                            }
                        }

                        function handleMouseUp(e) {
                            if (e.button !== 0) {
                                // Only process left clicks
                                return false;
                            }

                            if (currentlyDragging) {
                                setCurrentlyDragging(false);
                                if (insideFavouritesPane) {
                                    returnFromTearout();
                                } else {
                                    if (!store) {
                                        store = window.storeService.open(window.name);
                                    }

                                    dragService.overAnotherInstance((overAnotherInstance) => {
                                        if (overAnotherInstance) {
                                            dragService.moveToOtherInstance(scope.stock);
                                            store.remove(scope.stock);
                                            dragService = null;
                                        } else {
                                            // Create new window instance
                                            var compact = store.isCompact();
                                            windowService.createMainWindow(null, compact, (newWindow) => {
                                                newWindow.resizeTo(window.outerWidth, window.outerHeight, 'top-left');
                                                var newCardOffset = configService.getTopCardOffset(compact);
                                                newWindow.moveTo(e.screenX - newCardOffset[0], e.screenY - newCardOffset[1]);
                                                var newStore = window.storeService.open(newWindow.name);
                                                newStore.add(scope.stock);
                                                store.remove(scope.stock);
                                                newStore.toggleCompact(compact);
                                            });
                                        }

                                        // Remove drop-target from original instance
                                        parent.removeChild(myHoverArea);
                                        parent.removeChild(myDropTarget);
                                        dispose();

                                        // Destroy myself.
                                        tearoutWindow.close();
                                    });
                                }
                            }
                        }

                        function reorderFavourites() {
                            var hoverTargets = hoverService.get();

                            for (var i = 0, max = hoverTargets.length; i < max; i++) {
                                var overDropTarget = geometryService.elementIntersect(
                                    tearoutWindow, window, hoverTargets[i].hoverArea);

                                if (overDropTarget) {
                                    if (!store) {
                                        store = window.storeService.open(window.name);
                                    }

                                    store.reorder(scope.stock.code, hoverTargets[i].code);
                                    break;
                                }
                            }
                        }

                        function boundsChangingEvent() {
                            // Check if you are over a drop target by seeing if the tearout rectangle intersects the drop target
                            insideFavouritesPane = geometryService.elementIntersect(
                                tearoutWindow, window, document.getElementsByClassName('favourites')[0]);

                            if (insideFavouritesPane) {
                                reorderFavourites();
                            }
                        }

                        tearoutWindow.addEventListener('bounds-changing', boundsChangingEvent);

                        dragElement.addEventListener('mousedown', handleMouseDown);
                        document.addEventListener('mousemove', handleMouseMove, true);
                        document.addEventListener('mouseup', handleMouseUp, true);

                        function dispose() {
                            hoverService.remove(scope.stock.code);
                            tearoutWindow.removeEventListener('bounds-changing', boundsChangingEvent);
                            dragElement.removeEventListener('mousedown', handleMouseDown);
                            document.removeEventListener('mousemove', handleMouseMove);
                            document.removeEventListener('mouseup', handleMouseUp);
                        }

                        scope.$on('$destroy', () => {
                            dispose();
                        });
                    }
                };
            }]);
}(window));

@@ -1275,65 +1275,8 @@
 se,%0A
-                            insideFavouritesPane = true,%0A
     
@@ -1424,22 +1424,29 @@
 ion 
-setOffset(x, y
+insideFavouritesPane(
 ) %7B%0A
@@ -1477,62 +1477,282 @@
     
-offset.x = x;%0A                            offset.y = y
+// Check if you are over a drop target by seeing if the tearout rectangle intersects the drop target%0A                            return geometryService.elementIntersect(%0A                                tearoutWindow, window, document.getElementsByClassName('favourites')%5B0%5D)
 ;%0A  
@@ -1816,34 +1816,19 @@
  set
-CurrentlyDragging(dragging
+Offset(x, y
 ) %7B%0A
@@ -1857,38 +1857,64 @@
     
+  
-  currentlyDragging = dragging
+offset.x = x;%0A                            offset.y = y
 ;%0A  
@@ -3887,36 +3887,33 @@
                 
-setC
+c
 urrentlyDragging
@@ -3916,14 +3916,15 @@
 ging
-(
+ = 
 true
-)
 ;%0A  
@@ -4832,12 +4832,9 @@
     
-setC
+c
 urre
@@ -4849,15 +4849,16 @@
 ging
-(
+ = 
 false
-)
 ;%0A  
@@ -4903,32 +4903,34 @@
 deFavouritesPane
+()
 ) %7B%0A            
@@ -8104,329 +8104,8 @@
 ) %7B%0A
-                            // Check if you are over a drop target by seeing if the tearout rectangle intersects the drop target%0A                            insideFavouritesPane = geometryService.elementIntersect(%0A                                tearoutWindow, window, document.getElementsByClassName('favourites')%5B0%5D);%0A%0A
     
@@ -8152,16 +8152,18 @@
 itesPane
+()
 ) %7B%0A    

Refactor tearout directive