"use strict";
var ruler = function (options) {
    this.api = this.builder();
    this.api.constructRulers.call(this, options);
};
ruler.prototype.builder = function () {
    var VERTICAL = 1,
        HORIZONTAL = 2,
        CUR_DELTA_X = 0,
        CUR_DELTA_Y = 0,
        CUR_SCALE = 1;

    var options,
        rulerz = {},
        guides = [],
        theRulerDOM = document.createElement('div'),
        corners = [],
        defaultOptions = {
            rulerHeight: 15,
            fontFamily: 'arial',
            fontSize: '8px',
            strokeStyle: 'gray',
            sides: ['top', 'right'],
            cornerSides: ['TR'],
            lineWidth: 1,
            enableMouseTracking: true,
            enableToolTip: true
        };

    var positionRuler = function (orientation, alignment) {
        var rulWrapper = document.getElementsByClassName('active-page')[0].parentNode
            .getElementsByClassName("rul_wrapper")[0];
        var main = document.getElementsByClassName('active-page')[0]
            .getElementsByClassName(" main")[0];

        var pos = _h.getPosition(rulWrapper);
        var pos2 = _h.getPosition(main);
       
        var res2 = ((pos.width - pos2.width) / 2) - 36;
        switch (alignment) {
            case 'top':
                var horRuler = document
                    .getElementsByClassName("ruler-hor")[0];
                if (orientation === "Landscape") {
                    horRuler.style.top = 0 + "px";
                    horRuler.style.left = res2 + "px";
                } else {
                    horRuler.style.top = 0 + "px";
                    horRuler.style.left = res2 + "px";
                }
                break;
            case 'right':
                var verRuler = document
                    .getElementsByClassName("ruler-ver")[0];
                if (orientation === "Landscape") {
                    verRuler.style.top = 553 +"px";
                    verRuler.style.right = -541 + "px";
                } else {
                    verRuler.style.top = 553 + "px";
                    verRuler.style.right = -541 + "px";
                }
                break;
        }
    };
    var getDimension = function(target) {
        if (!target.classList.contains("ruler")) {
            var parent = target.parentNode;
            if (!parent.classList.contains("ruler")) {
                var parent2 = parent.parentNode;
                if (parent2.classList.contains("ruler")) {
                    if (parent2.classList.contains("ruler-ver")) 
                        return 1;
                     else
                        return 2;
                }
            }
            else {
                if (parent.classList.contains("ruler-ver"))
                    return 1;
                else
                    return 2;
            }
        } else {
            if (target.classList.contains("ruler-ver"))
                return 1;
            else
                return 2;
        }
    };
    var attachListeners = function (container, curRul) {
        var mousedown = function (e) {
            var dimension = getDimension(e.target);
            constructGuide(dimension, e.clientX, e.clientY, e);

        };

        curRul.target.addEventListener('mousedown', mousedown);
        curRul.clearListeners = function() {
            container.removeEventListener('mousedown', mousedown);
        };
    };

    var constructGuide = function (dimension, x, y, e, isSet) {
        var guideIndex;
        var moveCB = function (line, x, y) {
            var coor;
            if (line.dimension === VERTICAL) {
                coor = theRulerDOM.offsetWidth - x;
            } else {
                coor = y;
            }
            if (!line.assigned()) {
                if (coor > options.rulerHeight) {
                    line.assigned(true);
                }
                return;
            }

            if (coor < options.rulerHeight) {
                guides.some(function (guideLine, index) {
                    if (guideLine.line === line) {
                        guideIndex = index;
                        return true;
                    }
                });
                line.destroy();
                guides.splice(guideIndex, 1);

            }
        };

        var guide = document.createElement('div'),
            guideStyle = dimension === VERTICAL ? 'rul_lineVer' : 'rul_lineHor',
            curDelta = dimension === VERTICAL ? CUR_DELTA_X : CUR_DELTA_Y;
        guide.title = 'Double click to delete';
        ruler.prototype.utils.addClasss(guide, ['rul_line', guideStyle]);
        guide = theRulerDOM.appendChild(guide);
        if (dimension === VERTICAL) {
            guide.style.left = ruler.prototype.utils.pixelize(x - options.container.getBoundingClientRect().left);
            if (isSet) guide.style.left = ruler.prototype.utils.pixelize(Math.round(x / CUR_SCALE) + options.rulerHeight);
        }
        else {
            guide.style.top = ruler.prototype.utils.pixelize(y - options.container.getBoundingClientRect().top);
            if (isSet) guide.style.top = ruler.prototype.utils.pixelize(Math.round(y / CUR_SCALE) + options.rulerHeight);
        }
        guides.push({
            dimension: dimension,
            line: ruler.prototype.guideLine(guide, options.container.querySelector('.rul_wrapper'), dimension, options, curDelta, moveCB, e)
        });
    };
    
    var constructRuler = function (container, alignment) {
        var dimension = alignment === 'left' || alignment === 'right' ? VERTICAL : HORIZONTAL,
            rulerStyle = dimension === VERTICAL ? 'rul_ruler_Vertical' : 'rul_ruler_Horizontal';

        var div = ruler.prototype.utils.createEl("div", container);

        rulerz[alignment] = ruler.prototype.rulerConstructor(div, options, dimension);
        rulerz[alignment].drawRuler(dimension, options.size);
        //positionRuler(rulerz[alignment], alignment);
        attachListeners(container, rulerz[alignment]);
    };

    var constructCorner = (function () {
        function cornerDraw(container, side) {
            var corner = document.createElement('div'),
                cornerStyle = 'rul_corner' + side.toUpperCase();

            corner.title = 'حذف تمام خطوط';
            ruler.prototype.utils.addClasss(corner, ['rul_corner', cornerStyle]);
            corner.style.width = ruler.prototype.utils.pixelize(options.rulerHeight + 1);
            corner.style.height = ruler.prototype.utils.pixelize(options.rulerHeight);
            return container.appendChild(corner);

        }

        function mousedown(e) {
            e.stopPropagation();
            clearGuides();
        }

        return function(container, cornerSides) {
            cornerSides.forEach(function(side) {
                var corner = cornerDraw(container, side);
                corner.addEventListener('mousedown', mousedown);
                corner.destroy = function() {
                    corner.removeEventListener('mousedown', mousedown);
                    if (corner.parentNode)
                    corner.parentNode.removeChild(corner);
                };

                corners.push(corner);
            });
        };

    })();

    var mouseup = function (e) {
        guides.forEach(function(guide) {
            guide.line.stopDrag();
        });
    };

    var changeOrientation = function (orientation) {
        options.sides.forEach(function (side) {
            positionRuler(orientation, side);
        });
    };
    var constructRulers = function (curOptions) {
        theRulerDOM = ruler.prototype.utils.addClasss(theRulerDOM, 'rul_wrapper');
        options = ruler.prototype.utils.extend(defaultOptions, curOptions);
        theRulerDOM = options.container.appendChild(theRulerDOM);
        options.sides.forEach(function (side) {
            constructRuler(theRulerDOM, side);
            positionRuler(options.orientation, side);
        });
        constructCorner(theRulerDOM, options.cornerSides);
        options.container.addEventListener('mouseup', mouseup);
    };

    var forEachRuler = function (cb) {
        var index = 0;
        for (var rul in rulerz) {
            if (rulerz.hasOwnProperty(rul)) {
                cb(rulerz[rul], index++);
            }
        }
    };

    var clearGuides = function () {
        guides.forEach(function (guide) {
            guide.line.destroy();
        });
        guides = [];
    };

    var toggleGuideVisibility = function (val) {
        var func = val ? 'show' : 'hide';
        guides.forEach(function (guide) {
            guide.line[func]();
        });
    };

    var toggleRulerVisibility = function (val) {
        var state = val ? 'block' : 'none';
        theRulerDOM.style.display = state;
        var trackers = options.container.querySelectorAll('.rul_tracker');
        if (trackers.length > 0) {
            trackers[0].style.display = state;
            trackers[1].style.display = state;
        }

    };

    var getGuides = function () {
        return guides.map(function (guide) {
            return {
                posX: Math.round((parseInt(guide.line.guideLine.style.left) - CUR_DELTA_X - options.rulerHeight) * CUR_SCALE),
                posY: Math.round((parseInt(guide.line.guideLine.style.top) - CUR_DELTA_Y - options.rulerHeight) * CUR_SCALE),
                dimension: guide.dimension
            }
        });
    };

    var setGuides = function (_guides) {
        if (!_guides) { return }
        _guides.forEach(function (guide) {
            constructGuide(guide.dimension, guide.posX, guide.posY, null, true)
        })

    };

    var destroy = function () {
        clearGuides();
       
        forEachRuler(function (ruler) {
            ruler.destroy();
        });
        var rullers = document.getElementsByClassName("ruler");
        if (rullers.length)
            rullers[0].remove();
        if (rullers.length)
            rullers[0].remove();
        corners.forEach(function (corner) {
            corner.destroy();
        });
        options.container.removeEventListener('mouseup', mouseup);
        if (theRulerDOM.parentNode)
        theRulerDOM.parentNode.removeChild(theRulerDOM);
    };

    return {
        VERTICAL: VERTICAL,
        HORIZONTAL: HORIZONTAL,
        clearGuides: clearGuides,
        getGuides: getGuides,
        setGuides: setGuides,
        constructRulers: constructRulers,
        toggleRulerVisibility: toggleRulerVisibility,
        toggleGuideVisibility: toggleGuideVisibility,
        changeOrientation: changeOrientation,
        destroy: destroy
    }
};



ruler.prototype.rulerConstructor = function (_target, options, rulDimension) {

    var target = _target,
        rulThickness = 0,
        orientation = options.orientation,
        size = options.size,
        rulLength = 0,
        rulScale = 1,
        dimension = rulDimension || 2, 
        orgPos = 0,
        tracker = document.createElement('div');

    var getLength = function () {
        return rulLength;
    };

    var getThickness = function () {
        return rulThickness;
    };

    var getScale = function () {
        return rulScale;
    };

    var setScale = function (newScale) {
        rulScale = parseFloat(newScale);
        drawPoints();
        return rulScale;
    };

    var drawRuler = function (dimension, size) {
        rulLength = target.offsetWidth; 

       
        var topLength = 0, rightLength = 0, cmDiv, mmDiv;
        switch (size) {
        case "A4":
            if (orientation === "Landscape") {
                topLength = 30;
                rightLength = 21;
            } else {
                topLength = 21;
                rightLength = 30;
            }

            break;
        case "A3":
            break;
        }

        if (dimension === 1) {
            ruler.prototype.utils.addClasss(target, ["ruler", "ruler-ver"]);
            for (var k = 0; k < rightLength; k++) {
                cmDiv = ruler.prototype.utils.createEl("div", target);
                ruler.prototype.utils.addClasss(cmDiv, "cm");
                for (var b = 0; b < 9; b++) {
                    mmDiv = ruler.prototype.utils.createEl("div", cmDiv);
                    ruler.prototype.utils.addClasss(mmDiv, ["mm"]);
                }
            }
        } else {
            ruler.prototype.utils.addClasss(target, ["ruler", "ruler-hor"]);

            for (var i = 0; i < topLength; i++) {
                cmDiv = ruler.prototype.utils.createEl("div", target);
                ruler.prototype.utils.addClasss(cmDiv, "cm");
                for (var j = 0; j < 9; j++) {
                    mmDiv = ruler.prototype.utils.createEl("div", cmDiv);
                    ruler.prototype.utils.addClasss(mmDiv, "mm");
                }
            }
        }

    };

    var mousemove = function (e) {
        var posX = e.clientX;
        var posY = e.clientY;
        if (dimension === 2) {
            tracker.style.left = ruler.prototype.utils.pixelize(posX - parseInt(options.container.getBoundingClientRect().left));
        }
        else {
            tracker.style.top = ruler.prototype.utils.pixelize(posY - parseInt(options.container.getBoundingClientRect().top));
        }
    };

    var destroy = function () {
        options.container.removeEventListener('mousemove', mousemove);
        if (tracker.parentNode)
            tracker.parentNode.removeChild(tracker);
        this.clearListeners && this.clearListeners();

    };

    var initTracker = function () {
        tracker = options.container.appendChild(tracker);
        ruler.prototype.utils.addClasss(tracker, 'rul_tracker');
        var height = ruler.prototype.utils.pixelize(options.rulerHeight);
        if (dimension === 2) {
            tracker.style.height = height;
        }
        else {
            tracker.style.width = height;
        }

        options.container.addEventListener('mousemove', mousemove);
    };

    if (options.enableMouseTracking) {
        initTracker();
    }


    return {
        target: target,
        getLength: getLength,
        getThickness: getThickness,
        getScale: getScale,
        setScale: setScale,
        dimension: dimension,
        orgPos: orgPos,
        drawRuler: drawRuler,
        destroy: destroy
    }
};

ruler.prototype.guideLine = function (line, _dragContainer, lineDimension, options, curDelta, moveCB, event) {

    var self,
        guideLine = line,
        _curScale = 1,
        _assigned = false,
        orientation = options.orientation,
        size = options.size, 
        _curPosDelta = curDelta || 0,
        dragContainer = _dragContainer,
        dimension = lineDimension || 2,
        moveCB = moveCB || function () {
        };


    var curPosDelta = function (val) {
        if (typeof val === 'undefined') {
            return _curPosDelta;
        }
        return (_curPosDelta = val);
    };

    var assigned = function (val) {
        if (typeof val === 'undefined') {
            return _assigned;
        }
        return (_assigned = val);
    };

    var curScale = function (val) {
        if (typeof val === 'undefined') {
            return _curScale;
        }
        return (_curScale = val);
    };


    var draggable = (function () {
        return {
            move: function (xpos, ypos) {
                guideLine.style.left = ruler.prototype.utils.pixelize(xpos);
                guideLine.style.top = ruler.prototype.utils.pixelize(ypos);
                //updateToolTip(xpos, ypos);
                moveCB(self, xpos, ypos);
            },
            startMoving: function (evt) {
                ruler.prototype.utils.addClasss(guideLine, ['rul_line_dragged']);
                evt = evt || window.event;

                var offsetHeight;
                switch (size) {
                case "A4":
                    if (orientation === "Landscape") {
                        offsetHeight = 794;
                    } else {
                        offsetHeight = 1123;
                    }

                    break;
                case "A3":
                    break;
                }

                var posX = evt ? evt.clientX : 0,
                    posY = evt ? evt.clientY : 0,
                    divTop = parseInt(guideLine.style.top || 0),
                    divLeft = parseInt(guideLine.style.left || 0),
                    eWi = parseInt(guideLine.offsetWidth),
                    eHe = parseInt(guideLine.offsetHeight),
                    cWi = parseInt(dragContainer.offsetWidth),
                    cHe = parseInt(offsetHeight),
                    cursor = dimension === 2 ? 'ns-resize' : 'ew-resize';

                options.container.style.cursor = cursor;
                guideLine.style.cursor = cursor;
                var diffX = posX - divLeft,
                    diffY = posY - divTop;
                document.onmousemove = function moving(evt) {
                    evt = evt || window.event;
                    var posX = evt.clientX,
                        posY = evt.clientY,
                        aX = posX - diffX,
                        aY = posY - diffY;

                    if (aX < 0) {
                        aX = 0;
                    }
                    if (aY < 0) {
                        aY = 0;
                    }

                    if (aX + eWi > cWi) {
                        aX = cWi - eWi;
                    }
                    if (aY + eHe > cHe) {
                        aY = cHe - eHe;
                    }

                    draggable.move(aX, aY);
                };
                showToolTip();
            },
            stopMoving: function () {
                options.container.style.cursor = null;
                guideLine.style.cursor = null;
                $(guideLine).trigger('guideLineMove');
                document.onmousemove = function () {
                };
                hideToolTip();
                ruler.prototype.utils.removeClasss(guideLine, ['rul_line_dragged']);
            }
        }
    })();

    var showToolTip = function (e) {
        if (!options.enableToolTip) {
            return;
        }
        ruler.prototype.utils.addClasss(guideLine, 'rul_tooltip');
    };

    var updateToolTip = function (x, y) {
        if (y) {
            guideLine.dataset.tip = 'Y: ' + Math.round((y - options.rulerHeight - 1 - _curPosDelta) * _curScale) + ' px';
        }
        else {
            guideLine.dataset.tip = 'X: ' + Math.round((x - options.rulerHeight - 1 - _curPosDelta) * _curScale) + ' px';
        }
    };

    var hideToolTip = function (e) {
        ruler.prototype.utils.removeClasss(guideLine, 'rul_tooltip');
    };

    var destroy = function () {
        draggable.stopMoving();
        moveCB = null;
        guideLine.removeEventListener('mousedown', mousedown);
        guideLine.removeEventListener('mouseup', mouseup);
        guideLine.removeEventListener('dblclick', dblclick);
        guideLine.parentNode && guideLine.parentNode.removeChild(guideLine);
    };

    var hide = function () {
        guideLine.style.display = 'none';
    };

    var show = function () {
        guideLine.style.display = 'block';
    };

    var mousedown = function (e) {
        e.stopPropagation();
        draggable.startMoving();
    };

    var mouseup = function (e) {
        draggable.stopMoving();
    };

    var dblclick = function (e) {
        e.stopPropagation();
        destroy();
    };

    guideLine.addEventListener('mousedown', mousedown);

    guideLine.addEventListener('mouseup', mouseup);

    guideLine.addEventListener('dblclick', dblclick);
    if (event) draggable.startMoving(event);

    self = {
        setAsDraggable: draggable,
        startDrag: draggable.startMoving,
        stopDrag: draggable.stopMoving,
        destroy: destroy,
        curScale: curScale,
        assigned: assigned,
        curPosDelta: curPosDelta,
        guideLine: guideLine,
        dimension: dimension,
        hide: hide,
        show: show
    };
    return self;

};

ruler.prototype.utils = {
    extend: function extend() {
        for (var i = 1; i < arguments.length; i++)
            for (var key in arguments[i])
                if (arguments[i].hasOwnProperty(key))
                    arguments[0][key] = arguments[i][key];
        return arguments[0];
    },
    prependChild: function (container, element) {
        return container.insertBefore(element, container.firstChild);
    },
    addClasss: function (element, classNames) {
        if (!(classNames instanceof Array)) {
            classNames = [classNames];
        }

        classNames.forEach(function (name) {
            element.className += ' ' + name;
        });

        return element;

    },
    removeClasss: function (element, classNames) {
        var curCalsss = element.className;
        if (!(classNames instanceof Array)) {
            classNames = [classNames];
        }

        classNames.forEach(function (name) {
            curCalsss = curCalsss.replace(name, '');
        });
        element.className = curCalsss;
        return element;

    },
    createEl: function (tag, parent) {
        var element = document.createElement(tag);
        if (parent)
            parent.appendChild(element);
        return element;
    },
    pixelize: function (val) {
        return val + 'px';
    },
    setAttributes: function (el, args) {
        for (var k in args) {
            if (args.hasOwnProperty(k)) {
                var val = args[k];
                el.setAttribute(k, val);
            }
        }
    }
};


module.exports = ruler;