import { I18NMixins } from "../language/I18NMixins";
import Events from "../core/Events";
import { easeInOutQuint } from "../animation/Ease"
import { classMixin, mergeData, unique_ID, findArrayNumberByUniqueID, hexToRgb, trace } from "../core/Util"
import { Animate } from "../animation/Animate"
import * as DOM from "../dom/DOM"
import { DOMEvent } from "../dom/DOMEvent"
import * as Browser from "../core/Browser"
import Swipable from "../ui/Swipable";
import Message from "../ui/Message"
import { Slide } from "./Slide"
import { SlideNav } from "./SlideNav"

export class StorySlider {
    constructor(elem, data, options, language) {

        if (language) {
            this.setLanguage(language)
        }

        // DOM ELEMENTS
        this._el = {
            container: {},
            background: {},
            slider_container_mask: {},
            slider_container: {},
            slider_item_container: {}
        };

        this._nav = {};
        this._nav.previous = {};
        this._nav.next = {};

        // Slide Spacing
        this.slide_spacing = 0;

        // Slides Array
        this._slides = [];

        // Swipe Object
        this._swipable;

        // Preload Timer
        this.preloadTimer;

        // Message
        this._message;

        // Current Slide
        this.current_id = '';

        // Data Object
        this.data = {};

        this.options = {
            id: "",
            layout: "portrait",
            width: 600,
            height: 600,
            default_bg_color: { r: 255, g: 255, b: 255 },
            slide_padding_lr: 40, // padding on slide of slide
            start_at_slide: 1,
            slide_default_fade: "0%", // landscape fade
            // animation
            duration: 1000,
            ease: easeInOutQuint,
            // interaction
            dragging: true,
            trackResize: true
        };

        // Main element ID
        if (typeof elem === 'object') {
            this._el.container = elem;
            this.options.id = unique_ID(6, "tl");
        } else {
            this.options.id = elem;
            this._el.container = DOM.get(elem);
        }

        if (!this._el.container.id) {
            this._el.container.id = this.options.id;
        }

        // Animation Object
        this.animator = null;

        // Merge Data and Options
        mergeData(this.options, options);
        mergeData(this.data, data);

    }

    init() {
        this._initLayout();
        this._initEvents();
        this._initData();
        this.updateDisplay();

        // Go to initial slide
        this.goTo(this.options.start_at_slide);

        this._onLoaded();
    }

    /* Slides
    ================================================== */
    _addSlide(slide) {
        slide.addTo(this._el.slider_item_container);
        slide.on('added', this._onSlideAdded, this);
        slide.on('background_change', this._onBackgroundChange, this);
    }

    _createSlide(d, title_slide, n) {
        var slide = new Slide(d, this.options, title_slide, this.getLanguage());
        this._addSlide(slide);
        if (n < 0) {
            this._slides.push(slide);
        } else {
            this._slides.splice(n, 0, slide);
        }
    }

    _createSlides(array) {
        for (var i = 0; i < array.length; i++) {
            if (array[i].unique_id == "") {
                array[i].unique_id = unique_ID(6, "tl-slide");
            }
            this._createSlide(array[i], false, -1);
        }
    }

    _removeSlide(slide) {
        slide.removeFrom(this._el.slider_item_container);
        slide.off('added', this._onSlideRemoved, this);
        slide.off('background_change', this._onBackgroundChange);
    }

    _destroySlide(n) {
        this._removeSlide(this._slides[n]);
        this._slides.splice(n, 1);
    }

    _findSlideIndex(n) {
        var _n = n;
        if (typeof n == 'string' || n instanceof String) {
            _n = findArrayNumberByUniqueID(n, this._slides, "unique_id");
        }
        return _n;
    }

    /*	Public
    ================================================== */
    updateDisplay(width, height, animate, layout) {
        var nav_pos, _layout;

        if (typeof layout === 'undefined') {
            _layout = this.options.layout;
        } else {
            _layout = layout;
        }

        this.options.layout = _layout;

        if (width) {
            this.options.width = width;
        } else {
            this.options.width = this._el.container.offsetWidth;
        }

        if (height) {
            this.options.height = height;
        } else {
            this.options.height = this._el.container.offsetHeight;
        }

        this.slide_spacing = this.options.width * 2;

        // position navigation
        nav_pos = (this.options.height / 2);
        this._nav.next.setPosition({ top: nav_pos });
        this._nav.previous.setPosition({ top: nav_pos });


        // Position slides
        for (var i = 0; i < this._slides.length; i++) {
            this._slides[i].updateDisplay(this.options.width, this.options.height, _layout);
            this._slides[i].setPosition({ left: (this.slide_spacing * i), top: 0 });

        };

        // Go to the current slide
        this.goToId(this.current_id, true, true);
    }


    // Create a slide
    createSlide(d, n) {
        this._createSlide(d, false, n);
    }

    // Create Many Slides from an array
    createSlides(array) {
        this._createSlides(array);
    }

    // Destroy slide by index
    destroySlide(n) {
        this._destroySlide(n);
    }

    // Destroy slide by id
    destroySlideId(id) {
        this.destroySlide(this._findSlideIndex(id));
    }

    /*	Navigation
    ================================================== */
    goTo(n, fast, displayupdate) {
        n = parseInt(n);
        if (isNaN(n)) n = 0;

        var self = this;

        this.changeBackground({ color_value: "", image: false });

        // Clear Preloader Timer
        if (this.preloadTimer) {
            clearTimeout(this.preloadTimer);
        }

        // Set Slide Active State
        for (var i = 0; i < this._slides.length; i++) {
            this._slides[i].setActive(false);
        }

        if (n < this._slides.length && n >= 0) {
            this.current_id = this._slides[n].data.unique_id;

            // Stop animation
            if (this.animator) {
                this.animator.stop();
            }
            if (this._swipable) {
                this._swipable.stopMomentum();
            }

            if (fast) {
                this._el.slider_container.style.left = -(this.slide_spacing * n) + "px";
                this._onSlideChange(displayupdate);
            } else {
                this.animator = Animate(this._el.slider_container, {
                    left: -(this.slide_spacing * n) + "px",
                    duration: this.options.duration,
                    easing: this.options.ease,
                    complete: this._onSlideChange(displayupdate)
                });
            }

            // Set Slide Active State
            this._slides[n].setActive(true);

            // Update Navigation and Info
            if (this._slides[n + 1]) {
                this.showNav(this._nav.next, true);
                this._nav.next.update(this._slides[n + 1]);
            } else {
                this.showNav(this._nav.next, false);
            }
            if (this._slides[n - 1]) {
                this.showNav(this._nav.previous, true);
                this._nav.previous.update(this._slides[n - 1]);
            } else {
                this.showNav(this._nav.previous, false);
            }

            // Preload Slides
            this.preloadTimer = setTimeout(function() {
                self.preloadSlides(n);
            }, this.options.duration);
        }
    }

    goToId(id, fast, displayupdate) {
        this.goTo(this._findSlideIndex(id), fast, displayupdate);
    }

    preloadSlides(n) {
        if (this._slides[n + 1]) {
            this._slides[n + 1].loadMedia();
            this._slides[n + 1].scrollToTop();
        }
        if (this._slides[n + 2]) {
            this._slides[n + 2].loadMedia();
            this._slides[n + 2].scrollToTop();
        }
        if (this._slides[n - 1]) {
            this._slides[n - 1].loadMedia();
            this._slides[n - 1].scrollToTop();
        }
        if (this._slides[n - 2]) {
            this._slides[n - 2].loadMedia();
            this._slides[n - 2].scrollToTop();
        }
    }

    next() {
        var n = this._findSlideIndex(this.current_id);
        if ((n + 1) < (this._slides.length)) {
            this.goTo(n + 1);
        } else {
            this.goTo(n);
        }
    }

    previous() {
        var n = this._findSlideIndex(this.current_id);
        if (n - 1 >= 0) {
            this.goTo(n - 1);
        } else {
            this.goTo(n);
        }
    }

    showNav(nav_obj, show) {

        if (this.options.width <= 500 && Browser.mobile) {
            nav_obj.hide();
        } else {
            if (show) {
                nav_obj.show();
            } else {
                nav_obj.hide();
            }

        }
    }



    changeBackground(bg) {
            var bg_color = { r: 256, g: 256, b: 256 },
                bg_color_rgb;

            if (bg.color_value && bg.color_value != "") {
                bg_color = hexToRgb(bg.color_value);
                if (!bg_color) {
                    trace("Invalid color value " + bg.color_value);
                    bg_color = this.options.default_bg_color;
                }
            } else {
                bg_color = this.options.default_bg_color;
                bg.color_value = "rgb(" + bg_color.r + " , " + bg_color.g + ", " + bg_color.b + ")";
            }

            bg_color_rgb = bg_color.r + "," + bg_color.g + "," + bg_color.b;
            this._el.background.style.backgroundImage = "none";


            if (bg.color_value) {
                this._el.background.style.backgroundColor = bg.color_value;
            } else {
                this._el.background.style.backgroundColor = "transparent";
            }

            if (bg_color.r < 255 || bg_color.g < 255 || bg_color.b < 255 || bg.image) {
                this._nav.next.setColor(true);
                this._nav.previous.setColor(true);
            } else {
                this._nav.next.setColor(false);
                this._nav.previous.setColor(false);
            }
        }
        /*	Private Methods
        ================================================== */

    // Update Display

    // Reposition and redraw slides
    _updateDrawSlides() {
        var _layout = this.options.layout;

        for (var i = 0; i < this._slides.length; i++) {
            this._slides[i].updateDisplay(this.options.width, this.options.height, _layout);
            this._slides[i].setPosition({ left: (this.slide_spacing * i), top: 0 });
        };

        this.goToId(this.current_id, true, false);
    }


    /*	Init
    ================================================== */
    _initLayout() {

        this._el.container.classList.add('tl-storyslider');

        // Create Navigation
        this._nav.previous = new SlideNav({ title: "Previous", description: "description" }, { direction: "previous" }, this._el.container);
        this._nav.next = new SlideNav({ title: "Next", description: "description" }, { direction: "next" }, this._el.container);

        // Create Layout
        this._el.slider_container_mask = DOM.create('div', 'tl-slider-container-mask', this._el.container);
        this._el.background = DOM.create('div', 'tl-slider-background tl-animate', this._el.container);
        this._el.slider_container = DOM.create('div', 'tl-slider-container tlanimate', this._el.slider_container_mask);
        this._el.slider_item_container = DOM.create('div', 'tl-slider-item-container', this._el.slider_container);

        // Add aria-live polite to slide_container
        this._el.slider_container.setAttribute('aria-live', 'polite');

        // Update Size
        this.options.width = this._el.container.offsetWidth;
        this.options.height = this._el.container.offsetHeight;

        this._el.slider_container.style.left = "0px";

        if (Browser.touch) {
            //this._el.slider_touch_mask = DOM.create('div', 'tl-slider-touch-mask', this._el.slider_container_mask);
            this._swipable = new Swipable(this._el.slider_container_mask, this._el.slider_container, {
                enable: { x: true, y: false },
                snap: true
            });
            this._swipable.enable();

            // Message
            this._message = new Message(this._el.container, {
                    message_class: "tl-message-full",
                    message_icon_class: "tl-icon-swipe-left"
                },
                this.getLanguage());
            this._message.updateMessage(this._("swipe_to_navigate"));
            this._message.addTo(this._el.container);
        }

    }

    _initEvents() {
        this._nav.next.on('clicked', this._onNavigation, this);
        this._nav.previous.on('clicked', this._onNavigation, this);

        if (this._message) {
            this._message.on('clicked', this._onMessageClick, this);
        }

        if (this._swipable) {
            this._swipable.on('swipe_left', this._onNavigation, this);
            this._swipable.on('swipe_right', this._onNavigation, this);
            this._swipable.on('swipe_nodirection', this._onSwipeNoDirection, this);
        }


    }

    _initData() {
        if (this.data.title) {
            this._createSlide(this.data.title, true, -1);
        }
        this._createSlides(this.data.events);
    }

    /*	Events
    ================================================== */
    _onBackgroundChange(e) {
        var n = this._findSlideIndex(this.current_id);
        var slide_background = this._slides[n].getBackground();
        this.changeBackground(e);
        this.fire("colorchange", slide_background);
    }

    _onMessageClick(e) {
        this._message.hide();
    }

    _onSwipeNoDirection(e) {
        this.goToId(this.current_id);
    }

    _onNavigation(e) {

        if (e.direction == "next" || e.direction == "left") {
            this.next();
        } else if (e.direction == "previous" || e.direction == "right") {
            this.previous();
        }
        this.fire("nav_" + e.direction, this.data);
    }

    _onSlideAdded(e) {
        trace("slideadded")
        this.fire("slideAdded", this.data);
    }

    _onSlideRemoved(e) {
        this.fire("slideRemoved", this.data);
    }

    _onSlideChange(displayupdate) {
        if (!displayupdate) {
            this.fire("change", { unique_id: this.current_id });
        }
    }

    _onMouseClick(e) {

    }

    _fireMouseEvent(e) {
        if (!this._loaded) {
            return;
        }

        var type = e.type;
        type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type));

        if (!this.hasEventListeners(type)) {
            return;
        }

        if (type === 'contextmenu') {
            DOMEvent.preventDefault(e);
        }

        this.fire(type, {
            latlng: "something", //this.mouseEventToLatLng(e),
            layerPoint: "something else" //this.mouseEventToLayerPoint(e)
        });
    }

    _onLoaded() {
        this.fire("loaded", this.data);
    }


}

classMixin(StorySlider, I18NMixins, Events)
