text: function newTimelineChart() {
      const MODULE_NAME = 'Timeline Chart'
  
      let logger = newWebDebugLog()
  
  
      let timeFrame = INITIAL_TIME_PERIOD
      let datetime = NEW_SESSION_INITIAL_DATE
  
      let thisObject = {
          container: undefined,
          fitFunction: undefined,
          rateScale: undefined,
          timeFrameScale: undefined,
          payload: undefined,
          layerManager: undefined,
          plotterManager: undefined,
          upstreamTimeFrame: undefined,
          onKeyPressed: onKeyPressed,
          setDatetime: setDatetime,
          setTimeFrame: setTimeFrame,
          physics: physics,
          draw: draw,
          drawBackground: drawBackground,
          drawForeground: drawForeground,
          getContainer: getContainer,
          initialize: initialize,
          finalize: finalize
      }
  
      let timeMachineCoordinateSystem
      let timelineChartCoordinateSystem = newCoordinateSystem()
      timelineChartCoordinateSystem.name = 'TIMELINE CHART'
  
      let coordinateSystem
  
      let layersPanel
      let layersPanelHandle
  
      let onMouseOverEventSuscriptionId
      let onMouseNotOverEventSuscriptionId
      let rateScaleUpstreamEventSuscriptionId
      let rateScaleMouseOverEventSuscriptionId
      let timeFrameScaleEventSuscriptionId
      let timeFrameScaleMouseOverEventSuscriptionId
      let scaleChangedEventSubscriptionId
  
      let drawScales = false
      let mouse = {
          position: {
              x: 0,
              y: 0
          }
      }
  
      setupContainer()
      return thisObject
  
      function setupContainer() {
          thisObject.container = newContainer()
          thisObject.container.initialize(MODULE_NAME)
          thisObject.container.detectMouseOver = true
      }
  
      function finalize() {
          timeMachineCoordinateSystem.eventHandler.stopListening(scaleChangedEventSubscriptionId)
  
          if (thisObject.layerManager !== undefined) {
              finalizeLayerManager()
          }
  
          if (thisObject.rateScale !== undefined) {
              finalizeRateScale()
          }
  
          if (thisObject.timeFrameScale !== undefined) {
              finalizeTimeFrameScale()
          }
  
          thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
          thisObject.container.eventHandler.stopListening(onMouseNotOverEventSuscriptionId)
          thisObject.container.finalize()
          thisObject.container = undefined
          thisObject.payload = undefined
  
          mouse = undefined
          logger = undefined
  
          timeMachineCoordinateSystem = undefined
          timelineChartCoordinateSystem.finalize()
          timelineChartCoordinateSystem = undefined
          coordinateSystem = undefined
          layersPanel = undefined
          layersPanelHandle = undefined
      }
  
      function finalizeLayerManager() {
          if (thisObject.plotterManager !== undefined) {
              thisObject.plotterManager.finalize()
          }
          thisObject.plotterManager = undefined
          thisObject.layerManager = undefined
  
          UI.projects.foundations.spaces.panelSpace.destroyPanel(layersPanelHandle)
      }
  
      function finalizeTimeFrameScale() {
          if (thisObject.timeFrameScale === undefined) { return }
  
          thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleEventSuscriptionId)
          thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleMouseOverEventSuscriptionId)
          thisObject.timeFrameScale.finalize()
          thisObject.timeFrameScale = undefined
          if (thisObject.upstreamTimeFrame !== undefined) {
              timeFrame = thisObject.upstreamTimeFrame
              if (thisObject.plotterManager !== undefined) {
                  thisObject.plotterManager.setTimeFrame(timeFrame)
              }
          }
      }
  
      function finalizeRateScale() {
          if (thisObject.rateScale === undefined) { return }
  
          thisObject.rateScale.container.eventHandler.stopListening(rateScaleMouseOverEventSuscriptionId)
          thisObject.container.parentContainer.eventHandler.stopListening(rateScaleUpstreamEventSuscriptionId)
          thisObject.rateScale.finalize()
          thisObject.rateScale = undefined
  
          /* Resets the local container with the dimensions of its parent, the Time Machine */
          thisObject.container.frame.position.x = 0
          thisObject.container.frame.position.y = 0
          thisObject.container.frame.height = thisObject.container.parentContainer.frame.height
          thisObject.container.frame.width = thisObject.container.parentContainer.frame.width
      }
  
      function initialize(pTimeMachineCoordinateSystem, pTimeFrame) {
          /* We load the logo we will need for the background. */
  
          timeMachineCoordinateSystem = pTimeMachineCoordinateSystem
          coordinateSystem = timeMachineCoordinateSystem
          initializeCoordinateSystem()
  
          timeFrame = pTimeFrame
  
          onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
          onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
          scaleChangedEventSubscriptionId = timeMachineCoordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
      }
  
      function initializeCoordinateSystem() {
          let minValue = {
              x: timeMachineCoordinateSystem.min.x,
              y: 0
          }
  
          let maxValue = {
              x: timeMachineCoordinateSystem.max.x,
              y: nextPorwerOf10(MAX_DEFAULT_RATE_SCALE_VALUE) / 4
          }
  
          if (thisObject.rateScale !== undefined) {
              minValue.y = thisObject.rateScale.minValue
              maxValue.y = thisObject.rateScale.maxValue
          }
  
          timelineChartCoordinateSystem.initialize(
              minValue,
              maxValue,
              thisObject.container.frame.width,
              thisObject.container.frame.heigh
          )
      }
  
      function initializeLayerManager() {
          let owner = thisObject.payload.node.payload.parentNode.id // The real owner is the Time Machine
          layersPanelHandle = UI.projects.foundations.spaces.panelSpace.createNewPanel('Layers Panel', undefined, owner)
          thisObject.layerManager = UI.projects.foundations.spaces.panelSpace.getPanel(layersPanelHandle)
          thisObject.layerManager.payload = thisObject.payload.node.layerManager.payload
          thisObject.layerManager.initialize()
  
          /* Initialize the Plotter Manager */
          thisObject.plotterManager = newPlottersManager()
  
          thisObject.plotterManager.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
  
          thisObject.plotterManager.container.frame.position.x = 0
          thisObject.plotterManager.container.frame.position.y = 0
  
          thisObject.plotterManager.fitFunction = thisObject.fitFunction
          thisObject.plotterManager.payload = thisObject.payload
          thisObject.plotterManager.initialize(thisObject.layerManager)
          thisObject.plotterManager.setTimeFrame(timeFrame)
          thisObject.plotterManager.setDatetime(datetime)
          thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
      }
  
      function initializeRateScale() {
          thisObject.rateScale = newRateScale()
          thisObject.rateScale.fitFunction = thisObject.fitFunction
          thisObject.rateScale.payload = thisObject.payload.node.rateScale.payload
  
          rateScaleMouseOverEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('onMouseOverScale', rateScaleMouseOver)
          thisObject.rateScale.initialize(timelineChartCoordinateSystem, thisObject.container.parentContainer, thisObject.container)
  
          function rateScaleMouseOver(event) {
              thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
          }
      }
  
      function initializeTimeFrameScale() {
          thisObject.timeFrameScale = newTimeFrameScale()
          thisObject.timeFrameScale.fitFunction = thisObject.fitFunction
          thisObject.timeFrameScale.payload = thisObject.payload.node.timeFrameScale.payload
  
          timeFrameScaleEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('Time Frame Value Changed', timeFrameScaleValueChanged)
          timeFrameScaleMouseOverEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('onMouseOverScale', timeFrameScaleMouseOver)
          thisObject.timeFrameScale.initialize(thisObject.container.parentContainer)
  
          function timeFrameScaleValueChanged(event) {
              let currentTimeFrame = timeFrame
              timeFrame = event.timeFrame
              if (timeFrame !== currentTimeFrame) {
                  if (thisObject.plotterManager !== undefined) {
                      thisObject.plotterManager.setTimeFrame(timeFrame)
                  }
              }
          }
  
          function timeFrameScaleMouseOver(event) {
              thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
          }
      }
  
      function onKeyPressed(event) {
  
          /*
          We are going to pass this event to the scales and if they take it return true.
          */
  
          let point = {
              x: event.x,
              y: event.y
          }
          let container
  
          if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) {
              container = thisObject.rateScale.getContainer(point)
              if (container !== undefined) {
                  thisObject.rateScale.onKeyPressed(event)
                  return true
              }
          }
  
          if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) {
              container = thisObject.timeFrameScale.getContainer(point)
              if (container !== undefined) {
                  thisObject.timeFrameScale.onKeyPressed(event)
                  return true
              }
          }
  
          return false
      }
  
      function onScaleChanged(event) {
          if (thisObject.rateScale !== undefined) {
              thisObject.rateScale.onUpstreamScaleChanged(event)
          }
          timelineChartCoordinateSystem.min.x = timeMachineCoordinateSystem.min.x
          timelineChartCoordinateSystem.max.x = timeMachineCoordinateSystem.max.x
          timelineChartCoordinateSystem.maxHeight = timeMachineCoordinateSystem.maxHeight
          timelineChartCoordinateSystem.maxWidth = timeMachineCoordinateSystem.maxWidth
          timelineChartCoordinateSystem.autoMinXScale = timeMachineCoordinateSystem.autoMinXScale
          timelineChartCoordinateSystem.autoMaxXScale = timeMachineCoordinateSystem.autoMaxXScale
          timelineChartCoordinateSystem.recalculateScale()
      }
  
      function setTimeFrame(pTimeFrame) {
          timeFrame = pTimeFrame
          if (thisObject.plotterManager !== undefined) {
              thisObject.plotterManager.setTimeFrame(timeFrame)
          }
      }
  
      function setDatetime(pDatetime) {
          datetime = pDatetime
          if (thisObject.plotterManager !== undefined) {
              thisObject.plotterManager.setDatetime(datetime)
          }
      }
  
      function onMouseOver(event) {
          /* This event gets to the timeline chart container because it inherits it from the time machine container, which is the one raising Mouse Over and Mouse not Over Events to its children. */
          drawScales = true
  
          if (thisObject.rateScale !== undefined) {
              thisObject.rateScale.onMouseOverSomeTimeMachineContainer(event)
          }
  
          if (thisObject.timeFrameScale !== undefined) {
              thisObject.timeFrameScale.onMouseOverSomeTimeMachineContainer(event)
          }
  
          mouse.position.x = event.x
          mouse.position.y = event.y
      }
  
      function onMouseNotOver(event) {
          /* This event is inherited from the Time Machine */
          drawScales = false
  
          if (thisObject.rateScale !== undefined) {
              thisObject.rateScale.visible = false
          }
          if (thisObject.timeFrameScale !== undefined) {
              thisObject.timeFrameScale.visible = false
          }
      }
  
      function getContainer(point, purpose) {
          let container
  
          if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) {
              container = thisObject.rateScale.getContainer(point, purpose)
              if (container !== undefined) {
                  if (purpose === undefined) {
                      return container
                  } else {
                      if (container.isForThisPurpose(purpose)) {
                          return container
                      }
                  }
              }
          }
  
          if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) {
              container = thisObject.timeFrameScale.getContainer(point, purpose)
              if (container !== undefined) {
                  if (purpose === undefined) {
                      return container
                  } else {
                      if (container.isForThisPurpose(purpose)) {
                          return container
                      }
                  }
              }
          }
  
          return container
      }
  
      function physics() {
          plotterManagerPhysics()
          thisObjectPhysics()
          childrenPhysics()
          syncWithDesignerScales()
          syncWithDesignerLayerManager()
      }
  
      function plotterManagerPhysics() {
          if (thisObject.plotterManager !== undefined) {
              thisObject.plotterManager.physics()
          }
      }
  
      function thisObjectPhysics() {
          /* Only if the plotter manager has some layer turned on, we will pass the min and max upstream. */
          if (thisObject.plotterManager !== undefined && thisObject.plotterManager.connectors.length > 0) {
              timelineChartCoordinateSystem.reportParentXValue(timeMachineCoordinateSystem.min.x, timeMachineCoordinateSystem.max.x)
              timelineChartCoordinateSystem.physics()
  
              timeMachineCoordinateSystem.reportXValue(timelineChartCoordinateSystem.childrenMin.x)
              timeMachineCoordinateSystem.reportXValue(timelineChartCoordinateSystem.childrenMax.x)
          }
      }
  
      function syncWithDesignerLayerManager() {
          if (thisObject.payload.node === undefined) {
              finalizeLayerManager()
              return
          }
  
          if (thisObject.payload.node.layerManager === undefined && thisObject.layerManager !== undefined) {
              finalizeLayerManager()
          }
          if (thisObject.payload.node.layerManager !== undefined && thisObject.layerManager === undefined) {
              initializeLayerManager()
          }
      }
  
      function syncWithDesignerScales() {
          if (thisObject.payload.node === undefined) {
              finalizeRateScale()
              finalizeTimeFrameScale()
              return
          }
          if (thisObject.payload.node.rateScale === undefined && thisObject.rateScale !== undefined) {
              finalizeRateScale()
              coordinateSystem = timeMachineCoordinateSystem
              if (thisObject.plotterManager !== undefined) {
                  thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
              }
          }
          if (thisObject.payload.node.rateScale !== undefined && thisObject.rateScale === undefined) {
              initializeRateScale()
              coordinateSystem = timelineChartCoordinateSystem
              if (thisObject.plotterManager !== undefined) {
                  thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
              }
          }
          if (thisObject.payload.node.timeFrameScale === undefined && thisObject.timeFrameScale !== undefined) {
              finalizeTimeFrameScale()
          }
          if (thisObject.payload.node.timeFrameScale !== undefined && thisObject.timeFrameScale === undefined) {
              initializeTimeFrameScale()
          }
      }
  
      function childrenPhysics() {
          if (thisObject.rateScale !== undefined) {
              thisObject.rateScale.layersOn = thisObject.plotterManager.connectors.length
              thisObject.rateScale.physics()
          }
          if (thisObject.timeFrameScale !== undefined) {
              thisObject.timeFrameScale.layersOn = thisObject.plotterManager.connectors.length
              thisObject.timeFrameScale.physics()
          }
      }
  
      function drawBackground() {
          if (thisObject.container.frame.isInViewPort()) {
              if (drawScales === true) {
                  if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawBackground() }
              }
              drawChartsBackground()
              if (thisObject.plotterManager !== undefined) {
                  let elementsPlotted = thisObject.plotterManager.draw()
                  if (thisObject.timeFrameScale !== undefined) {
                      thisObject.timeFrameScale.adjustTimeFrame(elementsPlotted)
                  } else {
                      return elementsPlotted
                  }
              }
          }
      }
  
      function draw() {
          if (thisObject.container.frame.isInViewPort()) {
              if (drawScales === true) {
                  if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.draw() }
                  if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.draw() }
              }
          }
      }
  
      function drawForeground() {
          if (thisObject.container.frame.isInViewPort()) {
              if (drawScales === true) {
                  if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.drawForeground() }
                  if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawForeground() }
              }
          }
      }
  
      function drawChartsBackground() {
          UI.projects.foundations.utilities.drawPrint.drawContainerBackground(thisObject.container, UI_COLOR.WHITE, 0, thisObject.fitFunction)
      }
  }
  