import { Component, Input, OnChanges, HostListener, ElementRef }     from '@angular/core'

interface Navigator {
    arrows: boolean;
    dots: boolean;
}

@Component({
    moduleId: module.id+'',
    selector: 'slider',
    templateUrl: './tpl.slider.pug',
    styleUrls: ['./sty.slider.scss']
})


export class SliderComponent implements OnChanges {
    
    // Get configurable data
    @Input('items') items: any[]

    // GOTCHA: Has to be fed at strings, @Input will change them to act as their types
    @Input('navigation') navigation: string = 'arrows'
    @Input('elementsPrSlide--default') itemsPrSlide: number
    @Input('elementsPrSlide--lap') itemsPrSlideLap: number = 3.5
    @Input('elementsPrSlide--palm') itemsPrSlidePalm: number = 2.5
    @Input('model') model: string

    savedBaseItemsPrSlide: number

    wrapper: number
    calculatedWidth: number
    position: number = 0
    visible: boolean = false;

    containerMaxPosition: number;
    slidesPrPage: number;
    slideWidth: number;
    reset: boolean = false;
    navigator: Navigator = {
        arrows: false,
        dots: false
    }

    constructor (
        private _element : ElementRef
    ) {}

    ngOnChanges(): void {
        this.initSlider()

        // Decides navigation behaviour
        switch(this.navigation) {
            case 'full':
                this.navigator.arrows = true
                this.navigator.dots = true
            break;

            case 'none':
                this.navigator.arrows = false
                this.navigator.dots = false
            break;

            case 'dots':
                this.navigator.arrows = false
                this.navigator.dots = true
            break;

            default:
                this.navigator.arrows = true
                this.navigator.dots = false
            break;
    
        }
    }


    /**
     * Starts setWindowSize with window.innerWidth from load
     * 
     */
    initSlider() {
        let width = typeof window !== 'undefined' ? window.innerWidth : this._element.nativeElement.offsetWidth

        this.savedBaseItemsPrSlide = this.itemsPrSlide;
        this.setWindowSize( width )
    }
    

    /**
     * Fires resizer event on change from the sDOM
     * 
     * @param event: Object<Generic> 
     */
    @HostListener('window:resize', ['$event']) onResize(event) {
        this.setWindowSize(event.target.innerWidth);
    }


    /**
     * Sets Window Size based on feeded width
     * 
     * @param width: integer 
     */
    setWindowSize(width) {

        // Breakpoints for scaling and fitting
        let palmSmall =         321,
            lapStart =          681,
            deskStart =         960,
            deskWideStart =     1280,
            ultraWide =         1600,
            palmEnd =           (lapStart - 1),
            lapEnd =            (deskStart - 1),
            deskEnd =           (deskWideStart - 1);

        // Calculates the amount of sections pr slide in lower resolutions, based on original size
        
        if(width <= lapStart) {
            this.itemsPrSlide = this.itemsPrSlidePalm;
        } else if(width <= deskStart) {
            this.itemsPrSlide = this.itemsPrSlideLap;
        } else {
            this.itemsPrSlide = this.savedBaseItemsPrSlide;
        }

        // Calculate the wrappers width
        this.wrapper = this.items.length * (100 / this.itemsPrSlide)

        // Sets first position to 0
        this.position = 0

        // How many slides are displayed pr page
        this.slidesPrPage = this.itemsPrSlide;
        
        // Finds the highest position for displacing images
        this.containerMaxPosition = 100 - ((100 / this.items.length) * this.slidesPrPage);

        // Calculate the image' width, this value manipulates how many images displayed in a slide
        this.calculatedWidth = (100 / this.items.length)
    }


    /**
     * Displays image when done loading - onnly works on Type: Image
     */
    load() {
        this.visible = true
    }


    /**
     * Move the slider sections left, equal to the itemsPrSlide value
     * 
     * @param void
     */
    next(): void {

        this.position +=  (100 / this.items.length) * Math.floor(this.slidesPrPage);

        if(this.position > this.containerMaxPosition && this.reset == false) {
            this.position = this.containerMaxPosition;

            this.reset = true;

        } else if(this.position > this.containerMaxPosition && this.reset == true) {
            this.position = 0;

            this.reset = false;
        }
    }


    /**
     * Move the slider sections right, equal to the itemsPrSlide value
     * 
     * @param void
     */
    previous(): void {

        if(this.position == 0) 
            this.position = this.containerMaxPosition;
        else if( this.position < 0 )
            this.position = 0;
        else {
            
            this.position -= (100 / this.items.length) * Math.floor(this.slidesPrPage);

            if(this.position < 0)
                this.position = 0;
        }
    }


    /**
     * Sets position to image position, if navigation is enabled
     * 
     * @param image: number 
     */
    gotoSpecificImage(image: number) {
        this.position = image * (100 / (this.itemsPrSlide * this.items.length))
    }


    /**
     * Recieves index from `template` then calculates the current position, and
     * `Math.floor` to make an easy comparison with `this.position`
     * 
     * Math Explained: 100 (to get percentage) divide with (
     *   this.itemsPrSlide - Amount of items to use on each page
     *   this.items.length - Amount of total items
     * ) 
     * multiplied by the index (for current position) +1 to make up for index starting on 0
     * Minus an equal math string, without index+1, to move position to beginning of image
     * 
     * @param {number} index 
     * @returns {boolean}
     */
    isSelectedDot(index) {
        let currentPosition = (100 / (this.itemsPrSlide * this.items.length) * (index+1)) - (100 / (this.itemsPrSlide * this.items.length))

        return Math.floor(currentPosition) == Math.floor(this.position)
    }
}