# -*- coding: utf-8 -*-

"""
/***************************************************************************
 Networks
                                 A QGIS plugin
 Networks
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2018-02-26
        copyright            : (C) 2018 by Patrick Palmier
        email                : patrick.palmier@cerema.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

__author__ = 'Patrick Palmier'
__date__ = '2018-02-26'
__copyright__ = '(C) 2018 by Patrick Palmier'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

from qgis.PyQt.QtCore import QCoreApplication,QVariant,QDate,QDateTime,QTime
from qgis.core import *
from qgis.utils import *
from qgis.core import (QgsProcessing,
                       QgsFeatureSink,
                       QgsProcessingAlgorithm,
                       QgsProcessingParameterFeatureSource,
                       QgsProcessingParameterFeatureSink,
                       QgsProcessingParameterNumber,
                       QgsProcessingParameterBoolean,
                       QgsProcessingParameterString,
                       QgsProcessingParameterExtent,
                       QgsProcessingParameterField,
                       QgsProcessingParameterExpression,
                       QgsProcessingParameterDateTime,
                       QgsProcessingParameterFileDestination)

import io, locale,os
import datetime,re, gc

class Google_Stop:
    def __init__(self):
        self.numero=""
        self.nom=""
        self.x=0.0
        self.y=0.0
    def __repr__(self):
        return(unicode({'numero': self.numero,'nom':self.nom,'x':self.x,'y':self.y}))

class Google_Route:
    def __init__(self):
        self.numero=""
        self.nom=""
        self.type='tc'
    def __repr__(self):
        return(unicode({'numero': self.numero,'num':self.nom}))       

     
 
    
class Google_Trip:
    def __init__(self):
        self.route_id=""
        self.service_id=""
        self.trip_id=""
        self.shape_id=""
    def __repr__(self):
        return(unicode({'route_id': self.route_id,'service_id':self.service_id,'trip_id':self.trip_id}))

class Google_Shape:
    def __init__(self):
        self.shape_id=""
        self.x=""
        self.y=""
        self.seq=""
    def __repr__(self):
        return(unicode({'shape_id': self.shape_id,'shape_pt_lat':self.x,'shape_pt_lon':self.y,'shape_pt_sequence':self.seq}))


class Google_Calendar:
    def __init__(self):
        self.semaine=""
        self.calendrier=""
        self.debut=QDate()
        self.fin=QDate()
    def __repr__(self):
        return(unicode({'semaine': self.semaine,'calendrier':self.calendrier,'debut':self.debut,'fin':self.fin}))

class Google_Calendar_Date:
    def __init__(self):
        self.date=QDate()
        self.type=0
        self.service_id=""
    def __repr__(self):
        return(unicode({'date': self.date,'type':self.type}))
        
        
class Google_Stop_Time:
    def __init__(self):
        self.trip_id=""
        self.num_arret=""
        self.heure_arr=0.0
        self.heure_dep=0.0
        self.num_ordre=0
    def __repr__(self):
        return(unicode({'trip_id': self.trip_id,'num_arret':self.num_arret,'heure_arr':self.heure_arr,'heure_dep':self.heure_dep,'num_ordre':self.num_ordre}))


    
    



class ImportGTFSv2(QgsProcessingAlgorithm):
    """
    This is an example algorithm that takes a vector layer and
    creates a new identical one.

    It is meant to be used as an example of how to create your own
    algorithms and explain methods and variables used to do it. An
    algorithm like this will be available in all elements, and there
    is not need for additional work.

    All Processing algorithms should extend the QgsProcessingAlgorithm
    class.
    """

    # Constants used to refer to parameters and outputs. They will be
    # used when calling the algorithm from another algorithm, or when
    # calling from the QGIS console.

    INPUT= 'INPUT'
    DEBUT_PERIODE = 'START_DATE'
    FIN_PERIODE = 'END_DATE'
    HEURE_DEBUT='START_TIME'
    HEURE_FIN='END_TIME'
    OUTPUT='OUTPUT'
    LINE_BASED='LINE_BASED'
    PROJ='PROJ'
    ENCODE='ENCODE'

    def initAlgorithm(self, config):
        """
        Here we define the inputs and output of the algorithm, along
        with some other properties.
        """
        self.addParameter(
            QgsProcessingParameterFile(
                self.INPUT,
                self.tr('GTFS folder'),
                QgsProcessingParameterFile.Folder
            )
        )
        self.addParameter(
            QgsProcessingParameterDateTime(
                self.DEBUT_PERIODE,
                self.tr('Calendar start'),
                type=QgsProcessingParameterDateTime.Date
            )
        )
        self.addParameter(
            QgsProcessingParameterDateTime(
                self.FIN_PERIODE,
                self.tr('Calendar end'),
                type=QgsProcessingParameterDateTime.Date
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.HEURE_DEBUT,
                self.tr('Time period start'),
                defaultValue='07:00:00'
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.HEURE_FIN,
                self.tr('Time period end'),
                defaultValue='08:59:59'
            )
        )
        self.addParameter(
            QgsProcessingParameterCrs(
                self.PROJ,
                self.tr('output crs'),
                QgsProject.instance().crs()

            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.ENCODE,
                self.tr('Encoding'),
                defaultValue='utf_8_sig'
            )
        )
        

                # We add a feature sink in which to store our processed features (this
        # usually takes the form of a newly created vector layer when the
        # algorithm is run in QGIS).
        self.addParameter(
            QgsProcessingParameterFeatureSink(
                self.OUTPUT,
                self.tr('Mint network layer'),
                
            )
        )
        
    def lit_google_stops(self,nom_stops,encodage):
        google_stops = {}
        fichier_stops = io.open(nom_stops,encoding=encodage)
        for  i,ligne in enumerate(fichier_stops):
            if i==0:    
                header =  ligne.split(',') 
                headers = {}
                for j,ii in enumerate(header):
                    headers[ii.strip('"').strip()] = j;
            else:
                    delim="\""
                    elements =re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",ligne[:-1])
                    for ch in elements:
                        ch=ch.replace("\"", "")

                    google_stop = Google_Stop()
                    google_stop.numero = elements[headers["stop_id"]]
                    google_stop.nom = elements[headers["stop_name"]]
                    elements[headers["stop_lon"]]=elements[headers["stop_lon"]].replace("'", "").replace('"','')
                    elements[headers["stop_lat"]]=elements[headers["stop_lat"]].replace("'", "").replace('"','')
                    
                    if elements[headers["stop_lon"]]=='':
                         elements[headers["stop_lon"]]='0'
                    if elements[headers["stop_lat"]]=='':
                         elements[headers["stop_lat"]]='0'
                    if locale.localeconv()["decimal_point"]==",":
                        google_stop.x = float(elements[headers["stop_lon"]].replace(".", ","))
                        google_stop.y = float(elements[headers["stop_lat"]].replace(".", ","))
                        
                    else:
                        google_stop.x = float(elements[headers["stop_lon"]].replace(",", "."))
                        google_stop.y = float(elements[headers["stop_lat"]].replace(",", "."))
                    google_stops[google_stop.numero] = google_stop
        fichier_stops.close()
        return google_stops
            
            
    def lit_google_routes(self,nom_routes,encodage):
        google_routes = {}
        modes={'0':'tram','1':'metro','2':'train','3':'bus','4':'ferry','5':'tram-cable','6':'telepherique','7':'funiculaire','11':'trolley','12':'monorail'}
        fichier_routes = io.open(nom_routes,encoding=encodage)
        for i,ligne in enumerate(fichier_routes):
            if i==0:
                header = ligne[:-1].split(',')
                headers = {}
        
                for j,ii in enumerate(header):
                    headers[ii.strip('"')] = j

        
            else:
                h = []
                head = ligne.strip('\n').strip('\r')
                elements=re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",head)


                google_route = Google_Route()
                google_route.numero = elements[headers["route_id"]]
                if "route_short_name" in headers:
                    google_route.nom = elements[headers["route_short_name"]]
                elif "route_long_name" in headers:
                    google_route.nom = elements[headers["route_long_name"]]
                else:
                    google_route.nom = " "
                if "route_type" in headers:
                    if elements[headers["route_type"]] in modes:
                        google_route.type =modes[elements[headers["route_type"]]]
                google_routes[google_route.numero] = google_route

        fichier_routes.close()
        return google_routes
        
    def lit_google_shapes(self,nom_shapes,encodage):
        google_shapes = {}
        if os.path.exists(nom_shapes):
            fichier_shapes = io.open(nom_shapes,encoding=encodage)
            for i,ligne in enumerate(fichier_shapes):
                if i==0:
                    header = ligne[:-1].split(',')
                    headers = {}
            
                    for j,ii in enumerate(header):
                        headers[ii.strip('"')] = j

        
                else:
                    h = []
                    head = ligne.strip('\n').strip('\r')
                    elements=re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",head)


                    google_shape = Google_Shape()
                    google_shape.shape_id = elements[headers["shape_id"]]
                    if "shape_pt_lon" in headers:
                        google_shape.x = float(elements[headers["shape_pt_lon"]])
                    else:
                        google_shape.x=0
                    if "shape_pt_lat" in headers:
                        google_shape.y = float(elements[headers["shape_pt_lat"]])
                    else:
                        google_shape.y=0
                    if "shape_pt_sequence" in headers:
                        google_shape.seq = float(elements[headers["shape_pt_sequence"]])
                    else:
                        google_shape.seq=0
                    if google_shape.shape_id not in google_shapes:
                        google_shapes[google_shape.shape_id]=[]
                    google_shapes[google_shape.shape_id].append((QgsPointXY(google_shape.x,google_shape.y), google_shape.seq))

            fichier_shapes.close()
            google_shapes2={}
            for i in google_shapes:
                j=sorted(google_shapes[i],key=lambda x:x[1])
                if i not in google_shapes2:
                    google_shapes2[i]=[]
                google_shapes2[i].append(QgsGeometry.fromPolylineXY([m[0] for m in j]))
        else:
            google_shapes2=[]
        return google_shapes2


    def lit_google_trips(self,nom_trips,encodage):
        google_trips = {}
        fichier_trips =io.open(nom_trips,encoding=encodage)

        for i,ligne in enumerate(fichier_trips):
            if i==0:
                header = ligne.strip('\n').strip('\r').split(',')
                headers = {}
                for j,ii  in enumerate(header):
                    headers[ii.strip('"')] = j;
                
            else:
                h = []
                delim = "\"" 
                head = ligne.split(delim)
                for ch in head:
                    h.append(ch.replace(", ", "_ "))
                chaine = "".join(h)


                elements = chaine.split(',')


                google_trip = Google_Trip();
                if "shape_id" in headers:
                    google_trip.shape_id=elements[headers["shape_id"]].strip()
                google_trip.route_id = elements[headers["route_id"]].strip()
                google_trip.service_id = elements[headers["service_id"]].strip()
                google_trip.trip_id = elements[headers["trip_id"]].strip();
                google_trips[google_trip.trip_id] = google_trip


                
        fichier_trips.close()

        return google_trips

    def  lit_google_calendar_dates(self,nom_calendar_dates,encodage):
        google_calendar_dates= {}
        if os.path.isfile(nom_calendar_dates):
            fichier_calendar_dates = io.open(nom_calendar_dates,encoding=encodage)
            for i,ligne in enumerate(fichier_calendar_dates):
                if i==0:
                    header =ligne.strip('\n').strip('\r').split(',')
                    headers = {}
                    for j,ii  in enumerate(header):
                        headers[ii.strip('"')] = j
                else:
                    h = []
                    delim = "\"" 
                    head = ligne.strip('\n').strip('\r').split(delim)
                    for ch in head:
                        h.append(ch.replace(", ", "_ "))
                    chaine = "".join(h)
                    elements = chaine.split(',')
                    google_calendar_date = Google_Calendar_Date()
                    google_calendar_date.date = QDate(int(elements[headers["date"]][0:4]), int(elements[headers["date"]][4:6]),  int(elements[headers["date"]][6:8])).toPyDate()
                    google_calendar_date.type = int(elements[headers["exception_type"]])
                    service_id = elements[headers["service_id"]]
                    if service_id in google_calendar_dates:
                        google_calendar_dates[service_id].append(google_calendar_date)
                        
                    else:
                        
                        google_calendar_dates[service_id]=[]
                        google_calendar_dates[service_id].append(google_calendar_date)

            fichier_calendar_dates.close()
        return google_calendar_dates




    def lit_google_calendars(self,nom_calendars,debut_cal, fin_cal, google_calendar_dates,encodage):
        google_calendars ={}
        if os.path.isfile(nom_calendars):
            fichier_calendars = io.open(nom_calendars,encoding=encodage)
            for i, ligne in enumerate(fichier_calendars):

                
                if i==0:
                    header = ligne.strip('\n').strip('\r').split(',')
                    headers = {}
                    for j,ii  in enumerate(header):
                        headers[ii.strip('"')] = j
                else:
                        h = []
                        delim = "\"" 
                        head = ligne.strip('\n').strip('\r').split(delim)
                        for ch in head:
                            h.append(ch.replace(", ", "_ "))
                        chaine = "".join(h)


                        elements = chaine.split(',')

                        service_id = elements[headers["service_id"]]
                        
                        google_calendar = Google_Calendar()
                        google_calendar.semaine = "".join([elements[headers[k]] for k in ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']])
                        google_calendar.debut = QDate(int(elements[headers["start_date"]][0:4]), int(elements[headers["start_date"]][4:6]), int(elements[headers["start_date"]][6:8])).toPyDate()
                        google_calendar.fin =  QDate(int(elements[headers["end_date"]][0:4]), int(elements[headers["end_date"]][4:6]), int(elements[headers["end_date"]][6:8])).toPyDate()
                        duree_cal = max((debut_cal.daysTo(fin_cal)),1)
                        jour = debut_cal

                        calendrier=""
                        for i in range(duree_cal+1):
                            jour_semaine = jour.dayOfWeek()-1
                            if (google_calendar.debut <= jour <= google_calendar.fin and google_calendar.semaine[jour_semaine] == '1'):
                                calendrier += "O"
                            
                            else:
                                calendrier += "N"
                            
                            jour = jour.addDays(1)


                        
                        google_calendar.calendrier = calendrier
                        google_calendars[service_id]=google_calendar



            fichier_calendars.close()



        for  cal in google_calendar_dates:
            if  cal not in google_calendars:
                duree_cal=max((debut_cal.daysTo(fin_cal)+1),1)
                cal_sem='N'*duree_cal
                gc=Google_Calendar()
                gc.calendrier=cal_sem
                gc.debut=debut_cal
                gc.fin=fin_cal
                gc.semaine='N'*7
                google_calendars[cal]=gc


            if cal in google_calendar_dates:
                for caldate in google_calendar_dates[cal]:
                    date_jour=caldate.date
                    typjour = caldate.type
                    if (debut_cal<=date_jour<=fin_cal):
                        delta=(debut_cal.daysTo(date_jour))
                        if (typjour == 1):
                            google_calendars[cal].calendrier = google_calendars[cal].calendrier[0: delta] + "O" + google_calendars[cal].calendrier[delta + 1:]
                        
                        elif (typjour == 2):
                            google_calendars[cal].calendrier = google_calendars[cal].calendrier[0: delta] + "N" + google_calendars[cal].calendrier[delta + 1:]

        return google_calendars
            


    def lit_google_stop_times(self, nom_stop_times,encodage):
        google_stop_times = {}
        fichier_stop_times = io.open(nom_stop_times,encoding=encodage)
        for i,ligne in enumerate(fichier_stop_times):
                if i==0:
                    header = ligne.strip('\n').strip('\r').split(',')
                    headers = {}
                    for q, ii in enumerate(header):
                        headers[ii.strip('"')] = q
                else:
                    h = []
                    delim = "\"" 
                    head = ligne.split(delim)
                    for ch in head:
                        h.append(ch.replace(", ", "_ "))

                    chaine = "".join( h)


                    elements = chaine.split(',')
                    passage = Google_Stop_Time()
                   
                    passage.trip_id=elements[headers["trip_id"]]
                    try:
                        h1 = elements[headers["arrival_time"]].split(':')
                    except:
                        print(headers)
                        print(elements)
                    try:
                        h2 = elements[headers["departure_time"]].split(':')
                    except:
                        print(headers)
                        print(elements)
                    if len(h1) > 1:
                        passage.heure_arr = float(h1[0]) * 60.0 + float(h1[1]) + float(h1[2]) / 60.0
                        passage.heure_dep = float(h2[0]) * 60.0+ float(h2[1]) + float(h2[2]) / 60.0
                        passage.num_arret=elements[headers["stop_id"]]
                        passage.num_ordre= int(elements[headers["stop_sequence"]])
                        if passage.trip_id not in google_stop_times:
                            google_stop_times[passage.trip_id] = []
                  
                        google_stop_times[passage.trip_id].append([passage.num_ordre, passage])
                    
                    
                   

                
        fichier_stop_times.close()
        for i in google_stop_times:
            google_stop_times[i]=sorted(google_stop_times[i],key= lambda x: x[0])


        return google_stop_times
            


    def cree_chainages(self, google_routes, google_trips, google_calendars, google_stop_times,feedback):
        chainages = {}
        for inc,service in enumerate(google_stop_times):
            feedback.setProgress(inc*100/len(google_stop_times))
            chaine=""
            for num_ordre,passage in google_stop_times[service]:
                chaine += unicode(passage.num_arret)+ ";"
            if  chaine not in chainages:
                chainages[chaine] = []
                    
            trip=Google_Trip()
            chainages[chaine].append(google_trips[service])
        return chainages;


    def cree_musliw(self, google_routes,  google_trips, google_calendars, google_stop_times,  google_chainages, google_stops, google_shapes, feedback,heure_debut, heure_fin,iti,t_links ,proj, noeuds, liens,traces, date_debut,date_fin):
        
      
        
        i=0
        #fichier_musliw = io.open(nom_musliw,"w",encoding="utf8")
        src=QgsCoordinateReferenceSystem("EPSG:4326")
        dest=QgsCoordinateReferenceSystem(proj)
        xtr=QgsCoordinateTransform(src,dest,QgsProject.instance())
        nodes={}
        links={}

        for inc,chaine in enumerate(google_chainages):
            feedback.setProgress(inc*100/len(google_chainages))
            i+= 1
            j = 0
            arcs={}

            for mission in google_chainages[chaine]:

                if mission.route_id in google_routes:
                    elements = google_stop_times[mission.trip_id]
                    trace_id=google_trips[mission.trip_id].shape_id
                    n = len(elements)
                    j+=1
                    textel = ""
                    for  k in range(n-1):
                        if elements[k][1].heure_dep > elements[k + 1][1].heure_dep:
                            elements[k + 1][1].heure_dep+=1440.0
                        if elements[k][1].heure_arr > elements[k + 1][1].heure_arr:
                            elements[k + 1][1].heure_arr += 1440.0
                        if elements[k][1].num_arret not in google_stops:
                            arret = Google_Stop()
                            arret.nom = elements[k][1].num_arret
                            arret.x = 0
                            arret.y = 0
                            google_stops[elements[k][1].num_arret] = arret

                        if elements[k + 1][1].num_arret not in google_stops:
                            arret = Google_Stop()
                            arret.nom = elements[k + 1][1].num_arret
                            arret.x = 0
                            arret.y = 0
                            google_stops[elements[k + 1][1].num_arret] = arret

                        ij=(elements[k][1].num_arret,elements[k + 1][1].num_arret,inc+1)
                        id_link=(elements[k][1].num_arret,elements[k + 1][1].num_arret)
                        hd=heure_debut
                        hf=heure_fin
                        m1=QTime(0,0,0).secsTo(hd)/60
                        m2=QTime(0,0,0).secsTo(hf)/60
                        #m1=hd.hour()*60+hd.minute()+hd.second()/60+hd.msec()/60000
                        #m2=hf.hour()*60+hf.minute()+hf.second()/60+hf.msec()/60000
                        if m1<=elements[k][1].heure_arr and elements[k][1].heure_arr<=m2:
                            if elements[k][1].num_arret not in  nodes:
                                nodes[elements[k][1].num_arret]={'i':elements[k][1].num_arret,'name':google_stops[elements[k][1].num_arret].nom,'dep_monfri':0,'arr_monfri':0,'dep_sat':0,'arr_sat':0,'dep_sun':0,'arr_sun':0}
                                pt1=xtr.transform(QgsPointXY(google_stops[elements[k][1].num_arret].x,google_stops[elements[k][1].num_arret].y))
                                nodes[elements[k][1].num_arret]['geom']=QgsGeometry.fromPointXY(pt1)
                            if elements[k+1][1].num_arret not in  nodes:
                                nodes[elements[k+1][1].num_arret]={'i':elements[k+1][1].num_arret,'name':google_stops[elements[k+1][1].num_arret].nom,'dep_monfri':0,'arr_monfri':0,'dep_sat':0,'arr_sat':0,'dep_sun':0,'arr_sun':0}
                                pt1=xtr.transform(QgsPointXY(google_stops[elements[k+1][1].num_arret].x,google_stops[elements[k+1][1].num_arret].y))
                                nodes[elements[k+1][1].num_arret]['geom']=QgsGeometry.fromPointXY(pt1)
                            if id_link not in links:
                                links[id_link]={}
                                pt1=xtr.transform(QgsPointXY(google_stops[elements[k][1].num_arret].x,google_stops[elements[k][1].num_arret].y))
                                pt2=xtr.transform(QgsPointXY(google_stops[elements[k+1][1].num_arret].x,google_stops[elements[k+1][1].num_arret].y))
                                links[id_link]['geom']=QgsGeometry.fromPolylineXY([pt1,pt2])
                                links[id_link]['longueur']=links[id_link]['geom'].length()
                            if ij not in arcs:
                                arcs[ij]={'temps':0,'nb':0,'nb_monfri':0.0,'i':0,'j':0,'nb_sat':0.0,'nb_sun':0.0}
                                arcs[ij]['texte']=google_routes[mission.route_id].nom + "|" + google_stops[elements[k][1].num_arret].nom + "-" + google_stops[elements[k + 1][1].num_arret].nom
                                arcs[ij]['type']=google_routes[mission.route_id].type
                                pt1=xtr.transform(QgsPointXY(google_stops[elements[k][1].num_arret].x,google_stops[elements[k][1].num_arret].y))
                                pt2=xtr.transform(QgsPointXY(google_stops[elements[k+1][1].num_arret].x,google_stops[elements[k+1][1].num_arret].y))
                                arcs[ij]['geom']=QgsGeometry.fromPolylineXY([pt1,pt2])
                                arcs[ij]['longueur']=arcs[ij]['geom'].length()
                                arcs[ij]['mode']=google_routes[mission.route_id].nom
                                arcs[ij]['shape_id']=trace_id
                            arcs[ij]['temps']+=elements[k + 1][1].heure_arr-elements[k][1].heure_arr
                            arcs[ij]['nb']+=1.0
                            
                            calendrier=google_calendars[mission.service_id]
                            nb_sem=0.0
                            nb_sat=0.0
                            nb_sun=0.0
                            n_sem=0.0
                            n_sat=0.0
                            n_sun=0.0
                            for kk in range(len(calendrier.calendrier)):
                                if ((date_debut.addDays(kk)).dayOfWeek() in [1,2,3,4,5]):
                                    nb_sem+=1.0
                                    if calendrier.calendrier[kk]=='O':
                                        n_sem+=1.0
                                elif ((date_debut.addDays(kk)).dayOfWeek() in [6]):
                                    nb_sat+=1.0
                                    if calendrier.calendrier[kk]=='O':
                                        n_sat+=1.0
                                elif ((date_debut.addDays(kk)).dayOfWeek() in [7]):
                                    nb_sun+=1.0
                                    if calendrier.calendrier[kk]=='O':
                                        n_sun+=1.0
                                else:
                                    print((date_debut.addDays(kk)).dayOfWeek())
#                            ouput.write(";".join([str(s) for s in [calendrier.calendrier,calendrier.debut,calendrier.fin , n_sem,nb_sem,n_sat,nb_sat,n_sun,nb_sun]]))
                            try:
                                arcs[ij]['nb_monfri']+=n_sem/nb_sem
                            except:
                                arcs[ij]['nb_monfri']+=0
                            try:
                                arcs[ij]['nb_sat']+=n_sat/nb_sat
                            except:
                                arcs[ij]['nb_sat']+=0
                            try:
                                arcs[ij]['nb_sun']+=n_sun/nb_sun
                            except:
                                arcs[ij]['nb_sun']+=0
                                
                            
                            #arcs[ij]['nb_monfri']+=(len(google_calendars[mission.service_id].calendrier.split('O'))-1.0)/len(google_calendars[mission.service_id].calendrier)
                            try:
                                nodes[elements[k][1].num_arret]['dep_monfri']+=n_sem/nb_sem
                            except:
                                nodes[elements[k][1].num_arret]['dep_monfri']+=0
                            try:
                                nodes[elements[k+1][1].num_arret]['arr_monfri']+=n_sem/nb_sem
                            except:
                                nodes[elements[k+1][1].num_arret]['arr_monfri']+=0
                            try:
                                nodes[elements[k][1].num_arret]['dep_sat']+=n_sat/nb_sat
                            except:
                                nodes[elements[k][1].num_arret]['dep_sat']+=0
                            try:
                                nodes[elements[k+1][1].num_arret]['arr_sat']+=n_sat/nb_sat
                            except:
                                nodes[elements[k+1][1].num_arret]['arr_sat']+=0
                            try:
                                nodes[elements[k][1].num_arret]['dep_sun']+=n_sun/nb_sun
                            except:
                                nodes[elements[k][1].num_arret]['dep_sun']+=0
                            try:
                                nodes[elements[k+1][1].num_arret]['arr_sun']+=n_sun/nb_sun
                            except:
                                nodes[elements[k+1][1].num_arret]['arr_sun']+=0
                        

                            
            for s in arcs:
                segment=QgsFeature(t_links)
                segment.setGeometry(arcs[s]['geom'])
                segment['i']=s[0]
                segment['j']=s[1]
                segment['line']=s[2]
                segment['mode']=arcs[s]['mode']
                segment['shape_id']=arcs[s]['shape_id']
                segment['temps']=arcs[s]['temps']/arcs[s]['nb']
                segment['longueur']=arcs[s]['longueur']/1000
                segment['nb_monfri']=arcs[s]['nb_monfri']
                segment['texte']=arcs[s]['texte']
                segment['type']=arcs[s]['type']
                segment['nb_sat']=arcs[s]['nb_sat']
                segment['nb_sun']=arcs[s]['nb_sun']
                if segment['nb_monfri']>0:
                    segment['hdw_monfri']=(hd.secsTo(hf)/60)/segment['nb_monfri']
                if segment['nb_sat']>0:
                    segment['hdw_sat'] =(hd.secsTo(hf)/60)/segment['nb_sat']
                if segment['nb_sun']>0:
                    segment['hdw_sun']=(hd.secsTo(hf)/60)/segment['nb_sun']
                if (segment['nb_monfri']+segment['nb_sun']+segment['nb_sun'])>0:
                    iti.addFeature(segment)



        t_noeuds=QgsFields()
        t_noeuds.append(QgsField("i",QVariant.String))
        t_noeuds.append(QgsField("name",QVariant.String))
        t_noeuds.append(QgsField("dep_monfri",QVariant.Double))
        t_noeuds.append(QgsField("arr_monfri",QVariant.Double))
        t_noeuds.append(QgsField("dep_sat",QVariant.Double))
        t_noeuds.append(QgsField("arr_sat",QVariant.Double))
        t_noeuds.append(QgsField("dep_sun",QVariant.Double))
        t_noeuds.append(QgsField("arr_sun",QVariant.Double))
        
        t_arcs=QgsFields()
        t_arcs.append(QgsField("i",QVariant.String))
        t_arcs.append(QgsField("j",QVariant.String))
        t_arcs.append(QgsField("ij",QVariant.String))
        t_arcs.append(QgsField("longueur",QVariant.Double))
        
        t_shapes=QgsFields()
        t_shapes.append(QgsField("shape_id",QVariant.String))
            
        for n in nodes:
            noeud=QgsFeature(t_noeuds)
            noeud.setGeometry(nodes[n]['geom'])
            noeud['i']=n
            noeud['name']=nodes[n]['name']
            noeud['dep_monfri']=nodes[n]['dep_monfri']
            noeud['arr_monfri']=nodes[n]['arr_monfri']
            noeud['dep_sat']=nodes[n]['dep_sat']
            noeud['arr_sat']=nodes[n]['arr_sat']
            noeud['dep_sun']=nodes[n]['dep_sun']
            noeud['arr_sun']=nodes[n]['arr_sun']
            noeuds.addFeature(noeud)

        for l in links:
            link=QgsFeature(t_arcs)
            link.setGeometry(links[l]['geom'])
            link['i']=l[0]
            link['j']=l[1]
            link['ij']=l[0]+'-'+l[1]
            link['longueur']=links[l]['geom'].length()/1000
            liens.addFeature(link)
            
        
        for s in google_shapes:
            shape=QgsFeature(t_shapes)
            shape["shape_id"]=s
            google_shapes[s][0].transform(xtr)
            shape.setGeometry(google_shapes[s][0])
            traces.addFeature(shape)
            
            


    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        fichier_GTFS = self.parameterAsFile(parameters, self.INPUT, context)
        debut_calendrier=self.parameterAsDateTime(parameters,self.DEBUT_PERIODE,context)
        fin_calendrier=self.parameterAsDateTime(parameters,self.FIN_PERIODE,context)
        heure_debut=QTime.fromString(self.parameterAsString(parameters,self.HEURE_DEBUT,context))
        heure_fin=QTime.fromString(self.parameterAsString(parameters,self.HEURE_FIN,context))
        encodage=self.parameterAsString(parameters,self.ENCODE,context)
        
        proj=self.parameterAsCrs(parameters,self.PROJ,context)
        

        t_noeuds=QgsFields()
        t_noeuds.append(QgsField("i",QVariant.String))
        t_noeuds.append(QgsField("name",QVariant.String))
        t_noeuds.append(QgsField("dep_monfri",QVariant.Double))
        t_noeuds.append(QgsField("arr_monfri",QVariant.Double))
        t_noeuds.append(QgsField("dep_sat",QVariant.Double))
        t_noeuds.append(QgsField("arr_sat",QVariant.Double))
        t_noeuds.append(QgsField("dep_sun",QVariant.Double))
        t_noeuds.append(QgsField("arr_sun",QVariant.Double))
        
        t_arcs=QgsFields()
        t_arcs.append(QgsField("i",QVariant.String))
        t_arcs.append(QgsField("j",QVariant.String))
        t_arcs.append(QgsField("ij",QVariant.String))
        t_arcs.append(QgsField("longueur",QVariant.Double))
        
        t_links=QgsFields()
        t_links.append(QgsField("i",QVariant.String))
        t_links.append(QgsField("j",QVariant.String))
        t_links.append(QgsField("temps",QVariant.Double))
        t_links.append(QgsField("longueur",QVariant.Double))
        t_links.append(QgsField("line",QVariant.String))
        t_links.append(QgsField("hdw_monfri",QVariant.Double))
        t_links.append(QgsField("hdw_sat",QVariant.Double))
        t_links.append(QgsField("hdw_sun",QVariant.Double))
        t_links.append(QgsField("mode",QVariant.String))
        t_links.append(QgsField("texte",QVariant.String))
        t_links.append(QgsField("type",QVariant.String))
        t_links.append(QgsField("nb_monfri",QVariant.Double))
        t_links.append(QgsField("nb_sat",QVariant.Double))
        t_links.append(QgsField("nb_sun",QVariant.Double))
        t_links.append(QgsField("shape_id",QVariant.String))
        

        
        t_shapes=QgsFields()
        t_shapes.append(QgsField("shape_id",QVariant.String))
        
        src=QgsCoordinateReferenceSystem("EPSG:4326")
        dest=QgsCoordinateReferenceSystem(proj)
        xtr=QgsCoordinateTransform(src,dest,QgsProject.instance())       
        (iti,lines)=self.parameterAsSink(parameters, self.OUTPUT,context,t_links,QgsWkbTypes.MultiLineString, dest)

        save_options = QgsVectorFileWriter.SaveVectorOptions()
        save_options.fileEncoding = "UTF-8"
        transform_context = QgsProject.instance().transformContext()
        chemin=os.path.split(lines)
        fich_noeuds=chemin[0]+'/'+os.path.splitext(chemin[1])[0]+'_stops.gpkg'
        fich_arcs=chemin[0]+'/'+os.path.splitext(chemin[1])[0]+'_links.gpkg'
        fich_shapes=chemin[0]+'/'+os.path.splitext(chemin[1])[0]+'_shapes.gpkg'
        noeuds=QgsVectorFileWriter.create(fich_noeuds,t_noeuds,QgsWkbTypes.Point,dest,transform_context,save_options)
        links=QgsVectorFileWriter.create(fich_arcs,t_arcs,QgsWkbTypes.MultiLineString,dest,transform_context,save_options)
        shapes=QgsVectorFileWriter.create(fich_shapes,t_shapes,QgsWkbTypes.MultiLineString,dest,transform_context,save_options)
            

        
        # Compute the number of steps to display within the progress bar and
        # get features from source
        ##a=fenetre.split(",")
        ##fenetre2=QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3]))
        os.chdir(fichier_GTFS)
        date_debut=debut_calendrier.date()#QDate.fromString(debut_calendrier, "d/M/yyyy").toPyDate()
        date_fin=fin_calendrier.date()#QDate.fromString(fin_calendrier, "d/M/yyyy").toPyDate()
        feedback.setProgressText(self.tr(u'Reading stops'))
        google_stops = self.lit_google_stops("stops.txt",encodage)
        feedback.setProgressText(self.tr(u'Reading routes'))
        google_routes = self.lit_google_routes("routes.txt",encodage)
        feedback.setProgressText(self.tr(u'Reading trips'))
        google_trips = self.lit_google_trips("trips.txt",encodage)
        feedback.setProgressText(self.tr(u"Reading calendars_dates"))
        google_calendar_dates = self.lit_google_calendar_dates( "calendar_dates.txt",encodage)
        feedback.setProgressText(self.tr(u'Reading calendars'))
        google_calendars = self.lit_google_calendars( "calendar.txt", date_debut, date_fin, google_calendar_dates,encodage)
        feedback.setProgressText(self.tr(u"Reading stop_times"))
        google_stop_times = self.lit_google_stop_times( "stop_times.txt",encodage)
        feedback.setProgressText(self.tr(u"Generating lines"))
        google_shapes=self.lit_google_shapes( "shapes.txt",encodage)
        feedback.setProgressText(self.tr(u"Generating shapes"))
        google_chainages=self.cree_chainages(google_routes, google_trips, google_calendars, google_stop_times,feedback)
        feedback.setProgressText(self.tr(u'Generation Musliw file'))
        self.cree_musliw( google_routes, google_trips, google_calendars, google_stop_times, google_chainages, google_stops,google_shapes, feedback,heure_debut,heure_fin,iti,t_links,proj,noeuds, links,shapes, date_debut, date_fin)
        gc.collect()
        return {'lines' :lines,'nodes': fich_noeuds,'links': fich_arcs, 'shapes': fich_shapes}


    def name(self):
        """
        Returns the algorithm name, used for identifying the algorithm. This
        string should be fixed for the algorithm, and must not be localised.
        The name should be unique within each provider. Names should contain
        lowercase alphanumeric characters only and no spaces or other
        formatting characters.
        """
        return 'import_gtfs_v2'

    def displayName(self):
        """
        Returns the translated algorithm name, which should be used for any
        user-visible display of the algorithm name.
        """
        return self.tr('Import_GTFS_v2')

    def group(self):
        """
        Returns the name of the group this algorithm belongs to. This string
        should be localised.
        """
        return self.tr('Network')

    def groupId(self):
        """
        Returns the unique ID of the group this algorithm belongs to. This
        string should be fixed for the algorithm, and must not be localised.
        The group id should be unique within each provider. Group id should
        contain lowercase alphanumeric characters only and no spaces or other
        formatting characters.
        """
        return 'Network'

    def tr(self, string):
        return QCoreApplication.translate('ImportGTFSv2', string)
        
        
    def shortHelpString(self):
        return self.tr("""
        Scan a GTFS folder and generates the layer of stops, and the layer of simplified arcs and lines
		Computes the transport offer for the specified time period  and calendar (number of stops)
        
        Parameters:
            GTFS_folder : GTFS folder path
			calendar start: calendar date of the first day of the period (dd/mm/YYYY)
			calendar_end: calendar date of the last day of the period (dd/mm/YYYY)
			start_time: start time of the period (hh:mm:ss)
			end_time: end time of the period (hh:mm:ss)
			CRS: generated tables CRS
			Mint network layer: name of the lines layer. Stops and links layers name and will be identical but with _stops and _links at the end
        """)

    def createInstance(self):
        return ImportGTFSv2()
