<template>
    <v-row ref="globalTimeline">
        <div class="pa-0 switch" v-if="editActive">
            <v-switch
            v-model="editDates"
            label="Editer"
            ></v-switch>
        </div>
        <div class="pa-0 btns" :style="'width:'+btnsWidth+'px;'">
            <TimelineButton :type="'left'" :btnsWidth="btnsWidth" :elements="previousStep"  @click.native="previousAction"/>
            <!-- <v-btn
                fab
                dark
                x-small
                depressed
                color="primary" 
                @click="previousAction"
                >
                <v-icon dark>
                    mdi-chevron-left
                </v-icon>
            </v-btn> -->
        </div>
        <div ref="timelineContainer" class="timelineContainer" :style="getHeight">
            <TimelineContent 
                :editDates="editDates"  
                @setClicked="setClicked" 
                :stepClicked="stepClicked" 
                @showPopup="showPopup" 
                :globalHeight="getHeightGlobal" 
                :redefinedSteps="redefinedSteps" 
                :nbCrossingSteps="nbCrossingSteps" 
                :animation="animation" 
                :daysArray="daysEventArray" 
                :dayWidth="dayWidth" 
                :steps="value" 
                :style='getContainerStyle' class='timelineContent' ref="timelineContainer2"
                :leftContainer="left"
                @addDayItem="addDayItem"
                @reCalculateHeight="reCalculateHeight"
                @substractDayItem="substractDayItem"/>
        </div>
        <div class="pa-0 btns" :style="'width:'+btnsWidth+'px;'">
            <TimelineButton :type="'right'" :btnsWidth="btnsWidth" :elements="nextStep"  @click.native="nextAction"/>
            <!-- <v-btn
                fab
                dark
                x-small
                depressed
                color="primary" 
                @click="nextAction"
                >
                <v-icon dark>
                    mdi-chevron-right
                </v-icon>
            </v-btn> -->
        </div>
        <TimelinePopup @hidePopup="hidePopup" v-show="popupShow" :step="popupStep" :style="popupStyle" class="popup"/>
    </v-row>
</template>

<script>
import TimelineContent from '@/components/TimelineContent'
import TimelinePopup from '@/components/TimelinePopup'
import TimelineButton from '@/components/TimelineButton'
import dateManipulation from '@/mixins/dateManipulation'
import timelineMixin from '@/mixins/timelineMixin'
export default {
    name:"Timeline",
    props:["displaySize", "value", "editActive"],
    mixins:[dateManipulation, timelineMixin],
    components: {
        TimelineContent, TimelinePopup, TimelineButton
    },
    data() {
        return {
            editDates: false,
            popupShow : false,
            popupStyle : "",
            containerWidth : 0,
            windowSize:0,
            left:0,
            animation: true,
            daysEventArray: [],
            popupStep : {},
            stepClicked: false,
            nbCrossingSteps: 0,
            timelineStart: "",
            timelineEnd: "",
        }
    },
    mounted() {
        window.addEventListener('resize', this.onResize)
        //get la largeur du container
        this.containerWidth = this.$refs.globalTimeline.getBoundingClientRect().width - 20
        this.windowSize = document.getElementById("app").getBoundingClientRect().width;
        //déplace la timeline pour se mettre sur l'opération
        let operation = this.value.find((e) => e.type == "OPERATION")
        let endDate = this.splitDate(operation.end).date
        let startDate = new Date(endDate).getTime() - ((this.displaySize - 1) * (1000 * 60 * 60 * 24)) 
        let refDate = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(startDate)))
        this.timelineEnd = endDate
        this.timelineStart = refDate
        setTimeout(() => {
            var offsetLeft = this.$refs.timelineContainer2.$refs["day_"+refDate.split('-').join('')][0].$el.offsetLeft
            this.left = - offsetLeft
        }, 2);
        this.$refs.timelineContainer2.$refs.day_20210124[0].$el.style.backgroundColor = ""
        this.nbCrossingStepsFunction()
    },
    created() {
        //initialisation du tableau de jours
        let start = this.dateStepArray[0];
        //on prends les jours entre la première étape et la dernière
        for (let index = 0; index < this.nbDaysBetweenEvents; index++) {
            let element = new Date (new Date(start).getTime() + (index*24*60*60*1000));
            let type = ""
            if(element.getDay() == 0 || element.getDay() == 6){
                type = "weekend"
            }
            this.daysEventArray[index] = {
                date: this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(element)),
                class: type 
            }
        }
        // et on y ajoute autant de jours que le nombre de jours displayed. (evite un bug visuel sur les pastilles)
        for (let index = 1; index < (parseInt(this.displaySize) + 1); index++) {
            let element = new Date (new Date(start).getTime() - (index*24*60*60*1000));
            let type = ""
            if(element.getDay() == 0 || element.getDay() == 6){
                type = "weekend"
            }
            let object = {
                date: this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(element)),
                class: type 
            }
            this.daysEventArray.unshift(object)
        }
    },
    methods: {
        onResize(event) {
            setTimeout(() => {
                this.containerWidth = this.$refs.globalTimeline.getBoundingClientRect().width - 20;
                this.windowSize = document.getElementById("app").getBoundingClientRect().width;
                let operation = this.value.find((e) => e.type == "OPERATION")
                let endDate = this.splitDate(operation.end).date
                let startDate = new Date(endDate).getTime() - ((this.displaySize - 1) * (1000 * 60 * 60 * 24)) 
                let refDate = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(startDate)))
                this.timelineEnd = endDate
                this.timelineStart = refDate
                var offsetLeft = this.$refs.timelineContainer2.$refs["day_"+refDate.split('-').join('')][0].$el.offsetLeft
                this.left = - offsetLeft
            }, 200);
        },
        reCalculateHeight: function(){
            this.nbCrossingStepsFunction()
        },
        //Nombre de chevauchement d'étapes maximum
        nbCrossingStepsFunction: function(){
            this.nbCrossingSteps = this.getItemsOrdered(this.redefinedSteps).length
        },
        substractDayItem: function(event, position, stepId){
            let step = this.value.find((e) => e.id == stepId)
            if(position == 'end'){
                let endDate = new Date(step.end).getTime() - (1000 * 60 * 60 * 24)
                let newEnd = this.splitDate(new Intl.DateTimeFormat('fr-FR', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(endDate)))
                let finalDate = this.parseFrDateToUs(newEnd.date)+' '+newEnd.hour
                step.end = finalDate
            } else if(position == 'start'){
                let startDate = new Date(step.start).getTime() - (1000 * 60 * 60 * 24)
                let newStart= this.splitDate(new Intl.DateTimeFormat('fr-FR', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(startDate)))
                let finalDate = this.parseFrDateToUs(newStart.date)+' '+newStart.hour
                step.start = finalDate
            }
            this.$emit("input", this.value)
        },
        addDayItem: function(event, position, stepId){
            let step = this.value.find((e) => e.id == stepId)
            if(position == 'end'){
                let endDate = new Date(step.end).getTime() + (1000 * 60 * 60 * 24)
                let newEnd = this.splitDate(new Intl.DateTimeFormat('fr-FR', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(endDate)))
                let finalDate = this.parseFrDateToUs(newEnd.date)+' '+newEnd.hour
                step.end = finalDate
            } else if(position == 'start'){
                let startDate = new Date(step.start).getTime() + (1000 * 60 * 60 * 24)
                let newStart= this.splitDate(new Intl.DateTimeFormat('fr-FR', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(startDate)))
                let finalDate = this.parseFrDateToUs(newStart.date)+' '+newStart.hour
                step.start = finalDate
            }
            this.$emit("input", this.value)
        },
        //booléen au clic sur une pastille. Pour éviter les action au hover lorsque l'on a cliqué.
        setClicked: function (event, value){
            this.stepClicked = value
        },
        //action pour montrer la popup et la placée au meilleur endroit (gauche ou droite de la pastille cliquée)
        showPopup: function(event, id){
            let itemL = event.clientX + (this.dayWidth / 2);
            let step = this.value.find((e) => e.id == id)
            this.popupStep = step;
            if(itemL < (this.containerWidth / 2)){
                //mets la popup a gauche de la pastille cliquée 
                this.popupStyle = "left:"+itemL+"px;"
            }else {
                //mets la popup a droite de la pastille cliquée
                let position = itemL - 250;
                this.popupStyle = "left:"+(itemL - 460 - this.dayWidth*2)+"px;"
            }
            this.popupShow = true
        },
        //Cache la popup et repasse le booléen de clic a false
        hidePopup: function(){
            this.popupShow = false
            this.stepClicked = false
        },
        //si on va dans le futur 
        nextAction: function(){ 
            this.hidePopup();
            let newLeft = this.left - this.dayWidth * 7;
            if(newLeft < - (this.timelineTotalSize - this.containerWidth)){
                this.addDays(7, 'end')
            }
            this.left += - this.dayWidth * 7
            setTimeout(() => {
                this.timelineStart = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(this.timelineStart).getTime() + (7*24*60*60*1000)))
                this.timelineEnd = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(this.timelineEnd).getTime() + (7*24*60*60*1000)))
            }, 1)
        },
        //Si on va dans le passé
        previousAction: function(){
            this.hidePopup();
            let newLeft = this.left + this.dayWidth * 7;
            newLeft = newLeft > -1 && newLeft < 1 ? 0 : newLeft
            //Si on atteinds le left 0
            if(newLeft > 0){
                let offset = ((Math.round(-(newLeft + this.left)/this.dayWidth)+1));
                if(offset > 0){
                    this.addDays((7-offset), 'start')
                } else {
                    this.addDays(7, 'start')
                }
                setTimeout(() => {
                    this.animation = true;
                    this.left = 0;
                }, 1)
            } else {
                this.left += this.dayWidth * 7
                this.timelineStart = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(this.timelineStart).getTime() - (7*24*60*60*1000)))
                this.timelineEnd = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(this.timelineEnd).getTime() - (7*24*60*60*1000)))
            }
        },
        //fonction d'ajout de jours dans le tableau si on dépasse les jours de bases
        addDays: function(nb, where){
            switch (where) {
                case 'start':
                    this.animation = false;
                    let startDate = this.daysEventArray[0].date
                    for (let index = 1; index <= nb  ; index++) {
                        let element = new Date (new Date(startDate).getTime() - (index*24*60*60*1000));
                        let type = ""
                        if(element.getDay() == 0 || element.getDay() == 6){
                            type = "weekend"
                        }
                        let object = {
                            date: this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(element)),
                            class: type 
                        }
                        this.daysEventArray.unshift(object)     
                        this.left -= this.dayWidth            
                    }   
                    this.timelineStart = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(this.timelineStart).getTime() - (7*24*60*60*1000)))
                    this.timelineEnd = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date(this.timelineEnd).getTime() - (7*24*60*60*1000)))                     
                    break;
                case 'end':
                    let endDate = this.daysEventArray[this.daysEventArray.length - 1].date
                    for (let index = 1; index <= nb; index++) {
                        let element = new Date (new Date(endDate).getTime() + (index*24*60*60*1000));
                        let type = ""
                        if(element.getDay() == 0 || element.getDay() == 6){
                            type = "weekend"
                        }
                        let object = {
                            date: this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(element)),
                            class: type 
                        }
                        this.daysEventArray.push(object)
                    }
                    break;
            }
        },
       
    },
    computed: {
        previousStep: function(){
            let array = []
            this.value.forEach(step => {
                let isBefore = true
                if(new Date(this.splitDate(step.start).date).getTime() >= new Date(this.timelineStart).getTime() || 
                (step.period && (new Date(this.splitDate(step.start).date).getTime() >= new Date(this.timelineStart).getTime() || new Date(this.splitDate(step.end).date).getTime() >= new Date(this.timelineStart).getTime()))){
                    isBefore = false
                }
                if(isBefore){
                    array.push(step)
                }
            })
            return array
        },
        nextStep: function(){
            let array = []
            this.value.forEach(step => {
                let isBefore = true
                if(step.id == 20 && this.timelineEnd == "2021-01-21"){
                    console.log(step)
                    console.log(this.splitDate(step.start).date)
                    console.log(this.timelineEnd)
                    console.log("gettimestep", new Date(this.splitDate(step.start).date).getTime())
                    console.log("gettimelineend", new Date(this.timelineEnd).getTime())
                    console.log(new Date(this.splitDate(step.start).date).getTime() < new Date(this.timelineEnd).getTime())
                }
                
                if(new Date(this.splitDate(step.start).date).getTime() <= new Date(this.timelineEnd).getTime() || 
                (step.period && (new Date(this.splitDate(step.start).date).getTime() <= new Date(this.timelineEnd).getTime() || new Date(this.splitDate(step.end).date).getTime() <= new Date(this.timelineEnd).getTime()))){
                    isBefore = false
                }
                if(isBefore){
                    array.push(step)
                }
            })
            return array
        },
         //redéfini l'array des étapes pour y insérer les ref de jours de chacun
        redefinedSteps: function(){
            let newSteps = []
            this.value.forEach(step => {
                let object = Object.assign({}, step)
                object.start = this.splitDate(object.start).date 
                if(object.period){
                    object.end = this.splitDate(object.end).date
                    //définition de ttes les refs 
                    let ref = [];
                    let nbDaysPeriod = this.DaysBetween(new Date(object.start), new Date(object.end))
                    for (let index = 0; index < nbDaysPeriod; index++) {
                        let element = this.parseFrDateToUs(new Intl.DateTimeFormat('fr-FR').format(new Date (new Date(object.start).getTime() + (index*24*60*60*1000))));
                        ref.push("day_"+element.split('-').join(""))
                    }
                    object.ref = ref
                } else {
                    let soloRef = [];
                    soloRef.push("day_"+object.start.split('-').join(''))
                    object.ref = soloRef
                }
                newSteps.push(object)
            });
            return newSteps
        },
        //Taille de la frise au global
        timelineTotalSize : function(){
            return this.daysEventArray.length * this.dayWidth;
        },
        //Array des dates générées pour la frise
        dateStepArray : function(){
            let dateArray = []
            this.value.forEach(step => {
                let startDate = this.splitDate(step.start).date;
                dateArray.push(startDate);
                if(step.end != ''){
                    let endDate = this.splitDate(step.end).date;
                    dateArray.push(endDate);
                }
            });
            dateArray.sort(function(a, b){
                return new Date(a) - new Date(b)
            })
            return dateArray
        },
        //date du début de la première étape
        startEventDate: function() {
            return this.dateStepArray[0]
        },
        //date de fin de la derniere étapes
        endEventDate: function() {
            return this.dateStepArray[this.dateStepArray.length - 1]
        },
        //nombre de jours entre la première et la derniere étape
        nbDaysBetweenEvents: function() {
            return this.DaysBetween(new Date(this.startEventDate), new Date(this.endEventDate))
        },
        //style généré pour le placement de la frise
        getContainerStyle: function(){
            let nbSteps = this.nbCrossingSteps
            if(nbSteps%2 != 0){
                nbSteps += 1
            }
            let style = "";
            style += this.animation ? 'transition: left 0.5s ease-in-out; ' : ""
            style += "height:" + (nbSteps * 90 + 30) +"px; "
            style += "left:"+this.left+"px;"
            return style
        },
        getHeight: function(){
            let nbSteps = this.nbCrossingSteps
            if(nbSteps%2 != 0){
                nbSteps += 1
            }
            let style = "height:" + (nbSteps * 90 + 30) +"px; "

            //calcul de la largeur
            style += "width:"+(this.dayWidth * parseInt(this.displaySize))+"px;"

            return style
        },
        getHeightGlobal: function(){
            let nbSteps = this.nbCrossingSteps
            if(nbSteps%2 != 0){
                nbSteps += 1
            }
            return (nbSteps * (this.dayWidth + 50) + 30)
        },
        //largeur d'une cellule jour
        dayWidth: function() {
            return Math.floor((this.containerWidth - (this.btnsWidth * 2)) / parseInt(this.displaySize))
        },
        btnsWidth: function() {
            let width;
            if(this.containerWidth < 750){
                width = 40
            } else if(this.containerWidth < 1200){
                width = 100
            } else {
                width = 150
            }
            return width
        }
    },
}
</script>

<style lang="scss">
    .globalTimeline{
        display:flex;
        justify-content:center;
        align-items: center;
    }
    .switch {
        position:absolute;
        top:10px;
        right:10px;
        .v-input {
            margin:0
        }
    }
    .timelineContent {
        padding:0;
        display: flex;
        align-items: center;
        height:150px;
        width: 100%;
        position:absolute;
    }
    .timelineContainer {
        position:relative;
        overflow:hidden;
        height:150px;
        padding:0 !important;
    }
    .btns {
        display:flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }
</style>