(function (angular) {
    'use strict';
    angular.module('scrollable-table', [])
        .directive('scrollableTable', ['$timeout', '$q', '$parse', '$document', function ($timeout, $q, $parse, $document) {
            return {
                transclude: true,
                restrict: 'A',
                scope: {
                    rows: '=watch',
                    sortFn: '='
                },
                template: '
');
                        _body.addClass('scrollable-resizing');
                        coverPanel.addClass('active');
                        angular.element('.scrollableContainer').append(scaler);
                        scaler.css('left', startPoint);
                        _document.bind('mousemove', function (e) {
                            var offsetX = e.pageX - movingPos,
                                movedOffset = _getScale(scaler.css('left')) - startPoint,
                                widthOfActiveCol = thElm.width(),
                                nextElm = thElm.nextAll('th:visible').first(),
                                minWidthOfActiveCol = _getScale(thElm.css('min-width')),
                                widthOfNextColOfActive = nextElm.width(),
                                minWidthOfNextColOfActive = _getScale(nextElm.css('min-width'));
                            movingPos = e.pageX;
                            e.preventDefault();
                            if ((offsetX > 0 && widthOfNextColOfActive - movedOffset <= minWidthOfNextColOfActive)
                                || (offsetX < 0 && widthOfActiveCol + movedOffset <= minWidthOfActiveCol)) {
                                //stopping resize if user trying to extension and the active/next column already minimised.
                                return;
                            }
                            scaler.css('left', _getScale(scaler.css('left')) + offsetX);
                        });
                        _document.bind('mouseup', function (e) {
                            e.preventDefault();
                            scaler.remove();
                            _body.removeClass('scrollable-resizing');
                            coverPanel.removeClass('active');
                            _document.unbind('mousemove');
                            _document.unbind('mouseup');
                            var offsetX = _getScale(scaler.css('left')) - startPoint,
                                newWidth = thElm.width(),
                                minWidth = _getScale(thElm.css('min-width')),
                                nextElm = thElm.nextAll('th:visible').first(),
                                widthOfNextColOfActive = nextElm.width(),
                                minWidthOfNextColOfActive = _getScale(nextElm.css('min-width')),
                                tableElement = tableController.getTableElement().find('.scrollArea table');
                            //hold original width of cells, to display cells as their original width after turn table-layout to fixed.
                            if (tableElement.css('table-layout') === 'auto') {
                                tableElement.find("th .th-inner").each(function (index, el) {
                                    el = angular.element(el);
                                    var width = el.parent().width();
                                    el.parent().css('width', width);
                                });
                            }
                            tableElement.css('table-layout', 'fixed');
                            if (offsetX > 0 && widthOfNextColOfActive - offsetX <= minWidthOfNextColOfActive) {
                                offsetX = widthOfNextColOfActive - minWidthOfNextColOfActive;
                            }
                            nextElm.removeAttr('style');
                            newWidth += offsetX;
                            thElm.css('width', Math.max(minWidth, newWidth));
                            nextElm.css('width', widthOfNextColOfActive - offsetX);
                            tableController.renderTalble().then(resizeHeaderWidth());
                        });
                    };
                    function _init() {
                        var thInnerElms = elm.find('table th:not(:last-child) .th-inner');
                        if (thInnerElms.find('.resize-rod').length == 0) {
                            tableController.getTableElement().find('.scrollArea table').css('table-layout', 'auto');
                            var resizeRod = angular.element('
');
                            thInnerElms.append($compile(resizeRod)(scope));
                        }
                    }
                    function initRodPos() {
                        var tableElement = tableController.getTableElement();
                        var headerPos = 1;//  1 is the width of right border;
                        tableElement.find("table th .th-inner:visible").each(function (index, el) {
                            el = angular.element(el);
                            var width = el.parent().width(),   //to made header consistent with its parent.
                            // if it's the last header, add space for the scrollbar equivalent unless it's centered
                                minWidth = _getScale(el.parent().css('min-width'));
                            width = Math.max(minWidth, width);
                            el.css("left", headerPos);
                            headerPos += width;
                        });
                    }
                    function resizeHeaderWidth() {
                        var headerPos = 1,//  1 is the width of right border;
                            tableElement = tableController.getTableElement();
                        tableController.getTableElement().find("table th .th-inner:visible").each(function (index, el) {
                            el = angular.element(el);
                            var width = el.parent().width(),   //to made header consistent with its parent.
                            // if it's the last header, add space for the scrollbar equivalent unless it's centered
                                lastCol = tableElement.find("table th:visible:last"),
                                minWidth = _getScale(el.parent().css('min-width'));
                            width = Math.max(minWidth, width);
                            //following are resize stuff, to made th-inner position correct.
                            //last column's width should be automatically, to avoid horizontal scroll.
                            if (lastCol[0] != el.parent()[0]) {
                                el.parent().css('width', width);
                            }
                            el.css("left", headerPos);
                            headerPos += width;
                        });
                    }
                    function _resetColumnsSize(tableWidth) {
                        var tableElement = tableController.getTableElement(),
                            columnLength = tableElement.find("table th:visible").length,
                            lastCol = tableElement.find("table th:visible:last");
                        tableElement.find("table th:visible").each(function (index, el) {
                            el = angular.element(el);
                            if (lastCol.get(0) == el.get(0)) {
                                //last column's width should be automaically, to avoid horizontal scroll.
                                el.css('width', 'auto');
                                return;
                            }
                            var _width = el.data('width');
                            if (/\d+%$/.test(_width)) {    //percentage
                                _width = Math.ceil(tableWidth * _getScale(_width) / 100);
                            } else {
                                // if data-width not exist, use average width for each columns.
                                _width = tableWidth / columnLength;
                            }
                            el.css('width', _width + 'px');
                        });
                        tableController.renderTalble().then(resizeHeaderWidth());
                    }
                }
            }
        }])
    ;
    function _getScale(sizeCss) {
        return parseInt(sizeCss.replace(/px|%/, ''), 10);
    }
})(angular);