/*
 * jQuery FlexSlider v2.6.3
 * Copyright 2012 WooThemes
 * Contributing Author: Tyler Smith
 */
;
(function ($) {

    var focused = true;

    //FlexSlider: Object Instance
    $.flexslider = function (el, options) {
        var slider = $(el);

        // making variables public
        slider.vars = $.extend({}, $.flexslider.defaults, options);

        var namespace = slider.vars.namespace,
            msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
            touch = (("ontouchstart" in window) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,
            // depricating this idea, as devices are being released with both of these events
            eventType = "click touchend MSPointerUp keyup",
            watchedEvent = "",
            watchedEventClearTimer,
            vertical = slider.vars.direction === "vertical",
            reverse = slider.vars.reverse,
            carousel = (slider.vars.itemWidth > 0),
            fade = slider.vars.animation === "fade",
            asNav = slider.vars.asNavFor !== "",
            methods = {};

        // Store a reference to the slider object
        $.data(el, "flexslider", slider);

        // Private slider methods
        methods = {
            init: function () {
                slider.animating = false;
                // Get current slide and make sure it is a number
                slider.currentSlide = parseInt((slider.vars.startAt ? slider.vars.startAt : 0), 10);
                if (isNaN(slider.currentSlide)) { slider.currentSlide = 0; }
                slider.animatingTo = slider.currentSlide;
                slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
                slider.containerSelector = slider.vars.selector.substr(0, slider.vars.selector.search(' '));
                slider.slides = $(slider.vars.selector, slider);
                slider.container = $(slider.containerSelector, slider);
                slider.count = slider.slides.length;
                // SYNC:
                slider.syncExists = $(slider.vars.sync).length > 0;
                // SLIDE:
                if (slider.vars.animation === "slide") { slider.vars.animation = "swing"; }
                slider.prop = (vertical) ? "top" : "marginLeft";
                slider.args = {};
                // SLIDESHOW:
                slider.manualPause = false;
                slider.stopped = false;
                //PAUSE WHEN INVISIBLE
                slider.started = false;
                slider.startTimeout = null;
                // TOUCH/USECSS:
                slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function () {
                    var obj = document.createElement('div'),
                        props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
                    for (var i in props) {
                        if (obj.style[props[i]] !== undefined) {
                            slider.pfx = props[i].replace('Perspective', '').toLowerCase();
                            slider.prop = "-" + slider.pfx + "-transform";
                            return true;
                        }
                    }
                    return false;
                }());
                slider.ensureAnimationEnd = '';
                // CONTROLSCONTAINER:
                if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);
                // MANUAL:
                if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);

                // CUSTOM DIRECTION NAV:
                if (slider.vars.customDirectionNav !== "") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);

                // RANDOMIZE:
                if (slider.vars.randomize) {
                    slider.slides.sort(function () { return (Math.round(Math.random()) - 0.5); });
                    slider.container.empty().append(slider.slides);
                }

                slider.doMath();

                // INIT
                slider.setup("init");

                // CONTROLNAV:
                if (slider.vars.controlNav) { methods.controlNav.setup(); }

                // DIRECTIONNAV:
                if (slider.vars.directionNav) { methods.directionNav.setup(); }

                // KEYBOARD:
                if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {
                    $(document).bind('keyup', function (event) {
                        var keycode = event.keyCode;
                        if (!slider.animating && (keycode === 39 || keycode === 37)) {
                            var target = (keycode === 39) ? slider.getTarget('next') :
                                         (keycode === 37) ? slider.getTarget('prev') : false;
                            slider.flexAnimate(target, slider.vars.pauseOnAction);
                        }
                    });
                }
                // MOUSEWHEEL:
                if (slider.vars.mousewheel) {
                    slider.bind('mousewheel', function (event, delta, deltaX, deltaY) {
                        event.preventDefault();
                        var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
                        slider.flexAnimate(target, slider.vars.pauseOnAction);
                    });
                }

                // PAUSEPLAY
                if (slider.vars.pausePlay) { methods.pausePlay.setup(); }

                //PAUSE WHEN INVISIBLE
                if (slider.vars.slideshow && slider.vars.pauseInvisible) { methods.pauseInvisible.init(); }

                // SLIDSESHOW
                if (slider.vars.slideshow) {
                    if (slider.vars.pauseOnHover) {
                        slider.hover(function () {
                            if (!slider.manualPlay && !slider.manualPause) { slider.pause(); }
                        }, function () {
                            if (!slider.manualPause && !slider.manualPlay && !slider.stopped) { slider.play(); }
                        });
                    }
                    // initialize animation
                    //If we're visible, or we don't use PageVisibility API
                    if (!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {
                        (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();
                    }
                }

                // ASNAV:
                if (asNav) { methods.asNav.setup(); }

                // TOUCH
                if (touch && slider.vars.touch) { methods.touch(); }

                // FADE&&SMOOTHHEIGHT || SLIDE:
                if (!fade || (fade && slider.vars.smoothHeight)) { $(window).bind("resize orientationchange focus", methods.resize); }

                slider.find("img").attr("draggable", "false");

                // API: start() Callback
                setTimeout(function () {
                    slider.vars.start(slider);
                }, 200);
            },
            asNav: {
                setup: function () {
                    slider.asNav = true;
                    slider.animatingTo = Math.floor(slider.currentSlide / slider.move);
                    slider.currentItem = slider.currentSlide;
                    slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
                    if (!msGesture) {
                        slider.slides.on(eventType, function (e) {
                            e.preventDefault();
                            var $slide = $(this),
                                target = $slide.index();
                            var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container
                            if (posFromLeft <= 0 && $slide.hasClass(namespace + 'active-slide')) {
                                slider.flexAnimate(slider.getTarget("prev"), true);
                            } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) {
                                slider.direction = (slider.currentItem < target) ? "next" : "prev";
                                slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
                            }
                        });
                    } else {
                        el._slider = slider;
                        slider.slides.each(function () {
                            var that = this;
                            that._gesture = new MSGesture();
                            that._gesture.target = that;
                            that.addEventListener("MSPointerDown", function (e) {
                                e.preventDefault();
                                if (e.currentTarget._gesture) {
                                    e.currentTarget._gesture.addPointer(e.pointerId);
                                }
                            }, false);
                            that.addEventListener("MSGestureTap", function (e) {
                                e.preventDefault();
                                var $slide = $(this),
                                    target = $slide.index();
                                if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
                                    slider.direction = (slider.currentItem < target) ? "next" : "prev";
                                    slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
                                }
                            });
                        });
                    }
                }
            },
            controlNav: {
                setup: function () {
                    if (!slider.manualControls) {
                        methods.controlNav.setupPaging();
                    } else { // MANUALCONTROLS:
                        methods.controlNav.setupManual();
                    }
                },
                setupPaging: function () {
                    var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
                        j = 1,
                        item,
                        slide;

                    slider.controlNavScaffold = $('<ol class="' + namespace + 'control-nav ' + namespace + type + '"></ol>');

                    if (slider.pagingCount > 1) {
                        for (var i = 0; i < slider.pagingCount; i++) {
                            slide = slider.slides.eq(i);
                            if (undefined === slide.attr('data-thumb-alt')) { slide.attr('data-thumb-alt', ''); }
                            var altText = ('' !== slide.attr('data-thumb-alt')) ? altText = ' alt="' + slide.attr('data-thumb-alt') + '"' : '';
                            item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr('data-thumb') + '"' + altText + '/>' : '<a href="#">' + j + '</a>';
                            if ('thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions) {
                                var captn = slide.attr('data-thumbcaption');
                                if ('' !== captn && undefined !== captn) { item += '<span class="' + namespace + 'caption">' + captn + '</span>'; }
                            }
                            slider.controlNavScaffold.append('<li>' + item + '</li>');
                            j++;
                        }
                    }

                    // CONTROLSCONTAINER:
                    (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
                    methods.controlNav.set();

                    methods.controlNav.active();

                    slider.controlNavScaffold.delegate('a, img', eventType, function (event) {
                        event.preventDefault();

                        if (watchedEvent === "" || watchedEvent === event.type) {
                            var $this = $(this),
                                target = slider.controlNav.index($this);

                            if (!$this.hasClass(namespace + 'active')) {
                                slider.direction = (target > slider.currentSlide) ? "next" : "prev";
                                slider.flexAnimate(target, slider.vars.pauseOnAction);
                            }
                        }

                        // setup flags to prevent event duplication
                        if (watchedEvent === "") {
                            watchedEvent = event.type;
                        }
                        methods.setToClearWatchedEvent();

                    });
                },
                setupManual: function () {
                    slider.controlNav = slider.manualControls;
                    methods.controlNav.active();

                    slider.controlNav.bind(eventType, function (event) {
                        event.preventDefault();

                        if (watchedEvent === "" || watchedEvent === event.type) {
                            var $this = $(this),
                                target = slider.controlNav.index($this);

                            if (!$this.hasClass(namespace + 'active')) {
                                (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
                                slider.flexAnimate(target, slider.vars.pauseOnAction);
                            }
                        }

                        // setup flags to prevent event duplication
                        if (watchedEvent === "") {
                            watchedEvent = event.type;
                        }
                        methods.setToClearWatchedEvent();
                    });
                },
                set: function () {
                    var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a';
                    slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
                },
                active: function () {
                    slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
                },
                update: function (action, pos) {
                    if (slider.pagingCount > 1 && action === "add") {
                        slider.controlNavScaffold.append($('<li><a href="#">' + slider.count + '</a></li>'));
                    } else if (slider.pagingCount === 1) {
                        slider.controlNavScaffold.find('li').remove();
                    } else {
                        slider.controlNav.eq(pos).closest('li').remove();
                    }
                    methods.controlNav.set();
                    (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
                }
            },
            directionNav: {
                setup: function () {
                    var directionNavScaffold = $('<ul class="' + namespace + 'direction-nav"><li class="' + namespace + 'nav-prev"><a class="' + namespace + 'prev" href="#">' + slider.vars.prevText + '</a></li><li class="' + namespace + 'nav-next"><a class="' + namespace + 'next" href="#">' + slider.vars.nextText + '</a></li></ul>');

                    // CUSTOM DIRECTION NAV:
                    if (slider.customDirectionNav) {
                        slider.directionNav = slider.customDirectionNav;
                        // CONTROLSCONTAINER:
                    } else if (slider.controlsContainer) {
                        $(slider.controlsContainer).append(directionNavScaffold);
                        slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
                    } else {
                        slider.append(directionNavScaffold);
                        slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
                    }

                    methods.directionNav.update();

                    slider.directionNav.bind(eventType, function (event) {
                        event.preventDefault();
                        var target;

                        if (watchedEvent === "" || watchedEvent === event.type) {
                            target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
                            slider.flexAnimate(target, slider.vars.pauseOnAction);
                        }

                        // setup flags to prevent event duplication
                        if (watchedEvent === "") {
                            watchedEvent = event.type;
                        }
                        methods.setToClearWatchedEvent();
                    });
                },
                update: function () {
                    var disabledClass = namespace + 'disabled';
                    if (slider.pagingCount === 1) {
                        slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');
                    } else if (!slider.vars.animationLoop) {
                        if (slider.animatingTo === 0) {
                            slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1');
                        } else if (slider.animatingTo === slider.last) {
                            slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1');
                        } else {
                            slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
                        }
                    } else {
                        slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
                    }
                }
            },
            pausePlay: {
                setup: function () {
                    var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a href="#"></a></div>');

                    // CONTROLSCONTAINER:
                    if (slider.controlsContainer) {
                        slider.controlsContainer.append(pausePlayScaffold);
                        slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
                    } else {
                        slider.append(pausePlayScaffold);
                        slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
                    }

                    methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');

                    slider.pausePlay.bind(eventType, function (event) {
                        event.preventDefault();

                        if (watchedEvent === "" || watchedEvent === event.type) {
                            if ($(this).hasClass(namespace + 'pause')) {
                                slider.manualPause = true;
                                slider.manualPlay = false;
                                slider.pause();
                            } else {
                                slider.manualPause = false;
                                slider.manualPlay = true;
                                slider.play();
                            }
                        }

                        // setup flags to prevent event duplication
                        if (watchedEvent === "") {
                            watchedEvent = event.type;
                        }
                        methods.setToClearWatchedEvent();
                    });
                },
                update: function (state) {
                    (state === "play") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText);
                }
            },
            touch: function () {
                var startX,
                  startY,
                  offset,
                  cwidth,
                  dx,
                  startT,
                  onTouchStart,
                  onTouchMove,
                  onTouchEnd,
                  scrolling = false,
                  localX = 0,
                  localY = 0,
                  accDx = 0;

                if (!msGesture) {
                    onTouchStart = function (e) {
                        if (slider.animating) {
                            e.preventDefault();
                        } else if ((window.navigator.msPointerEnabled) || e.touches.length === 1) {
                            slider.pause();
                            // CAROUSEL:
                            cwidth = (vertical) ? slider.h : slider.w;
                            startT = Number(new Date());
                            // CAROUSEL:

                            // Local vars for X and Y points.
                            localX = e.touches[0].pageX;
                            localY = e.touches[0].pageY;

                            offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
                                     (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
                                     (carousel && slider.currentSlide === slider.last) ? slider.limit :
                                     (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
                                     (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
                            startX = (vertical) ? localY : localX;
                            startY = (vertical) ? localX : localY;

                            el.addEventListener('touchmove', onTouchMove, false);
                            el.addEventListener('touchend', onTouchEnd, false);
                        }
                    };

                    onTouchMove = function (e) {
                        // Local vars for X and Y points.

                        localX = e.touches[0].pageX;
                        localY = e.touches[0].pageY;

                        dx = (vertical) ? startX - localY : startX - localX;
                        scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));

                        var fxms = 500;

                        if (!scrolling || Number(new Date()) - startT > fxms) {
                            e.preventDefault();
                            if (!fade && slider.transitions) {
                                if (!slider.vars.animationLoop) {
                                    dx = dx / ((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx) / cwidth + 2) : 1);
                                }
                                slider.setProps(offset + dx, "setTouch");
                            }
                        }
                    };

                    onTouchEnd = function (e) {
                        // finish the touch by undoing the touch session
                        el.removeEventListener('touchmove', onTouchMove, false);

                        if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
                            var updateDx = (reverse) ? -dx : dx,
                                target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');

                            if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {
                                slider.flexAnimate(target, slider.vars.pauseOnAction);
                            } else {
                                if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
                            }
                        }
                        el.removeEventListener('touchend', onTouchEnd, false);

                        startX = null;
                        startY = null;
                        dx = null;
                        offset = null;
                    };

                    el.addEventListener('touchstart', onTouchStart, false);
                } else {
                    el.style.msTouchAction = "none";
                    el._gesture = new MSGesture();
                    el._gesture.target = el;
                    el.addEventListener("MSPointerDown", onMSPointerDown, false);
                    el._slider = slider;
                    el.addEventListener("MSGestureChange", onMSGestureChange, false);
                    el.addEventListener("MSGestureEnd", onMSGestureEnd, false);

                    function onMSPointerDown(e) {
                        e.stopPropagation();
                        if (slider.animating) {
                            e.preventDefault();
                        } else {
                            slider.pause();
                            el._gesture.addPointer(e.pointerId);
                            accDx = 0;
                            cwidth = (vertical) ? slider.h : slider.w;
                            startT = Number(new Date());
                            // CAROUSEL:

                            offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
                                (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
                                    (carousel && slider.currentSlide === slider.last) ? slider.limit :
                                        (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
                                            (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
                        }
                    }

                    function onMSGestureChange(e) {
                        e.stopPropagation();
                        var slider = e.target._slider;
                        if (!slider) {
                            return;
                        }
                        var transX = -e.translationX,
                            transY = -e.translationY;

                        //Accumulate translations.
                        accDx = accDx + ((vertical) ? transY : transX);
                        dx = accDx;
                        scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));

                        if (e.detail === e.MSGESTURE_FLAG_INERTIA) {
                            setImmediate(function () {
                                el._gesture.stop();
                            });

                            return;
                        }

                        if (!scrolling || Number(new Date()) - startT > 500) {
                            e.preventDefault();
                            if (!fade && slider.transitions) {
                                if (!slider.vars.animationLoop) {
                                    dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);
                                }
                                slider.setProps(offset + dx, "setTouch");
                            }
                        }
                    }

                    function onMSGestureEnd(e) {
                        e.stopPropagation();
                        var slider = e.target._slider;
                        if (!slider) {
                            return;
                        }
                        if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
                            var updateDx = (reverse) ? -dx : dx,
                                target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');

                            if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {
                                slider.flexAnimate(target, slider.vars.pauseOnAction);
                            } else {
                                if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
                            }
                        }

                        startX = null;
                        startY = null;
                        dx = null;
                        offset = null;
                        accDx = 0;
                    }
                }
            },
            resize: function () {
                if (!slider.animating && slider.is(':visible')) {
                    if (!carousel) { slider.doMath(); }

                    if (fade) {
                        // SMOOTH HEIGHT:
                        methods.smoothHeight();
                    } else if (carousel) { //CAROUSEL:
                        slider.slides.width(slider.computedW);
                        slider.update(slider.pagingCount);
                        slider.setProps();
                    }
                    else if (vertical) { //VERTICAL:
                        slider.viewport.height(slider.h);
                        slider.setProps(slider.h, "setTotal");
                    } else {
                        // SMOOTH HEIGHT:
                        if (slider.vars.smoothHeight) { methods.smoothHeight(); }
                        slider.newSlides.width(slider.computedW);
                        slider.setProps(slider.computedW, "setTotal");
                    }
                }
            },
            smoothHeight: function (dur) {
                if (!vertical || fade) {
                    var $obj = (fade) ? slider : slider.viewport;
                    (dur) ? $obj.animate({ "height": slider.slides.eq(slider.animatingTo).innerHeight() }, dur) : $obj.innerHeight(slider.slides.eq(slider.animatingTo).innerHeight());
                }
            },
            sync: function (action) {
                var $obj = $(slider.vars.sync).data("flexslider"),
                    target = slider.animatingTo;

                switch (action) {
                    case "animate": $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true); break;
                    case "play": if (!$obj.playing && !$obj.asNav) { $obj.play(); } break;
                    case "pause": $obj.pause(); break;
                }
            },
            uniqueID: function ($clone) {
                // Append _clone to current level and children elements with id attributes
                $clone.filter('[id]').add($clone.find('[id]')).each(function () {
                    var $this = $(this);
                    $this.attr('id', $this.attr('id') + '_clone');
                });
                return $clone;
            },
            pauseInvisible: {
                visProp: null,
                init: function () {
                    var visProp = methods.pauseInvisible.getHiddenProp();
                    if (visProp) {
                        var evtname = visProp.replace(/[H|h]idden/, '') + 'visibilitychange';
                        document.addEventListener(evtname, function () {
                            if (methods.pauseInvisible.isHidden()) {
                                if (slider.startTimeout) {
                                    clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible
                                } else {
                                    slider.pause(); //Or just pause
                                }
                            }
                            else {
                                if (slider.started) {
                                    slider.play(); //Initiated before, just play
                                } else {
                                    if (slider.vars.initDelay > 0) {
                                        setTimeout(slider.play, slider.vars.initDelay);
                                    } else {
                                        slider.play(); //Didn't init before: simply init or wait for it
                                    }
                                }
                            }
                        });
                    }
                },
                isHidden: function () {
                    var prop = methods.pauseInvisible.getHiddenProp();
                    if (!prop) {
                        return false;
                    }
                    return document[prop];
                },
                getHiddenProp: function () {
                    var prefixes = ['webkit', 'moz', 'ms', 'o'];
                    // if 'hidden' is natively supported just return it
                    if ('hidden' in document) {
                        return 'hidden';
                    }
                    // otherwise loop over all the known prefixes until we find one
                    for (var i = 0; i < prefixes.length; i++) {
                        if ((prefixes[i] + 'Hidden') in document) {
                            return prefixes[i] + 'Hidden';
                        }
                    }
                    // otherwise it's not supported
                    return null;
                }
            },
            setToClearWatchedEvent: function () {
                clearTimeout(watchedEventClearTimer);
                watchedEventClearTimer = setTimeout(function () {
                    watchedEvent = "";
                }, 3000);
            }
        };

        // public methods
        slider.flexAnimate = function (target, pause, override, withSync, fromNav) {
            if (!slider.vars.animationLoop && target !== slider.currentSlide) {
                slider.direction = (target > slider.currentSlide) ? "next" : "prev";
            }

            if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";

            if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
                if (asNav && withSync) {
                    var master = $(slider.vars.asNavFor).data('flexslider');
                    slider.atEnd = target === 0 || target === slider.count - 1;
                    master.flexAnimate(target, true, false, true, fromNav);
                    slider.direction = (slider.currentItem < target) ? "next" : "prev";
                    master.direction = slider.direction;

                    if (Math.ceil((target + 1) / slider.visible) - 1 !== slider.currentSlide && target !== 0) {
                        slider.currentItem = target;
                        slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
                        target = Math.floor(target / slider.visible);
                    } else {
                        slider.currentItem = target;
                        slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
                        return false;
                    }
                }

                slider.animating = true;
                slider.animatingTo = target;

                // SLIDESHOW:
                if (pause) { slider.pause(); }

                // API: before() animation Callback
                slider.vars.before(slider);

                // SYNC:
                if (slider.syncExists && !fromNav) { methods.sync("animate"); }

                // CONTROLNAV
                if (slider.vars.controlNav) { methods.controlNav.active(); }

                // !CAROUSEL:
                // CANDIDATE: slide active class (for add/remove slide)
                if (!carousel) { slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide'); }

                // INFINITE LOOP:
                // CANDIDATE: atEnd
                slider.atEnd = target === 0 || target === slider.last;

                // DIRECTIONNAV:
                if (slider.vars.directionNav) { methods.directionNav.update(); }

                if (target === slider.last) {
                    // API: end() of cycle Callback
                    slider.vars.end(slider);
                    // SLIDESHOW && !INFINITE LOOP:
                    if (!slider.vars.animationLoop) { slider.pause(); }
                }

                // SLIDE:
                if (!fade) {
                    var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
                        margin, slideString, calcNext;

                    // INFINITE LOOP / REVERSE:
                    if (carousel) {
                        margin = slider.vars.itemMargin;
                        calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
                        slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
                    } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") {
                        slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
                    } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") {
                        slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
                    } else {
                        slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
                    }
                    slider.setProps(slideString, "", slider.vars.animationSpeed);
                    if (slider.transitions) {
                        if (!slider.vars.animationLoop || !slider.atEnd) {
                            slider.animating = false;
                            slider.currentSlide = slider.animatingTo;
                        }

                        // Unbind previous transitionEnd events and re-bind new transitionEnd event
                        slider.container.unbind("webkitTransitionEnd transitionend");
                        slider.container.bind("webkitTransitionEnd transitionend", function () {
                            clearTimeout(slider.ensureAnimationEnd);
                            slider.wrapup(dimension);
                        });

                        // Insurance for the ever-so-fickle transitionEnd event
                        clearTimeout(slider.ensureAnimationEnd);
                        slider.ensureAnimationEnd = setTimeout(function () {
                            slider.wrapup(dimension);
                        }, slider.vars.animationSpeed + 100);

                    } else {
                        slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function () {
                            slider.wrapup(dimension);
                        });
                    }
                } else { // FADE:
                    if (!touch) {
                        slider.slides.eq(slider.currentSlide).css({ "zIndex": 1 }).animate({ "opacity": 0 }, slider.vars.animationSpeed, slider.vars.easing);
                        slider.slides.eq(target).css({ "zIndex": 2 }).animate({ "opacity": 1 }, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
                    } else {
                        slider.slides.eq(slider.currentSlide).css({ "opacity": 0, "zIndex": 1 });
                        slider.slides.eq(target).css({ "opacity": 1, "zIndex": 2 });
                        slider.wrapup(dimension);
                    }
                }
                // SMOOTH HEIGHT:
                if (slider.vars.smoothHeight) { methods.smoothHeight(slider.vars.animationSpeed); }
            }
        };
        slider.wrapup = function (dimension) {
            // SLIDE:
            if (!fade && !carousel) {
                if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {
                    slider.setProps(dimension, "jumpEnd");
                } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {
                    slider.setProps(dimension, "jumpStart");
                }
            }
            slider.animating = false;
            slider.currentSlide = slider.animatingTo;
            // API: after() animation Callback
            slider.vars.after(slider);
        };

        // SLIDESHOW:
        slider.animateSlides = function () {
            if (!slider.animating && focused) { slider.flexAnimate(slider.getTarget("next")); }
        };
        // SLIDESHOW:
        slider.pause = function () {
            clearInterval(slider.animatedSlides);
            slider.animatedSlides = null;
            slider.playing = false;
            // PAUSEPLAY:
            if (slider.vars.pausePlay) { methods.pausePlay.update("play"); }
            // SYNC:
            if (slider.syncExists) { methods.sync("pause"); }
        };
        // SLIDESHOW:
        slider.play = function () {
            if (slider.playing) { clearInterval(slider.animatedSlides); }
            slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
            slider.started = slider.playing = true;
            // PAUSEPLAY:
            if (slider.vars.pausePlay) { methods.pausePlay.update("pause"); }
            // SYNC:
            if (slider.syncExists) { methods.sync("play"); }
        };
        // STOP:
        slider.stop = function () {
            slider.pause();
            slider.stopped = true;
        };
        slider.canAdvance = function (target, fromNav) {
            // ASNAV:
            var last = (asNav) ? slider.pagingCount - 1 : slider.last;
            return (fromNav) ? true :
                   (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
                   (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
                   (target === slider.currentSlide && !asNav) ? false :
                   (slider.vars.animationLoop) ? true :
                   (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
                   (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
                   true;
        };
        slider.getTarget = function (dir) {
            slider.direction = dir;
            if (dir === "next") {
                return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
            } else {
                return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
            }
        };

        // SLIDE:
        slider.setProps = function (pos, special, dur) {
            var target = (function () {
                var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,
                    posCalc = (function () {
                        if (carousel) {
                            return (special === "setTouch") ? pos :
                                   (reverse && slider.animatingTo === slider.last) ? 0 :
                                   (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
                                   (slider.animatingTo === slider.last) ? slider.limit : posCheck;
                        } else {
                            switch (special) {
                                case "setTotal": return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
                                case "setTouch": return (reverse) ? pos : pos;
                                case "jumpEnd": return (reverse) ? pos : slider.count * pos;
                                case "jumpStart": return (reverse) ? slider.count * pos : pos;
                                default: return pos;
                            }
                        }
                    }());

                return (posCalc * -1) + "px";
            }());

            if (slider.transitions) {
                target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + target + ",0,0)";
                dur = (dur !== undefined) ? (dur / 1000) + "s" : "0s";
                slider.container.css("-" + slider.pfx + "-transition-duration", dur);
                slider.container.css("transition-duration", dur);
            }

            slider.args[slider.prop] = target;
            if (slider.transitions || dur === undefined) { slider.container.css(slider.args); }

            slider.container.css('transform', target);
        };

        slider.setup = function (type) {
            // SLIDE:
            if (!fade) {
                var sliderOffset, arr;

                if (type === "init") {
                    slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({ "overflow": "hidden", "position": "relative" }).appendTo(slider).append(slider.container);
                    // INFINITE LOOP:
                    slider.cloneCount = 0;
                    slider.cloneOffset = 0;
                    // REVERSE:
                    if (reverse) {
                        arr = $.makeArray(slider.slides).reverse();
                        slider.slides = $(arr);
                        slider.container.empty().append(slider.slides);
                    }
                }
                // INFINITE LOOP && !CAROUSEL:
                if (slider.vars.animationLoop && !carousel) {
                    slider.cloneCount = 2;
                    slider.cloneOffset = 1;
                    // clear out old clones
                    if (type !== "init") { slider.container.find('.clone').remove(); }
                    slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))
                                    .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));
                }
                slider.newSlides = $(slider.vars.selector, slider);

                sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
                // VERTICAL:
                if (vertical && !carousel) {
                    slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
                    setTimeout(function () {
                        slider.newSlides.css({ "display": "block" });
                        slider.doMath();
                        slider.viewport.height(slider.h);
                        slider.setProps(sliderOffset * slider.h, "init");
                    }, (type === "init") ? 100 : 0);
                } else {
                    slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
                    slider.setProps(sliderOffset * slider.computedW, "init");
                    setTimeout(function () {
                        slider.doMath();
                        slider.newSlides.css({ "width": slider.computedW, "marginRight": slider.computedM, "float": "left", "display": "block" });
                        // SMOOTH HEIGHT:
                        if (slider.vars.smoothHeight) { methods.smoothHeight(); }
                    }, (type === "init") ? 100 : 0);
                }
            } else { // FADE:
                slider.slides.css({ "width": "100%", "float": "left", "marginRight": "-100%", "position": "relative" });
                if (type === "init") {
                    if (!touch) {
                        //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);
                        if (slider.vars.fadeFirstSlide == false) {
                            slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({ "zIndex": 2 }).css({ "opacity": 1 });
                        } else {
                            slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({ "zIndex": 2 }).animate({ "opacity": 1 }, slider.vars.animationSpeed, slider.vars.easing);
                        }
                    } else {
                        slider.slides.css({ "opacity": 0, "display": "block", "webkitTransition": "opacity " + slider.vars.animationSpeed / 1000 + "s ease", "zIndex": 1 }).eq(slider.currentSlide).css({ "opacity": 1, "zIndex": 2 });
                    }
                }
                // SMOOTH HEIGHT:
                if (slider.vars.smoothHeight) { methods.smoothHeight(); }
            }
            // !CAROUSEL:
            // CANDIDATE: active slide
            if (!carousel) { slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide"); }

            //FlexSlider: init() Callback
            slider.vars.init(slider);
        };

        slider.doMath = function () {
            var slide = slider.slides.first(),
                slideMargin = slider.vars.itemMargin,
                minItems = slider.vars.minItems,
                maxItems = slider.vars.maxItems;

            slider.w = (slider.viewport === undefined) ? slider.width() : slider.viewport.width();
            slider.h = slide.height();
            slider.boxPadding = slide.outerWidth() - slide.width();

            // CAROUSEL:
            if (carousel) {
                slider.itemT = slider.vars.itemWidth + slideMargin;
                slider.itemM = slideMargin;
                slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
                slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;
                slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1))) / minItems :
                               (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1))) / maxItems :
                               (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;

                slider.visible = Math.floor(slider.w / (slider.itemW));
                slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible) ? slider.vars.move : slider.visible;
                slider.pagingCount = Math.ceil(((slider.count - slider.visible) / slider.move) + 1);
                slider.last = slider.pagingCount - 1;
                slider.limit = (slider.pagingCount === 1) ? 0 :
                               (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
            } else {
                slider.itemW = slider.w;
                slider.itemM = slideMargin;
                slider.pagingCount = slider.count;
                slider.last = slider.count - 1;
            }
            slider.computedW = slider.itemW - slider.boxPadding;
            slider.computedM = slider.itemM;
        };

        slider.update = function (pos, action) {
            slider.doMath();

            // update currentSlide and slider.animatingTo if necessary
            if (!carousel) {
                if (pos < slider.currentSlide) {
                    slider.currentSlide += 1;
                } else if (pos <= slider.currentSlide && pos !== 0) {
                    slider.currentSlide -= 1;
                }
                slider.animatingTo = slider.currentSlide;
            }

            // update controlNav
            if (slider.vars.controlNav && !slider.manualControls) {
                if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
                    methods.controlNav.update("add");
                } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
                    if (carousel && slider.currentSlide > slider.last) {
                        slider.currentSlide -= 1;
                        slider.animatingTo -= 1;
                    }
                    methods.controlNav.update("remove", slider.last);
                }
            }
            // update directionNav
            if (slider.vars.directionNav) { methods.directionNav.update(); }

        };

        slider.addSlide = function (obj, pos) {
            var $obj = $(obj);

            slider.count += 1;
            slider.last = slider.count - 1;

            // append new slide
            if (vertical && reverse) {
                (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
            } else {
                (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
            }

            // update currentSlide, animatingTo, controlNav, and directionNav
            slider.update(pos, "add");

            // update slider.slides
            slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
            // re-setup the slider to accomdate new slide
            slider.setup();

            //FlexSlider: added() Callback
            slider.vars.added(slider);
        };
        slider.removeSlide = function (obj) {
            var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;

            // update count
            slider.count -= 1;
            slider.last = slider.count - 1;

            // remove slide
            if (isNaN(obj)) {
                $(obj, slider.slides).remove();
            } else {
                (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
            }

            // update currentSlide, animatingTo, controlNav, and directionNav
            slider.doMath();
            slider.update(pos, "remove");

            // update slider.slides
            slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
            // re-setup the slider to accomdate new slide
            slider.setup();

            // FlexSlider: removed() Callback
            slider.vars.removed(slider);
        };

        slider.destroy = function () {
            var classNamespace = '.' + slider.vars.namespace; // Namespaced class selector
            if (slider.vars.controlNav) slider.controlNav.closest(classNamespace + 'control-nav').remove(); // Remove control elements if present
            if (slider.vars.directionNav) slider.directionNav.closest(classNamespace + 'direction-nav').remove(); // Remove direction-nav elements if present
            if (slider.vars.pausePlay) slider.pausePlay.closest(classNamespace + 'pauseplay').remove(); // Remove pauseplay elements if present
            slider.find('.clone').remove(); // Remove any flexslider clones
            slider.unbind(slider.vars.eventNamespace); // Remove events on slider
            if (slider.vars.animation != "fade") slider.container.unwrap(); // Remove the .flex-viewport div
            slider.container.removeAttr('style') // Remove generated CSS (could collide with 3rd parties)
            slider.container.unbind(slider.vars.eventNamespace); // Remove events on slider
            slider.slides.removeAttr('style'); // Remove generated CSS (could collide with 3rd parties)
            slider.slides.filter(classNamespace + 'active-slide').removeClass(slider.vars.namespace + 'active-slide'); // Remove slide active class
            slider.slides.unbind(slider.vars.eventNamespace); // Remove events on slides
            $(document).unbind(slider.vars.eventNamespace + "-" + slider.id); // Remove events from document for this instance only
            $(window).unbind(slider.vars.eventNamespace + "-" + slider.id); // Remove events from window for this instance only 
            slider.stop(); // Stop the interval
            slider.removeData('flexslider'); // Remove data
        }

        //FlexSlider: Initialize
        methods.init();
    };

    // Ensure the slider isn't focussed if the window loses focus.
    $(window).blur(function (e) {
        focused = false;
    }).focus(function (e) {
        focused = true;
    });

    //FlexSlider: Default Settings
    $.flexslider.defaults = {
        namespace: "flex-",             //{NEW} String: Prefix string attached to the class of every element generated by the plugin
        selector: ".slides > li",       //{NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
        animation: "fade",              //String: Select your animation type, "fade" or "slide"
        easing: "swing",                //{NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
        direction: "horizontal",        //String: Select the sliding direction, "horizontal" or "vertical"
        reverse: false,                 //{NEW} Boolean: Reverse the animation direction
        animationLoop: true,            //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
        smoothHeight: false,            //{NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode
        startAt: 0,                     //Integer: The slide that the slider should start on. Array notation (0 = first slide)
        slideshow: true,                //Boolean: Animate slider automatically
        slideshowSpeed: 7000,           //Integer: Set the speed of the slideshow cycling, in milliseconds
        animationSpeed: 600,            //Integer: Set the speed of animations, in milliseconds
        initDelay: 0,                   //{NEW} Integer: Set an initialization delay, in milliseconds
        randomize: false,               //Boolean: Randomize slide order
        fadeFirstSlide: true,           //Boolean: Fade in the first slide when animation type is "fade"
        thumbCaptions: false,           //Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav.

        // Usability features
        pauseOnAction: true,            //Boolean: Pause the slideshow when interacting with control elements, highly recommended.
        pauseOnHover: false,            //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
        pauseInvisible: true,   		//{NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.
        useCSS: true,                   //{NEW} Boolean: Slider will use CSS3 transitions if available
        touch: true,                    //{NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
        video: false,                   //{NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches

        // Primary Controls
        controlNav: true,               //Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage
        directionNav: true,             //Boolean: Create navigation for previous/next navigation? (true/false)
        prevText: "Previous",           //String: Set the text for the "previous" directionNav item
        nextText: "Next",               //String: Set the text for the "next" directionNav item

        // Secondary Navigation
        keyboard: true,                 //Boolean: Allow slider navigating via keyboard left/right keys
        multipleKeyboard: false,        //{NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
        mousewheel: false,              //{UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
        pausePlay: false,               //Boolean: Create pause/play dynamic element
        pauseText: "Pause",             //String: Set the text for the "pause" pausePlay item
        playText: "Play",               //String: Set the text for the "play" pausePlay item

        // Special properties
        controlsContainer: "",          //{UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $(".flexslider-container"). Property is ignored if given element is not found.
        manualControls: "",             //{UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(".flex-control-nav li") or "#tabs-nav li img", etc. The number of elements in your controlNav should match the number of slides/tabs.
        customDirectionNav: "",         //{NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes "prev" and "next" (plus namespace)
        sync: "",                       //{NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
        asNavFor: "",                   //{NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider

        // Carousel Options
        itemWidth: 0,                   //{NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
        itemMargin: 0,                  //{NEW} Integer: Margin between carousel items.
        minItems: 1,                    //{NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
        maxItems: 0,                    //{NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
        move: 0,                        //{NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
        allowOneSlide: true,           //{NEW} Boolean: Whether or not to allow a slider comprised of a single slide

        // Callback API
        start: function () { },            //Callback: function(slider) - Fires when the slider loads the first slide
        before: function () { },           //Callback: function(slider) - Fires asynchronously with each slider animation
        after: function () { },            //Callback: function(slider) - Fires after each slider animation completes
        end: function () { },              //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
        added: function () { },            //{NEW} Callback: function(slider) - Fires after a slide is added
        removed: function () { },           //{NEW} Callback: function(slider) - Fires after a slide is removed
        init: function () { }             //{NEW} Callback: function(slider) - Fires after the slider is initially setup
    };

    //FlexSlider: Plugin Function
    $.fn.flexslider = function (options) {
        if (options === undefined) { options = {}; }

        if (typeof options === "object") {
            return this.each(function () {
                var $this = $(this),
                    selector = (options.selector) ? options.selector : ".slides > li",
                    $slides = $this.find(selector);

                if (($slides.length === 1 && options.allowOneSlide === false) || $slides.length === 0) {
                    $slides.fadeIn(400);
                    if (options.start) { options.start($this); }
                } else if ($this.data('flexslider') === undefined) {
                    new $.flexslider(this, options);
                }
            });
        } else {
            // Helper strings to quickly perform functions on the slider
            var $slider = $(this).data('flexslider');
            switch (options) {
                case "play": $slider.play(); break;
                case "pause": $slider.pause(); break;
                case "stop": $slider.stop(); break;
                case "next": $slider.flexAnimate($slider.getTarget("next"), true); break;
                case "prev":
                case "previous": $slider.flexAnimate($slider.getTarget("prev"), true); break;
                case "destroy": $slider.destroy(); break;
                default: if (typeof options === "number") { $slider.flexAnimate(options, true); }
            }
        }
    };
})(jQuery);

'use strict';

(function (module) {

    module.service('VehicleDetailSearchService', [
        '$http', '$q', 'Config', 'ZipCodeService', function ($http, $q, Config, ZipCodeService) {

            var allVehicles = {
                SearchResults: [],
                Spotlights: [],
                SearchTotalCount: 0,
                HasAutoSmartXLive: false,
                dealerLogoUpdateDate: null

            };
            var topCount = 4;
            function newSearchObj() {

                var newGuid = function () {
                    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                        return v.toString(16);
                    });
                };
                return {
                    IsLoadMoreSearch: false,
                    ItemType: 5, // Car
                    ItemTypes: [5], // Default to Car
                    ClientWebsiteId: Config.ClientWebSiteID,
                    SearchString: null,
                    SearchSellersByMakeId: null,
                    Latitude: ZipCodeService.Location.Latitude || Config.CurrentLatitude,
                    Longitude: ZipCodeService.Location.Longitude || Config.CurrentLongitude,
                    DistanceRadius: 255,
                    DistanceUnit: 0,
                    TopCount: topCount,
                    SortBy: "DistanceNearToFar",
                    Condition: 1,
                    UserGuid: newGuid(),
                    PageNumber: 0,
                    IsUserSearchTerm: false,
                    DoNotLogSearch: false,
                    LanguageId: 2,
                    AutoExtendDealerDistance: false,
                    RequireImage: false,
                    RequireNonZeroPrice: false,
                    OnlyPreferredDealers: false,
                    OnlyAutoPremierDealers: false,
                    OriginalSearchString: null,
                    ActualSearchString: null,
                    TransactionGuid: newGuid(),
                    ProceedToUseSecondarySearch: false,
                    UseSecondarySearch: false,
                    TransactionStep: 1,
                    RawSearchString: null,
                    IsHidden: false,
                    NewChecked: true,
                    UsedChecked: true,
                    LoanRate: Config.Rate,
                    LoanTerm: Config.Term,
                    MakeModels: [],
                    MiscellaneousList: [],
                    ColorList: [],
                    UsageMax: 0,
                    IsNonTextBasedSearch: true,
                    BodyTypeList: [],
                    ExcludedItemIdList: [],
                    DealerClientCode: null,
                    IncludeSpotlightResults: true,
                    ShowSpecficInventoryCount: null,
                    SourcePlatform: 1,
                    SourceSection: 1,
                    ZipCode: "",
                    SearchRequestType: 1,
                    ExecutionTimeSearchQuery: null,
                    ExecutionTimeWholeSearch: null,
                    YearMin: 1980,
                    YearMax: new Date().getFullYear() + 1,
                    CUEnablePriceGuidance: Config.EnablePriceGuidance
                };
            }


            var getCurrentFilterOptions = function (condition,dealerCode,isPreferredPlus,make,model,itemid) {
                var searchObj = newSearchObj();
                searchObj.ZipCode = ZipCodeService.Location.CurrentZipCode;
                searchObj.Condition = condition;
                searchObj.DealerClientCode = dealerCode;
                searchObj.OnlyAutoPremierDealers = isPreferredPlus;
                searchObj.MakeModels = [{ Make: make, Model: model }];
                searchObj.ExcludedItemIdList = [itemid];

                return searchObj;

            }


            var retrieveVehicles = function (condition,dealerCode,isPreferredPlus,make,model,itemid) {
                var searchObj = getCurrentFilterOptions(condition, dealerCode, isPreferredPlus, make, model,itemid);
                var json = JSON.stringify(searchObj);

                var deferred = $q.defer();
                var link = Config.BaseDirectory + "/SearchService/PostSearch";


                var promise = $http({
                    method: 'POST',
                    url: link,

                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': '*/*',
                        'Accept-Language': 'en-US,en;q=0.8'

                    },
                    data: json,
                }).then(function (data) {
                    if (data.data) {
                        data = data.data;
                    }
                    allVehicles.SearchResults = data.SearchResults;
                    allVehicles.Spotlights = data.SpotLightResults;
                    allVehicles.SearchTotalCount = data.SearchTotalCount;
                    allVehicles.HasAutoSmartXLive = data.HasAutoSmartXLive;
                    allVehicles.Loading = false;
                    allVehicles.dealerLogoUpdateDate = (data.SearchResults.length === 0) ? null : data.SearchResults[0].DealerLogoUpdateDate;

                    deferred.resolve(data);
                }).catch(function (data) {
                    allVehicles.Loading = false;
                    deferred.reject(data);
                });
                return deferred.promise;
            };


            return {
                RetrieveVehicles: retrieveVehicles,
                allVehicles: allVehicles

            }
        }
    ]);
})(angular.module('AutoSMART.Web.Search'));
"use strict";

(function (module) {

    module.component('dealerinformationcomponent', {

        controller: ['$scope','VehicleDetailService','$rootScope','$uibModal', 'Config',
            function ($scope,VehicleDetailService, $rootScope, $uibModal, Config) {
                var ctrl = this;
                ctrl.$onInit = function () {
                    ctrl.vehicleInfo = VehicleDetailService.VehicleInfo;
                    ctrl.ContactNameDisplay = (ctrl.vehicleInfo.SellerInfo.DealerContactName) ? ctrl.vehicleInfo.SellerInfo.DealerContactName:"Sales Manager";
                    
                };
                ctrl.displayAsxCard = function () {
                    return ctrl.vehicleInfo.SellerInfo.IsPreferredPlus ? true : false;;
                }
                ctrl.svgcontent = {
                    "TextColor": "white",
                    "ShieldColor": "white"
                };
                ctrl.ClientLogo = Config.ClientColorlessLogoUrl;
                ctrl.data = {
                    Latitude: null,
                    Longitude: null,
                    DealerAddress: "",
                    DealerName: "",
                    OwnerLocation:""
                }
                ctrl.displayDealerRating = function() {
                    return ctrl.vehicleInfo.SellerInfo.Rating && ctrl.vehicleInfo.SellerInfo.Rating > 0.0;
                }
                ctrl.openLocation = function () {
                    ctrl.data.Latitude = ctrl.vehicleInfo.SellerInfo.Latitude;
                    ctrl.data.Longitude = ctrl.vehicleInfo.SellerInfo.Longitude;
                    ctrl.data.DealerAddress = ctrl.vehicleInfo.SellerInfo.Address1;
                    ctrl.data.DealerName = ctrl.vehicleInfo.SellerInfo.SellerName;
                    ctrl.data.OwnerLocation = ctrl.vehicleInfo.SellerInfo.Address2;
                    var modalInstance = $uibModal.open({
                        component: 'locationcomponent',
                        windowClass: 'location-modal-content',
                        scope: $scope
                    });

                    $rootScope.modalInstance = modalInstance;

                    modalInstance.result.then(function (data) {
                        if (data.data) {
                            data = data.data;
                        }
                        console.log(data);
                    });
                };

                ctrl.openRating = function (isValid) {
                    if (isValid) {
                        ctrl.data.ClientCode = ctrl.vehicleInfo.SellerInfo.ClientCode;
                        var ratingInstance = $uibModal.open({
                            component: 'dealerratercomponent',
                            scope: $scope,
                            windowClass: 'dealerrater-modal-content'
                        });

                        $scope.ratingInstance = ratingInstance;
                    }
                };
            }], 
        templateUrl: UrlContent('/App/VehicleDetail/Views/dealerInformation.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

  module.component('vdpdealercommentscomponent', {

      controller: [
        "VehicleDetailService", "Config", "QuickQuoteService",
        function(VehicleDetailService, Config, QuickQuoteService) {
          var ctrl = this;
          ctrl.$onInit = function() {
            ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
            ctrl.ShowComments = (ctrl.VehicleInfo.HasChromeData) ? false : true;
            ctrl.showAppointment = !Config.IsQuickQuoteEnabled || (Config.IsQuickQuoteEnabled && !QuickQuoteService.GetQQResultCookie());
            //Test String
            //ctrl.Comments = 'COMING SOON<br /> <br /> <h3>2014 Honda&#174; Gold Wing&#174; Valkyrie&#174;</h3><strong>Legendary Power, Groundbreaking Style</strong><p>Here&#8217;s the formula: Take Honda&#174;&#8217;s legendary 1832cc flat six and build it into the ultimate cruiser&#8212;powerful, awe-inspiring and like no other. Now add in great handling and iconic style, and you&#8217;ll see why it&#8217;s the cruiser that only Honda&#174; could build.</p><div class=""trims_standardfeatures trims_honda_features""><strong>Innovations</strong><ul><li>LED Lighting</li></ul><p>The LED headlight, taillight and turn signals give the Valkyrie&#174; a modern, super-clean look and provide fantastic illumination as well. Style and function&#8212;that&#8217;s what the Valkyrie&#174; is all about.</p><ul><li>Unique Cruiser Style</li></ul><p>The Valkyrie&#174; outperforms all other cruisers and it looks the part. The six-cylinder engine itself is a major styling point, and the frame tank and bodywork flow from front to back. Polished-metal highlights and a low, aggressive stance complete the standout styling.</p><ul><li>10-Spoke Cast-Aluminum Wheels</li></ul><p>Strong, lightweight (thanks to the hollow-spoke design) and super stylish, the Valkyrie&#174;&#8217;s wheels make a big statement and are an integral part of this bike&#8217;s great handling.</p><ul><li>1832cc Engine</li></ul><p>There&#8217;s no denying it&#8212;the Valkyrie&#174; is all about its engine. And with an engine this big, you&#8217;ve got smooth power everywhere. Stoplight-to-stoplight acceleration? Passing power? Loads of torque? The Valkyrie&#174; has it all and then some.</p><ul><li>750lb Weight</li></ul><p>At just 750lbs with a full tank of gas, the new Valkyrie&#174; is just right&#8212;not too light for an engine like this, and not too heavy either. What you get is plenty of smooth-handling comfort.</p><ul><li>Low Center Of Gravity</li></ul><p>How low can you go? The Valkyrie&#174;&#8217;s engine is mounted low into its aluminum t';
            ctrl.Comments = String(ctrl.VehicleInfo.DealerComments).replace(/<[^>]+>/gm, ''); //remove html tags
            ctrl.Comments = String(ctrl.Comments).replace(/&#?[a-z0-9]+;/gm, ' '); //remove html entities
          };

          ctrl.DisplayComments = function() {
            if (ctrl.ShowComments == true) {
              ctrl.ShowComments = false;
            } else {
              ctrl.ShowComments = true;
            }
          };
        }
      ],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-dealercomments.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

'use strict';

(function(module) {
    module.component('vdppriceanalysiscomponent',
        {
            controller: [
                "VehicleDetailService", "Config", "$sce", "PriceComparisonService", function (VehicleDetailService, Config, $sce, PriceComparisonService) {
                    var ctrl = this;
                    ctrl.$onInit = function() {
                        ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                        ctrl.visibleSubTab = (ctrl.VehicleInfo.MarketPriceInfo) ? 'summary' : 'compare';
                        ctrl.LegalDisclaimer = ctrl.HtmlTagConvert(Config.LegalPriceAnalysisTab);
                        ctrl.DisplayMobileTabs = false;
                        var vehicleInfo = VehicleDetailService.VehicleInfo;
                        var dealerCode = vehicleInfo.SellerInfo.ClientCode;
                        var vin = vehicleInfo.VIN;
                        var price = vehicleInfo.PriceRetail;
                        var miles = vehicleInfo.Usage;
                        var itemId = vehicleInfo.ItemID;
                        PriceComparisonService.GetPriceComparison(dealerCode, vin, itemId, price, miles).then(function (data) {
                            if (data.data) {
                                data = data.data;
                            }
                            ctrl.ComparisonData = data;
                            ctrl.DisplayMobileTabs = true;
                        });

                    };

                    ctrl.HtmlTagConvert = function (convert) {
                        var openTag = "&lt;p&gt;";
                        var closeTag = "&lt;/p&gt;";
                        var reOpenTag = new RegExp(openTag, 'g');
                        var reCloseTag = new RegExp(closeTag, 'g');
                        var convertTags = convert.replace(reOpenTag, "<p>").replace(reCloseTag, "</p>");
                        return $sce.trustAsHtml(convertTags);
                    }
                }
            ],
            templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-priceanalysis.html')
        });
})(angular.module('AutoSMART.Web.VehicleDetail'));
'use strict';

(function (module) {
    module.component('vdppriceanalysiscomparecomponent',
        {
            controller: [
                '$scope', 'VehicleDetailService', 'PriceComparisonService', 'Config', function ($scope, VehicleDetailService, PriceComparisonService) {
                    var ctrl = this;
                    ctrl.$onInit = function () {
                        ctrl.ComparisonData = PriceComparisonService.GetPriceComparisonChart(ctrl.data);
                        ctrl.vehicle = ($scope.$parent.$ctrl.VehicleInfo) ? $scope.$parent.$ctrl.VehicleInfo : $scope.$parent.$ctrl.vehicle;
                        ctrl.VehicleNumber = (ctrl.vehicle.MarketPriceInfo) ? ctrl.vehicle.MarketPriceInfo.CompareCount : ctrl.vehicle.PriceCompareVehicleCount;
                    }
                }
            ],
            bindings: {
                data: '<'
            },
            templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-priceanalysis-compare.html')
        });
})(angular.module('AutoSMART.Web.VehicleDetail'));
"use strict";

(function (module) {

    module.component('vdpoverviewcomponent', {
        controller: [
            "VehicleDetailService",
            function(VehicleDetailService) {
                var ctrl = this;
                ctrl.$onInit = function() {
                    ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                }
            }
        ],

        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-overview.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vdpmakeappointmentcomponent', {
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-makeAppointment.html'),
        bindings: {
            itemid: '<',
            vehicle: '<',
            displayasx: '<'
        },
        controller: ["$uibModal", "$scope", "Config", "GoogleAnalyticsService",
            function ($uibModal, $scope, Config, GoogleAnalyticsService) {
                var $ctrl = this;
                var qqResultCookieName = "qqresult";
                $scope.makeAppointmentClicked = function () {
                    $ctrl.AppointmentBtn = GoogleAnalyticsService.AppointmentBtn;
                    $ctrl.AppointmentBtn();
                    var qqEnabled = Config.IsQuickQuoteEnabled;
                    var qqResult = getQQResultCookie();
                    var useQqLeadForm = false;
                    if (qqEnabled && qqResult !== null) {
                        useQqLeadForm = true;
                    }
                    var modalInstance;

                    if (useQqLeadForm) {
                        modalInstance = $uibModal.open({
                            component: "prequalifyvehicleleadcomponent",
                            scope: $scope,
                            windowClass: 'vdplead-modal-content prequalify-vdplead-modal-content'
                        });
                    } else {
                        modalInstance = $uibModal.open({
                            component: "Vehicleleadcomponent",
                            scope: $scope,
                            windowClass: 'vdplead-modal-content',
                            resolve: {
                                componentname: function () {
                                    return 'scheduleappointment';
                                }
                            }
                        });
                    }

                    $scope.modalRebateInstance = modalInstance;
                };

                $scope.cancel = function () {
                    $scope.modalInstance.close();
                };

                function getQQResultCookie() {
                    return JSON.parse($.cookie(qqResultCookieName)
                        ? $.cookie(qqResultCookieName)
                        : localStorage.getItem(qqResultCookieName));
                }

            }]
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vdprebatescomponent', {

        controller: ["$rootScope", "$scope", "$location", "CalculatorService", "$cookies", "$uibModal", "ChromeDataService", "VehicleDetailService", "ZipCodeService", "NotificationService",
            function ($rootScope, $scope, $location, CalculatorService, $cookies, $uibModal, ChromeDataService, VehicleDetailService, ZipCodeService, NotificationService) {
                var ctrl = this;

                var rebate = function () {
                    ZipCodeService.Init().then(function () {

                        ctrl.ShowRebateInfo = false;
                        ctrl.NoRebateText = "Rebate information is not available for this vehicle for Zip Code " + ZipCodeService.Location.CurrentZipCode;
                        ctrl.vehicle = VehicleDetailService.VehicleInfo;
                        callChromedata();
                    });
                };

                ctrl.$onInit = function () {
                    rebate();
                }

                function callChromedata() {
                    if (ctrl.vehicle.ChromeStyleID && ctrl.vehicle.PhysicalCondition == 'New') {
                        ChromeDataService.GetChromeIncentive(ctrl.vehicle.ChromeStyleID, ZipCodeService.Location.CurrentZipCode).then(function (result) {
                            if (result && result.Incentives.length > 0) {
                                setUpChromeRebateList(result);
                                ctrl.ShowRebateInfo = true;
                            }
                        });
                    }

                }


                $rootScope.$on('ZipCodeService:zipCodeChanged', function currentCityChanged(event, value) {
                    callChromedata();
                });

                var setUpChromeRebateList = function (data) {
                    ctrl.CashRebateContent = [];
                    angular.forEach(data.Incentives, function (value) {
                        var cashRebateBox = {};
                        var vv = value.programValues.valueVariationList[0];
                        if (vv.programValueList[0].cash) {
                            cashRebateBox.Requirements = vv.Requirements;
                            cashRebateBox.Cash = vv.programValueList[0].cash;
                            cashRebateBox.GroupAffiliation = value.GroupAffiliation;
                            cashRebateBox.CategoryDescription = value.CategoryDescription;
                            cashRebateBox.ExpiryDate = value.ExpiryDate;
                            cashRebateBox.EffectiveDate = value.EffectiveDate;
                            cashRebateBox.StackabilityList = data.StackabilityList.join(', ');
                            cashRebateBox.PreviousOwnership = value.PreviousOwnership;
                            cashRebateBox.VehicleStatus = ctrl.vehicle.PhysicalCondition;
                            angular.forEach(value.programRuleList, function (pr) {
                                if (pr.Type === 'Eligibility') {
                                    cashRebateBox.Eligibility = pr.Description;
                                }

                                if (pr.Type === 'Qualification') {
                                    cashRebateBox.Qualification = pr.Description;
                                }
                            });

                            var iList = [];
                            angular.forEach(value.InstitutionList, function (i) {
                                iList.push(i.Description);
                            });
                            cashRebateBox.Institution = iList.join(', ');

                            ctrl.CashRebateContent.push(cashRebateBox);
                        }
                    });
                };

                NotificationService.subscribe("saveZipCode", $scope, rebate);
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-rebates.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vdprebatescardcomponent', {
        bindings: {
            rebate: '<'
        },
        controller: ["$scope", "$location", "Config", "CalculatorService", "$cookies", "$uibModal",
            function ($scope, $location, Config, CalculatorService, $cookies, $uibModal) {
                var ctrl = this;

                ctrl.openRebateModal = function () {
                    var modalInstance = $uibModal.open({
                        component: 'rebatedetailcomponent',
                        scope: $scope
                    });

                    $scope.modalRebateInstance = modalInstance;
                };
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-rebates-card.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));


(function (module) {

    module.component('rebatedetailcomponent', {
        templateUrl: "/App/VehicleDetail/Views/vdp-rebates-carddetail.html",
        bindings: {
            data: "="
        },
        controller: ["$scope",
            function ($scope) {
                var ctrl = this;
                ctrl.rebate = $scope.$parent.$ctrl.rebate;
                $scope.cancel = function () {
                    $scope.$parent.$parent.modalRebateInstance.close();
                };
            }]
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vdpsafetycomponent', {
        controller: ["VehicleDetailService",
            function (VehicleDetailService) {
                var ctrl = this;
                ctrl.$onInit = function () {
                    ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                }
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-safety.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vdptechspecscomponent', {

        controller: ["VehicleDetailService",
            function (VehicleDetailService) {
                var $ctrl = this;
                $ctrl.$onInit = function () {
                    $ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                }
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-techspecs.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vdpwarrantycomponent', {

        controller: ["VehicleDetailService", "$sce",
            function (VehicleDetailService, $sce) {
                var $ctrl = this;
                $ctrl.$onInit = function () {
                    $ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                }
                $ctrl.renderHtml = function (html) {
                    return $sce.trustAsHtml(html);
                }

            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vdp-warranty.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vehicledatacomponent', {

        controller: [ "VehicleDetailService",
            function ( VehicleDetailService) {
                var ctrl = this;
                ctrl.$onInit = function() {
                    ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                };

                var hasData = function(string) {
                    if (!string) {
                        return false;
                    }

                    return true;
                };

                ctrl.hasMileageData = function(city, hwy) {
                    return (hasData(city) && hasData(hwy));
                };

                ctrl.hasDisplayData = function(data) {
                    return !!data; // data can be null, '', undefined, etc. !data returns true, !!data returns false
                };
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vehicleData.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vehicledetailcomponent', {

        controllerAs: "$ctrl",
        controller: ["$scope", "$location", "VehicleDetailService", "Config", "ChromeDataService", "$timeout", "CalculatorService", 'VehiclePricingService', "$anchorScroll", "$stateParams", "insights", "VehicleFavoriteService", "GoogleAnalyticsService", "QuickQuoteService", "AmplitudeService",
            function ($scope, $location, VehicleDetailService, Config, ChromeDataService, $timeout, CalculatorService, VehiclePricingService, $anchorScroll, $stateParams, insights, VehicleFavoriteService, GoogleAnalyticsService, QuickQuoteService, AmplitudeService) {
                var ctrl = this;

                $scope.clickedFavorite = function ($event) {
                    if (ctrl.IsFavorite()) {
                        ctrl.RemoveVehicleClick = GoogleAnalyticsService.RemoveVehicleClick;
                        ctrl.RemoveVehicleClick();
                    }
                    else {
                        ctrl.SaveVehicleClick = GoogleAnalyticsService.SaveVehicleClick;
                        ctrl.SaveVehicleClick();
                    }
                    $event.stopImmediatePropagation();
                    $event.preventDefault();

                    var favorite = {
                        ItemID: ctrl.VehicleInfo.ItemID,
                        ImagePath: ctrl.VehicleInfo.Images ? ctrl.VehicleInfo.Images[0].ImagePath : ctrl.VehicleInfo.ImagePath,
                        ItemName: ctrl.VehicleInfo.ItemName,
                        PriceRetail: ctrl.VehicleInfo.PriceRetail,
                        PhysicalCondition: ctrl.VehicleInfo.PhysicalCondition,
                        UsageType: ctrl.VehicleInfo.UsageType,
                        Usage: ctrl.VehicleInfo.Usage,
                        Distance: ctrl.VehicleInfo.Distance,
                        Latitude: ctrl.VehicleInfo.Latitude,
                        Longitude: ctrl.VehicleInfo.Longitude,
                        IsStockPhoto: ctrl.VehicleInfo.IsStockPhoto
                    };
                    VehicleFavoriteService.SaveFavoriteVehicle(favorite);

                };

                $scope.makeAppointmentClicked = function () {
                  var qqEnabled = Config.IsQuickQuoteEnabled;
                  var qqResult = getQQResultCookie();
                  var useQqLeadForm = false;
                  if (qqEnabled && qqResult !== null) {
                    useQqLeadForm = true;
                  }
                  var modalInstance;

                  if (useQqLeadForm) {
                    modalInstance = $uibModal.open({
                      component: "prequalifyvehicleleadcomponent",
                      scope: $scope,
                      windowClass: 'vdplead-modal-content prequalify-vdplead-modal-content'
                    });
                  } else {
                    modalInstance = $uibModal.open({
                      component: "Vehicleleadcomponent",
                      scope: $scope,
                      windowClass: 'vdplead-modal-content'
                    });
                  }

                  $scope.modalRebateInstance = modalInstance;
                };

                ctrl.IsFavorite = function () {
                    return VehicleFavoriteService.GetVehicleByItemid(ctrl.VehicleInfo.ItemID);
                }

                function getSessionSetting() {
                    var result = sessionStorage.getItem("srpSource");
                    if (typeof result != 'undefined' && result != null) {
                        return result;
                    }
                };

                ctrl.$onInit = function () {
                    var correlationId = insights.randomString(5);
                    insights.logEvent('Vehicle Detail Page load start', { 'tenentId': Config.ClientCode, "correlationId": correlationId });
                    document.title = "AutoSMART - Details";                    
                    var itemid = $scope.$parent.itemid;
                    var isSpotlight = $scope.$parent.isSpotlight;
                    var sourcefromImageClick = $scope.$parent.sourcefrom;
                    var sourcefromDivClick = getSessionSetting();
                    var sources = null;
                    if (sourcefromImageClick) {
                        sources = sourcefromImageClick;
                    }
                    else {
                        sources = $scope.$parent.isSpotlight ? 'Spotlight' : (sourcefromDivClick ? sourcefromDivClick : 'Other');

                    }

                    if (sourcefromDivClick) {
                        sessionStorage.removeItem("srpSource");
                    }
                    
                    var qqstatus = Config.IsQuickQuoteEnabled && QuickQuoteService.GetQQProcessResultCookie();
                    ctrl.qqstatus = qqstatus ? 'True' : 'False';
                    var qqresult = Config.IsQuickQuoteEnabled && QuickQuoteService.GetQQResultCookie();
                    ctrl.qqresult = qqresult ? 'True' : 'False';

                    VehicleDetailService.RetrieveVehicle(itemid, true, isSpotlight).then(function () {
                        ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;

                        if (!ctrl.VehicleInfo.Images || ctrl.VehicleInfo.Images.length === 0) {
                            var image = {
                                ImagePath: '',
                                OriginalImagePath: ''
                            };
                            ctrl.VehicleInfo.Images.push(image);
                        }

                        if (!ctrl.VehicleInfo.MarketPrice || ctrl.VehicleInfo.MarketPrice === 0) {
                            ctrl.VehicleInfo.MarketPrice = 'N/A';
                        }

                        if (ctrl.VehicleInfo.UsageType != null && ctrl.VehicleInfo.UsageType.toLowerCase() === 'mi') {
                            ctrl.VehicleInfo.UsageType = 'miles';
                        }

                        VehicleDetailService.RetrieveVehicleChromeData();

                        AmplitudeService.logEvent('Vehicle Detail Page Viewed',
                            {
                                'Quick Quote Completed?': ctrl.qqstatus,
                                'Quick Quote Rates and Terms returned to the user?': ctrl.qqresult,
                                'Vehicle Type': ctrl.VehicleInfo.PhysicalCondition,
                                'Make': ctrl.VehicleInfo.Make,
                                'Model': ctrl.VehicleInfo.Model,
                                'Attribution source to VDP': sources
                            });

                        insights.logEvent('Vehicle Detail Page load finish', { 'tenentId': Config.ClientCode, "correlationId": correlationId });
                    });
                    CalculatorService.Init().then(function () {
                        ctrl.calcContent = CalculatorService.CalcContent;
                    });

                    $(window).scroll(function () {
                        var overview = $("#vehiclepricingcomponent");
                        if ($(overview).offset()) {
                            var posY = $(overview).offset().top - $(window).scrollTop() + $(overview).height();
                            if (posY <= 0 && window.innerWidth >= 767) {
                                $('#vehicle-detail-sticky').fadeIn();
                            } else {
                                $('#vehicle-detail-sticky').fadeOut();
                            }
                        }
                    });

                    $(window).resize(function () {
                        var windowWidth = window.innerWidth;
                        var currentYPos = $(window).scrollTop() + $(overview).height();
                        var offset = $(overview).offset().top;
                        if (windowWidth < 767) {
                            $('#vehicle-detail-sticky-mobile').fadeIn();
                            if (currentYPos < offset) {
                                $('#vehicle-detail-sticky').fadeOut();
                            }
                        } else {
                            $('#vehicle-detail-sticky-mobile').fadeOut();
                            if (currentYPos >= offset) {
                                $('#vehicle-detail-sticky').fadeIn();
                            }
                        }
                    });
                }
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vehicleDetail.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vehicleinformationdropdownscomponent', {
        controllerAs: "$ctrl",
        controller: ['$window', 'VehicleDetailService',
            function ($window, VehicleDetailService) {
                var ctrl = this;
                ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                ctrl.PhysicalConditionNew = ctrl.VehicleInfo.PhysicalCondition === 'New' ? true : false;
                ctrl.clientCode = ctrl.data;
                ctrl.visiblePane = 'OVERVIEW';
                ctrl.IsPreferredPlus = ctrl.VehicleInfo.SellerInfo.IsPreferredPlus;
                
                if ((!ctrl.VehicleInfo.HasChromeData && ctrl.VehicleInfo.HasPricingData) ||  fromPriceAnalysisModal()) {
                    ctrl.visiblePane = 'PRICE COMPARISON';
                }

                function fromPriceAnalysisModal() {
                    return $window.location.search.toLowerCase().indexOf('padetails') > -1;
                }
            }],
            bindings: {
                data: '<'
            },
        templateUrl: UrlContent('/App/VehicleDetail/Views/vehicleInformationDropdowns.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vehicleinformationtabscomponent', {

        controller: ["$window", "VehicleDetailService", "$timeout", "$anchorScroll", 'Config', 'QuickQuoteService',
            function ($window, VehicleDetailService, $timeout, $anchorScroll, Config, QuickQuoteService) {
                var ctrl = this;
                ctrl.PhysicalConditionNew = VehicleDetailService.VehicleInfo.PhysicalCondition === 'New' ? true : false;
                ctrl.$onInit = function () {
                    ctrl.showAppointment = !Config.IsQuickQuoteEnabled || (Config.IsQuickQuoteEnabled && !QuickQuoteService.GetQQResultCookie());
                    ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                }

                var fromPriceAnalysisModal = function() {
                    return $window.location.search.toLowerCase().indexOf('padetails') > -1;

                    //var qStringArr = $window.location.search.split('&');
                    //if (qStringArr.indexOf('PADetails') > -1) {
                    //    return true;
                    //}
                    //return false;
                }

                ctrl.ShowPriceAnalysisTab = function () {
                    var check = (ctrl.VehicleInfo.ItemTypeID === 5 && ctrl.HasPriceAnalysis) || fromPriceAnalysisModal();
                    return check;
                }

                //Add scrollTo functionality on the VDP
                var hash = $window.location.hash;
                if (hash) {
                    $timeout(function () {
                        hash = hash.split('#');
                        $anchorScroll(hash[1]);
                    });
                }
            }],

        templateUrl: UrlContent('/App/VehicleDetail/Views/vehicleInformationTabs.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

"use strict";

(function (module) {

    module.component('vehiclephotoscomponent', {
        bindings: {
            images: '<'
        },
        controller: ['$scope', 'InventoryImageSizeService',
            function ($scope, InventoryImageSizeService) {
                var $ctrl = this;
                $ctrl.VDPImageSize = InventoryImageSizeService.images.VDPLarge;

                $ctrl.currentIndex = 0;
                $scope.$watch('$ctrl.currentIndex', function () {
                    $ctrl.images.forEach(function (image) {
                        image.visible = false; // make every image invisible
                    });

                    $ctrl.images[$ctrl.currentIndex].visible = true; // make the current image visible
                });
                
                $ctrl.next = function () {
                    $ctrl.currentIndex < $ctrl.images.length - 1 ? $ctrl.currentIndex++ : $ctrl.currentIndex = 0;
                };

                $ctrl.prev = function () {
                    $ctrl.currentIndex > 0 ? $ctrl.currentIndex-- : $ctrl.currentIndex = $ctrl.images.length - 1;
                };

                $ctrl.stockPhotoMessage = 'This image is a stock photo and is not an exact representation of any vehicle offered for sale. Advertised vehicles of this model may have styling, trim levels, colors and optional equipment that differ from the stock photo.';
            }],

        templateUrl: UrlContent('/App/VehicleDetail/Views/vehiclePhotos.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));
"use strict";

(function (module) {

    module.component('vehiclepricingcomponent', {

        controller: ["$scope", "$rootScope", "$uibModal", "VehicleDetailService", "CalculatorService", "HidePriceDifferenceService", "QuickQuoteService",
            function ($scope, $rootScope, $uibModal, VehicleDetailService, CalculatorService, HidePriceDifferenceService, QuickQuoteService) {
                var ctrl = this;
                ctrl.openPriceAnalysisModal = function () {
                    var modalInstance = $uibModal.open({
                        component: 'priceanalysismodalcomponent',
                        windowClass: 'vdplead-modal-content',
                        scope: $scope
                    });

                    $rootScope.modalInstance = modalInstance;
                    modalInstance.result.then(function (data) {
                        if (data.data) {
                            data = data.data;
                        }
                        console.log(data);
                    });
                }

                ctrl.$onInit = function() {
                    ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                    ctrl.CalcContent = CalculatorService.CalcContent;
                    ctrl.PreQualFormData = QuickQuoteService.GetPreQualFormData() || ctrl.CalcContent.DownPayment;
                    ctrl.isNoQQ = !CalculatorService.qqSelectedRateTermCookie;
                };

                ctrl.hidePriceDifference = function (location) {
                    var result = HidePriceDifferenceService.IsDealerFromTexas(location);
                    return result;
                }


            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vehiclePricing.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));

'use strict';
(function(module) {
    module.component('similarvehicles', {
        controller: ["$scope", "$window", "VehicleDetailSearchService", "$rootScope", "NotificationService", "InventoryImageSizeService", "GoogleAnalyticsService",
            function ($scope, $window, VehicleDetailSearchService, $rootScope, NotificationService, InventoryImageSizeService, GoogleAnalyticsService) {
                var ctrl = this;
                ctrl.stockPhotoMessage = 'This image is a stock photo and is not an exact representation of any vehicle offered for sale. Advertised vehicles of this model may have styling, trim levels, colors and optional equipment that differ from the stock photo.';
                ctrl.VDPImageSize = InventoryImageSizeService.images.Compare;
                ctrl.$onInit = function() {
                    retrieveVehicles();
                };

                $scope.similarvehiclesClick = function () {
                    ctrl.RecommendedVehicleClick = GoogleAnalyticsService.RecommendedVehicleClick;
                    ctrl.RecommendedVehicleClick();
                }

                var retrieveVehicles = function() {
                VehicleDetailSearchService.RetrieveVehicles(ctrl.physicalcondition, (ctrl.ispreferredplus == true) ? ctrl.dealercode : "", ctrl.ispreferredplus, ctrl.make, ctrl.model,ctrl.itemid).then(function() {
                        ctrl.SearchResults = VehicleDetailSearchService.allVehicles.SearchResults;
                    });
                };

                NotificationService.subscribe("saveZipCode", $scope, retrieveVehicles);

            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/similarVehicles.html'),
         bindings: {
             physicalcondition: '=',
            dealercode: '=',
            ispreferredplus: '=',
            make: '=',
            model: '=',
            itemid:'='
        }
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));
'use strict';
(function (module) {
    module.component('vehiclemakemodelcomponent', {
        controller: ['VehicleDetailService',
            function (VehicleDetailService) {
                var ctrl = this;

                ctrl.$onInit = function () {
                    ctrl.VehicleInfo = VehicleDetailService.VehicleInfo;
                };
            }],
        templateUrl: UrlContent('/App/VehicleDetail/Views/vehicleMakeModel.html')
    });
})(angular.module('AutoSMART.Web.VehicleDetail'));
'use strict';

(function (module) {

    module.service('VehicleDetailService', [
        '$http', '$q', 'Config', 'ZipCodeService', 'DistanceCalculationService', 'VehiclePricingService', function ($http, $q, Config, ZipCodeService, DistanceCalculationService, VehiclePricingService) {

            var vehicleInfo = {
                ItemID: 0,
                ImagePath: "",
                ItemName: "",
                UsageType: "",
                Usage: 0,
                Distance: 0,
                PhysicalCondition: "",
                MakeID: 0,
                Make: "",
                ModelID: 0,
                Model: "",
                Year: "",
                VIN: "",
                PriceRetail: 0,
                InteriorColor: "",
                ExteriorColor: "",
                DealerComments: "",
                VehicleOptions: "",
                Trim: "",
                Images: [],
                ItemId: 0,
                OverView: "",
                WordCloud: "",
                MPGCity: "",
                MPGHWY: "",
                Doors: 0,
                Passengers: "",
                EngineType: "",
                EngineDisplacement: "",
                Drivetrain: "",
                TransmissionType: "",                
                StandardEquipment: [],
                TechSpecsChassis: [],
                TechSpecsDimension: [],
                TechSpecsPowerTrain: [],
                Warranty: "",
                Safety: [],
                ChromeStyleID: 0,
                SellerInfo: {},
                SellerClientContact: [],
                HasChromeData: true,
                DistanceToDealer: 0,
                Success: true,
                ActiveVehicle: true,
                StockNumber: "",
                ContactName: "",
                IsStockPhoto: false,
                IsPlusDealer: null,
                ListPrice: null,
                AdditionalOptions: '',
                VehicleHistoryURL: "",
                VehicleHistorySingleOwner: false,
                TransmissionRaw: ""
            };

            var hasPricingData = function(inStockDate) {
                var value = true;
                if (vehicleInfo.MarketPriceInfo == null) {
                    value = false;
                }
                return value;
            };

            var verifyChromeStyleID = function () {
                vehicleInfo.HasChromeData = false;

                if (vehicleInfo.ChromeStyleID != null && vehicleInfo.ChromeStyleID > 0) {
                    vehicleInfo.HasChromeData = true;
                }

                if (vehicleInfo.AdditionalChromeStyles != null) {
                    vehicleInfo.HasChromeData = true;                    
                }
            }

            var transmissionVersion = function (transmissionRaw, chromeTransmissionType, transmission, chromeTransmissionTypeCont ) {
                if (transmissionRaw || transmissionRaw != "") {
                    return transmissionRaw;
                }

                if (chromeTransmissionType) {
                    return chromeTransmissionType + '-speed ' + chromeTransmissionTypeCont;
                }

                return transmission;
            }

            var retrieveVehicle = function (itemId, isVDP, isSpotlight) {
                if (isVDP === undefined || !isVDP) {
                    isVDP = false;
                }

                if (isSpotlight === undefined || !isSpotlight) {
                    isSpotlight = false;
                }
                
                var deferred = $q.defer();
                var link = Config.VehicleApiUrl + "dealerdata/get?id=" + itemId + "&userId=" + Config.UserId + "&clientWebsiteId=" + Config.ClientWebSiteID + "&isVdp=" + isVDP + "&isSpotlight=" + isSpotlight;

                var promise = $http({
                    method: 'GET',
                    url: link,

                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': '*/*',
                        'Accept-Language': 'en-US,en;q=0.8'

                    }
                   
                }).then(function (data) {
                    if (data.data) {
                        data = data.data;
                    }
                    vehicleInfo.PhysicalCondition = data.PhysicalCondition;
                    vehicleInfo.MakeID = data.MakeID;
                    vehicleInfo.Make = data.Make;
                    vehicleInfo.ModelID = data.ModelID;
                    vehicleInfo.Model = data.Model;
                    vehicleInfo.Year = data.Year;
                    vehicleInfo.VIN = data.VIN;
                    vehicleInfo.PriceRetail = (data.PriceRetail == null) ? 0 : data.PriceRetail;
                    vehicleInfo.ItemID = data.ItemId;
                    vehicleInfo.InteriorColor = data.InteriorColor;
                    vehicleInfo.ExteriorColor = data.ExteriorColor;
                    vehicleInfo.DealerComments = data.DealerComments;
                    vehicleInfo.VehicleOptions = data.VehicleOptions;
                    vehicleInfo.Trim = data.Trim;
                    vehicleInfo.ChromeStyleID = data.ChromeStyleId;
                    vehicleInfo.Images = [];
                    if (data.Images != null) {
                        data.Images.forEach(function (element) {
                            vehicleInfo.Images.push(element);
                            if (element.IsStockPhoto === true) {
                                vehicleInfo.IsStockPhoto = true;
                            }
                        });
                    }
                    vehicleInfo.ImagePath = data.ImagePath;
                    vehicleInfo.ItemName = data.Year + ' ' + data.Make + ' ' + data.Model;
                    vehicleInfo.ItemTypeID = data.ItemTypeID;
                    vehicleInfo.UsageType = data.UsageType;
                    vehicleInfo.Usage = data.Usage;
                    vehicleInfo.Distance = 0;
                    vehicleInfo.StockNumber = data.StockNumber;
                    vehicleInfo.ContactName = data.ContactName;
                    vehicleInfo.Doors = data.Doors;
                    vehicleInfo.EngineType = data.Engine;
                    vehicleInfo.Drivetrain = data.DriveTrain;                    
                    if (data.TransmissionRaw != undefined || data.TransmissionRaw != null || data.TransmissionRaw === "") {
                        vehicleInfo.TransmissionRaw = data.TransmissionRaw;
                    }                    
                    vehicleInfo.TransmissionType = data.Transmission;
                    vehicleInfo.ListPrice = data.ListPrice;

                    if (data.SellerInfo != null) {
                        vehicleInfo.SellerInfo = data.SellerInfo;
                        vehicleInfo.DealerId = vehicleInfo.SellerInfo.DealerId;

                        var locationInfo = ZipCodeService.Location;
                        vehicleInfo.DistanceToDealer = DistanceCalculationService.CalculateDistance(locationInfo.Latitude, locationInfo.Longitude, vehicleInfo.SellerInfo.Latitude, vehicleInfo.SellerInfo.Longitude);
                    }
                    if (data.ItemId == null) {
                       vehicleInfo.Success = false;
                       deferred.resolve(data);
                       return;
                    }
                    vehicleInfo.ActiveVehicle = (data.StatusID === 1) ? true : false;
                    
                    if (data.MarketPriceInfo != null && (Config.EnablePriceGuidance === 'true' || data.MarketPriceInfo.DealTypeId !== 3)) {
                        vehicleInfo.PricingData =
                            VehiclePricingService.GetPricingData(data.PriceRetail, data.MarketPriceInfo.MarketValue, data.MarketPriceInfo.DealTypeId);
                    }

                    if (Config.EnablePriceGuidance === 'true' || (data.MarketPriceInfo != null && data.MarketPriceInfo.DealTypeId !== 3)) {
                        vehicleInfo.MarketPriceInfo = data.MarketPriceInfo;
                    }

                    vehicleInfo.RecentPricingData =
                        VehiclePricingService.GetRecentPriceData(data.PriceRetail,
                            data.RecentPrice,
                            data.RecentPriceDate);
                    
                    if (data.InStockDate !== null) {
                        vehicleInfo.DaysAtDealer = VehiclePricingService.GetDaysAtDealer(data.InStockDate);
                    }
                    vehicleInfo.AdditionalChromeStyles = data.AdditionalChromeStyles;
                    if (data.AdditionalOptions != null) {
                        vehicleInfo.AdditionalOptions = data.AdditionalOptions.join(' ');
                    }
                    vehicleInfo.HasPricingData = hasPricingData(data.InStockDate);
                    vehicleInfo.VehicleHistoryURL = data.VehicleHistoryURL;
                    vehicleInfo.VehicleHistorySingleOwner = data.VehicleHistorySingleOwner;   
                    vehicleInfo.IsPlusDealer = data.SellerInfo.IsPreferredPlus;

                    deferred.resolve(data);
                }).catch(function (data) {
                    vehicleInfo.Success = false;
                    deferred.reject(data);
                });
                return deferred.promise;
            };

            var retrieveVehicleChromeData = function () {
                verifyChromeStyleID();
                var deferred = $q.defer();

                var chromeStyleId;
                if (vehicleInfo.AdditionalChromeStyles != null) {
                    chromeStyleId = vehicleInfo.AdditionalChromeStyles[0];
                } else {
                    chromeStyleId = vehicleInfo.ChromeStyleID;
                }

                if (chromeStyleId == null || chromeStyleId == 0) {
                    return;
                }

                var link = Config.VehicleApiUrl + "chromedata/" + chromeStyleId;
               
                var promise = $http({
                    method: 'GET',
                    url: link,

                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': '*/*',
                        'Accept-Language': 'en-US,en;q=0.8'
                    }

                }).then(function (data) {
                    if (data.data) {
                        data = data.data;
                    }
                    if (!data) {
                        vehicleInfo.HasChromeData = false;
                    }
                    else {
                        vehicleInfo.OverView = data.Overview;
                        vehicleInfo.WordCloud = (data.WordCloud == null) ? "" : data.WordCloud.replace(/;/g, '.');
                        vehicleInfo.MPGCity = data.MPGCity;
                        vehicleInfo.MPGHWY = data.MPGHwy;
                        vehicleInfo.Doors = (data.Doors) ? data.Doors : vehicleInfo.Doors;
                        vehicleInfo.Passengers = data.Passengers;
                        vehicleInfo.EngineType = (data.EngineType) ? data.EngineType : vehicleInfo.EngineType;
                        vehicleInfo.EngineDisplacement = data.EngineDisplacement;
                        vehicleInfo.Drivetrain = (data.Drivetrain) ? data.Drivetrain : vehicleInfo.Drivetrain;
                        vehicleInfo.TransmissionType = transmissionVersion(vehicleInfo.TransmissionRaw, data.TransmissionType, vehicleInfo.TransmissionType, data.TransmissionTypeCont);
                        vehicleInfo.StandardEquipment = data.StandardEquipment;
                        vehicleInfo.TechSpecsChassis = data.TechSpecsChassis;
                        vehicleInfo.TechSpecsDimension = data.TechSpecsDimension;
                        vehicleInfo.TechSpecsPowerTrain = data.TechSpecsPowerTrain;
                        vehicleInfo.Warranty = (data.Warranty == null) ? "" : data.Warranty.replace(/(?:\r\n|\r|\n)/g, '<br />');
                        vehicleInfo.Safety = data.Safety;
                    }
                    deferred.resolve(data);
                }).catch(function (data) {
                    deferred.reject(data);
                });
                return deferred.promise;
            };


            return {
                RetrieveVehicle: retrieveVehicle,
                RetrieveVehicleChromeData: retrieveVehicleChromeData,
                VehicleInfo: vehicleInfo
            }
        }
    ]);
})(angular.module('AutoSMART.Web.VehicleDetail'));

'use strict';
(function (module) {
    module.service('PriceComparisonService', ['Config', '$locale', '$filter', '$http', '$q', 'VehicleDetailService', function (Config, $locale, $filter, $http, $q, VehicleDetailService) {
        var chartData, axisMinMax, tableData;

        var getLowHighAverage = function (list) {
            var lowPrice = Number.POSITIVE_INFINITY;
            var lowMileage = Number.POSITIVE_INFINITY;
            var highPrice = Number.NEGATIVE_INFINITY;
            var highMileage = Number.NEGATIVE_INFINITY;
            var lowPriceCounter = 0, highPriceCounter = 0;
            var priceSum = 0, milesSum = 0;
            for (var i = list.length - 1; i >= 0; i--) {

                if (list[i].Price < lowPrice) {
                    lowPrice = list[i].Price;
                    lowPriceCounter = i;
                }
                if (list[i].Price > highPrice) {
                    highPrice = list[i].Price;
                    highPriceCounter = i;
                }

                if (list[i].Miles < lowMileage) lowMileage = list[i].Miles;
                if (list[i].Miles > highMileage) highMileage = list[i].Miles;

                priceSum += list[i].Price;
                milesSum += list[i].Mileage;
            }

            var lowRow = { Price: list[lowPriceCounter].Price, Mileage: list[lowPriceCounter].Mileage };
            var highRow = { Price: list[highPriceCounter].Price, Mileage: list[highPriceCounter].Mileage };
            var avgRow = { Price: Math.round(priceSum / list.length), Mileage: Math.round(milesSum / list.length) };
            axisMinMax = { PriceMax: highPrice + 1000, PriceMin: lowPrice - 1000, MileageMax: highMileage + 1000, MileageMin: lowMileage - 1000 };
            return{ Low: lowRow, High: highRow, Average: avgRow };
        }

        var cleanString = function (text) {
            var point = text.indexOf('.');
            if (point > -1) {
                return text.substring(0, point);
            }
            return text;
        }

        var getFormattedText = function (text, type) {
            var formatter = type === 0 ? 'currency' : 'number';
            return cleanString($filter(formatter)(text));
        }

        var getFormattedLabel = function (value, type) {
            if (typeof value === 'string' || value instanceof String) {
                value = parseFloat(value.replace(',', ''));
            }

            var val = Math.ceil(value / 1000) + 'K';
            switch (type) {
                case 0: //price
                    return '$' + val;
                case 1: //miles
                    return val;
            }
            return '';
        }

        var getChartOptions = function () {
            var chartWidth = 500;
            if (screen.width === 320) {
                chartWidth = 410;
            }
            if (screen.width === 375 || screen.width === 1024) {
                chartWidth = 465;
            }

            var chartOptions = {
                width: chartWidth,
                height: 300,
                legend: 'none',
                title: 'PRICE vs MILEAGE',
                titleTextStyle: {
                    fontSize: 12,
                    fontName: 'Roboto',
                    bold: false
                },
                vAxis: {
                    gridlines: { color: '#EEEEEE' }, baselineColor: '#EEEEEE',
                    textStyle: { color: '#999999', fontSize: 12 }, viewWindowMode: 'pretty'
                },
                hAxis: {
                    gridlines: { color: '#EEEEEE' }, baselineColor: '#EEEEEE',
                    textStyle: { color: '#999999', fontSize: 12 }, viewWindowMode: 'pretty'
                },

                pointSize: 14,
                trendlines: {
                    0: {
                        type: 'linear',
                        color: Config.SecondaryColor,
                        lineWidth: 3,
                        opacity: 0.3,
                        visibleInLegend: false,
                        tooltip: false
                    }
                },
                isStacked: 'relative',
                chartArea: { backgroundColor: '#F9F9F9' }
            };
            return chartOptions;
        }

        var getTableData = function (dataArray) {
            var lowHighAvg = getLowHighAverage(dataArray);
            var lowPrice = lowHighAvg.Low.Price;
            var lowMiles = lowHighAvg.Low.Mileage;
            var highPrice = lowHighAvg.High.Price;
            var highMiles = lowHighAvg.High.Mileage;
            var avgPrice = lowHighAvg.Average.Price;
            var avgMiles = lowHighAvg.Average.Mileage;
            return {
                LowPrice: lowPrice,
                HighPrice: highPrice,
                AveragePrice: avgPrice,
                LowMiles: lowMiles,
                HighMiles: highMiles,
                AverageMiles: avgMiles
            };
        }

        var drawChart = function () {
            var data = new google.visualization.DataTable();
            data.addColumn('number', 'Mileage');
            data.addColumn('number', 'Prices');
            data.addColumn({ type: 'string', role: 'style' });
            data.addColumn({ type: 'string', role: 'tooltip' });

            var selectedVehicle;
            angular.forEach(chartData,
            function (object) {
                if (object.IsSelected) {
                    selectedVehicle = object;
                }
                else
                {
                    data.addRow([
                    object.Mileage,
                    object.Price,
                    'point {stroke-color: ' + Config.SecondaryColor + '; fill-color: #FFFFFF;}',
                    getFormattedText(object.Price, 0) + '\n' + getFormattedText(object.Mileage, 1) + ' miles'
                    ]);
                }
            });

            if (selectedVehicle != undefined) {
                data.addRow([
                selectedVehicle.Mileage, selectedVehicle.Price,
                'point {stroke-color: ' + Config.SecondaryColor + '; fill-color:' + Config.SecondaryColor + ';}',
                getFormattedText(selectedVehicle.Price, 0) + '\n' + getFormattedText(selectedVehicle.Mileage, 1) + ' miles'
                ]);
            }


            var options = getChartOptions();
            var chartHolders = document.getElementsByClassName('chart-holder');
            for (var i = 0; i < chartHolders.length; i++) {
                var elem = chartHolders[i];
                var chart = new google.visualization.ScatterChart(elem);
                google.visualization.events.addListener(chart, 'ready', afterDraw);

                google.visualization.events.addListener(chart, 'ready', function () {
                    var axisLabels = elem.getElementsByTagName('text');
                    for (var i = 0; i < axisLabels.length; i++) {
                        if (axisLabels[i].getAttribute('text-anchor') === 'end') {
                            axisLabels[i].textContent = getFormattedLabel(axisLabels[i].textContent, 0);
                        }
                        if (axisLabels[i].getAttribute('text-anchor') === 'middle') {
                            axisLabels[i].textContent = getFormattedLabel(axisLabels[i].textContent, 1);
                        }
                    }
                });

                chart.draw(data, options);
            }
        };

        function afterDraw() {
            var loadingChartDataHolder = document.getElementsByClassName('loading-chart-holder');
            for (var i = 0; i < loadingChartDataHolder.length; i++) {
                fade(loadingChartDataHolder[i]);
                var chartHolder = document.getElementsByClassName('chart-holder');
                unfade(chartHolder[i]);
            }
        }

        function fade(element) {
            var op = 1;  // initial opacity
            var timer = setInterval(function () {
                if (op <= 0.1) {
                    clearInterval(timer);
                    element.style.display = 'none';
                }
                element.style.opacity = op;
                element.style.filter = 'alpha(opacity=' + op * 100 + ")";
                op -= op * 0.1;
            }, 10);
        }

        function unfade(element) {
            var op = 0.1;  // initial opacity
            element.style.display = 'block';
            var timer = setInterval(function () {
                if (op >= 1) {
                    clearInterval(timer);
                }
                element.style.opacity = op;
                element.style.filter = 'alpha(opacity=' + op * 100 + ")";
                op += op * 0.1;
            }, 10);
        }

        var setData = function (response) {
            chartData = response;
            tableData = getTableData(response);
            var vehicleInfo = VehicleDetailService.VehicleInfo;

            return { TableData: tableData, Features: vehicleInfo.AdditionalOptions };
        }

        var processData = function (response) {
            google.charts.load('current', { packages: ['corechart'] });
            var returnData = setData(response);
            google.charts.setOnLoadCallback(drawChart);

            return returnData;
        }

        var returnObj = undefined;
        var getPriceComparison = function (dealerCode, vin, itemId, price, miles) {
            miles = (miles) ? miles : 0;
            var deferred = $q.defer();
            var url = Config.VehicleApiUrl + 'pricecomparison/get?dealer=' + dealerCode + '&vin=' + vin + '&itemId=' + itemId + '&price=' + price + '&mileage=' + miles;

            $http.get(url)
                .then(function(response) {
                    returnObj = response.data;
                    deferred.resolve(returnObj);
                },
                    function(failReason) {
                        console.log('failed: ' + failReason);
                        deferred.reject(failReason);
                    });

            return deferred.promise;
        };

        var getPriceComparisonChart = function (priceChartData) {
            if (priceChartData) {
                return processData(priceChartData);
            }
            return null;
        };

        return {
            GetPriceComparison: getPriceComparison,
            GetPriceComparisonChart: getPriceComparisonChart
        };
    }]);

})(angular.module('AutoSMART.Web.VehicleDetail'));
