/**
 * EPharma Multiple path - 1.00.110517
 *
 */
(function($) {

    var MultiplePath = function(node) {
        this.isMobile = ($(window).width() < 640);

        this.node = $(node);
        this.content = $('#content-main div.article');
        this.transitions = $('html').hasClass('csstransitions');

        this.width = 0;
        this.height = 0;

        this.clip = this.node.find('.navigation');
        this.nav = this.node.find('.path').eq(0);
        this.links = this.nav.find('a');
        this.current = this.node.find('.current');
        var link = this.current.find(' > a');

        this.navigate(link, false, false);

        this.nav.bind('click', this.handleNavClick.bind(this));

        this.relations = new LBi.LinkRelations();
        this.relations.subscribe(/path-/i, this.handlePathClick.bind(this));

        try {
            window.addEventListener('popstate', this.handlePopState.bind(this), false);
        } catch (e) {}

        this.scrollTo(0, 0);
        this.initDragging();

        this.contentHtml = this.content.html();
        this.expand(true);

        // Setup mobile
        if (this.isMobile) {
            this.initMobile();
        }
    };

    MultiplePath.prototype = {

        constructor: MultiplePath,

        initDragging: function() {
            this._mousedown = this.handleMousedown.bind(this);
            this._mousemove = this.handleMousemove.bind(this);
            this._mouseup = this.handleMouseup.bind(this);
            this._mouseleave = this.handleMouseleave.bind(this);

            this.touch = touchEnabled();
            if(this.touch) {
                var node = this.clip[0];
                node.addEventListener('touchstart', this._mousedown, false);
                node.addEventListener('touchend', this._mouseup, false);
            } else {
                this.clip.bind('mousedown', this._mousedown);
                this.clip.bind('mouseup', this._mouseup);
                this.clip.bind('mouseleave', this._mouseleave);
            }

            if(!this.node.hasClass('collapsed')) {
                this.findDimensions();
            }
            var self = this;
            $(window).load( function() {
                self.enable();
            });

        },

        handleNavClick: function(e) {
            e.preventDefault();

            if(this.navEnabled){
                var link = $(e.target).closest('a');
                if(link.length) {
                    e.preventDefault();
                    if(!this.swiped) {
                        this.navigate(link, true, true);
                    }
                }
            }
        },

        handlePathClick: function(e) {

            e.preventDefault();

            var link = $(e.target).closest('a');
            var rel = link.attr('rel');
            var type = /path-([^ ]+)/.exec(rel)[1];
            switch (type) {
                case 'link':
                    var href = link.attr('href');
                    this.findPath(href, true);
                    $('html,body').animate(
                        {scrollTop: this.node.offset().top},
                        500,
                        this.handlePageScroll.bind(this)
                    );
                break;
                case 'toggle':
                    var mode = this.node.hasClass('collapsed');
                    this.expand(mode);
                break;
                case 'up':
                    this.scroll(0);
                break;
                case 'right':
                    this.scroll(1);
                break;
                case 'down':
                    this.scroll(2);
                break;
                case 'left':
                    this.scroll(3);
                break;
            }
        },

        handlePageScroll: function() {
            if (this.isMobile) {
                EPHARMA.setMobileNav();
            }
        },

        handleMousedown: function(e) {
            this.swiped = false;
            var event = this.getEvent(e);
            e.preventDefault();

            this.cx = event.clientX;
            this.cy = event.clientY;

            this.corX = this.posX;
            this.corY = this.posY;

            if(this.touch) {
                this.clip[0].addEventListener('touchmove', this._mousemove, false);
            } else {
                this.clip.bind('mousemove', this._mousemove);
            }
        },

        handleMousemove: function(e) {
            var event = this.getEvent(e);
            e.preventDefault();

            var tx = (event.clientX - this.cx + this.corX);
            var ty = (event.clientY - this.cy + this.corY);

            //var dx = this.cx - event.clientX;
            //var dy = this.cy - event.clientY;

            //var dpos = Math.max(dx, dy);
            //var dneg = Math.min(dx, dy);

            //if(dpos > 29 || dneg < -29) {
                this.moveTo(tx, ty, false);
            //}

            //this.triggerClick(event);

        },

        handleMouseup: function(e) {
            var event = this.getEvent(e);
            e.preventDefault();

            /*var tx = (event.clientX - this.cx);
            var ty = (event.clientY - this.cy);

            var dx = tx - this.posX;
            var dy = ty - this.posY;

            //this.moveTo(tx, ty);

            if(Math.sqrt(dx*dx + dy*dy) < 10) {
                // touch based devices cancel click when preventing touch events.
                if(this.touch) {
                    this.triggerClick(event);
                }
            } else {
                this.swiped = true;
            }
            */
            if(this.touch) {
                this.clip[0].removeEventListener('touchmove', this._mousemove, false);
                // Check if the user touch on a link or the text of the link
                if ($(e.target).is('a') || e.target instanceof Text) {
                    this.handleNavClick(e);
                }
            } else {
                this.clip.unbind('mousemove', this._mousemove);
            }
        },

        handleMouseleave: function(e) {
            this.clip.unbind('mousemove', this._mousemove);
        },

        getEvent: function(e) {
            var event = e;

            var touch = e.touches;
            var changed = e.changedTouches;

            if(touch && touch[0]) {
                event = touch[0];
            } else if(changed && changed[0]) {
                event = changed[0];
            }

            return event;
        },

        /*triggerClick: function(e) {
            var event = document.createEvent('MouseEvent');
            event.initMouseEvent("click", true, true, window, 1,
                e.screenX, e.screenY, e.clientX, e.clientY, false, false, false, false, 0, null);
            e.target.dispatchEvent(event);
        },*/

        handlePopState: function(e) {
            var state = e.state;
            if(state && state.path) {
                this.findPath(state.path, false);
            } else {
                // Reset the multi path to the original state
                this.reset();
            }
        },

        expand: function(toggle) {
            this.node.toggleClass('collapsed', !toggle);
            var text = (toggle) ? 'Collapse' : 'Expand';
            $('.switch', this.node).text(text);
            this.findDimensions();
            this.scrollTo(0,0);
        },

        findDimensions: function() {
            var items = this.node.find('li:visible');
            var width = 0;
            var height = 0;
            var i, l = items.length;
            for(var i=0; i<l; i++) {
                var node = items[i];
                width = Math.max(width, node.offsetLeft + node.offsetWidth);
                height = Math.max(height, node.offsetTop + node.offsetHeight);
            }

            this.width = width;
            this.height = height;
            this.nav.width(width);
        },

        findPath: function(href, save) {
            var target = this.links.filter('a[href="' + href + '"]');
            if(target.length) {
                this.navigate(target.eq(0), true, save);
            } else {
                this.load(href, save);
            }
        },

        navigate: function(link, load, save) {
            var item = link.closest('li');
            if(item.length) {
                this.clearPath();
                this.setPath(item);
                this.setCurrent(item);
            }

            var href = link.attr('href');
            if(load && href) {
                this.load(href, save);
            }
        },

        scroll: function(dir) {
            var x = this.posX;
            var y = this.posY;

            switch (dir) {
                case 0:y += 200;break;
                case 1:x -= 200;break;
                case 2:y -= 200;break;
                case 3:x += 200;break;
            }

            this.moveTo(x, y, true);
        },

        moveTo: function(x, y, trans) {
            var clipW = this.clip.width();
            var clipH = this.clip.height();

            this.posX = parseInt(Math.min(0, Math.max(x, clipW - this.width - 10)), 10);
            this.posY = parseInt(Math.min(0, Math.max(y, clipH - this.height - 10)), 10);

            var css = this.nav[0].style, duration;

            if (trans) {
                this.nav.removeClass('notransition');
                duration = 250;
            } else {
                this.nav.addClass('notransition');
                duration = 0;
            }

            if (this.transitions) {
                var translate = 'translate(' + this.posX + 'px, ' + this.posY + 'px)';
                css.WebkitTransform = translate;
                css.MozTransform = translate;
                css.OTransform = translate;
                css.transform = translate;
            } else {
                this.nav.stop().animate({left : this.posX, top: this.posY}, duration);
            }
        },

        scrollTo: function(x, y) {
            this.posX = x;
            this.posY = y;
            this.scroll(-1);
        },

        load: function(href, saveState) {
            $.ajax({
                url: href,
                type: 'get',
                dataType: 'html',
                success: this.handleResponse.bind(this)
            });

            if(saveState && history.pushState) {
                history.pushState({path: href}, '', href);
            }
        },

        clearPath: function() {
            if(this.breadcrumb) {
                this.breadcrumb.removeClass('active');
            }

            this.breadcrumb = $();
        },

        addToPath: function(item) {
            item.addClass('active');
            this.breadcrumb = this.breadcrumb.add(item);
        },

        setCurrent: function(item) {
            this.current.removeClass('current');
            (this.current = item).addClass('current');
        },

        setPath: function(item) {
            var list = item.closest('ul, ol');
            var next = null;
            if(!list.length) {
                return;
            }

            this.addToPath(item);

            if(list.hasClass('path')) {
                next = item.prev();
                if(next.length === 0) {
                    next = list.closest('li');
                }
            }

            if(list.hasClass('group')) {
                next = list.closest('li');
            }

            next && this.setPath(next);
        },

        handleResponse: function(response) {
//            this.navEnabled = true;
            this.content.html(response);

            var self = this;
            setTimeout(function() {
                self.expand(false);
            }, 500);
        },

        enable: function(){
            this.navEnabled = true;
        },

        /**
         * Resets the multi path to the original state.
         */
        reset: function() {
            // Set the main content to the original content
            this.content.html(this.contentHtml);
            // Navigate to the starting node
            this.navigate(this.nav.find('.start a'), false, false);
            // Find the dimensions to set the path block right
            this.findDimensions();
            // Expand the multi path
            if (this.isMobile) {
                this.expand(false);
            } else {
                this.expand(true);
            }
        },

        /**
         * Initializes the mobile extra's.
         */
        initMobile: function() {
            // Shrink the view port
            this.expand(false);

            // Set the mobile nav size
            this.setMobileNavSize();

            // On orientation change
            this.isLandscape = $(window).width() > $(window).height();
            $(window).bind('resize', this.mobileOrientationChange.bind(this));
        },

        /**
         * Handles the orientation change.
         */
        mobileOrientationChange: function() {
            // Get orientation of screen
            var landscape = $(window).width() > $(window).height();
            if (landscape != this.isLandscape) {
                // Set the nav size
                this.setMobileNavSize();
                this.isLandscape = landscape;
            }
        },

        /**
         * Sets the size of the mobile navigation.
          */
        setMobileNavSize: function() {
            var width = $(window).width();
            this.node.css('width', width + 'px');
        }
    };


    function touchEnabled() {
        return !!('ontouchstart' in window);
    }

    window.MultiplePath = MultiplePath;

}(window.jQuery));

