'use strict';
angular.module('beamng.apps')
.directive('gooseDataLogger', ['$timeout', function($timeout) {
  return {
    template: '<object style="width:100%; height:100%;" type="image/svg+xml" data="/ui/modules/apps/DataLogger/DataLogger.svg"></object>',
    replace: true,
    restrict: 'EA',
    link: function(scope, element, attrs) {
      const localStorageKey = 'loggerData';

      // Unit systems for metric only
      const unitSystems = {
        metric: {
          speedFactor: 1, // m/s to meters
          label: 'meters'
        }
      };

      // Always use metric system
      scope.units = unitSystems.metric;
      scope.goalEnd_330ft = 100.5;    // 330 feet in meters
      scope.goalEnd_60ft = 18.2;      // 60 feet in meters
      scope.goalEnd_660ft = 201;      // 660 feet in meters
      scope.goalEnd_1000ft = 304;     // 1000 feet in meters
      scope.goalEnd_1320ft = 402;     // 1320 feet in meters (1/4 mile)

      function saveData() {
        const data = {
          rpmData,
          wpData,
          asData,
          tpsData,
          psiData,
          gearData,
          gforceData,
          currentX // Save the vertical line position
        };
        localStorage.setItem(localStorageKey, JSON.stringify(data));
      }

      function loadData() {
        const data = JSON.parse(localStorage.getItem(localStorageKey));
        if (data) {
          rpmData = data.rpmData || [];
          wpData = data.wpData || [];
          asData = data.asData || [];
          tpsData = data.tpsData || [];
          psiData = data.psiData || [];
          gearData = data.gearData || [];
          gforceData = data.gforceData || [];
          currentX = data.currentX || 135; // Default to 135 if no saved position
        }
      }

      let svgDocument, rpmLine, wpLine, asLine, tpsLine, psiLine, gearLine, gforceLine;
      let rpmReadout, wheelSpeedReadout, airSpeedReadout, tpsReadout, psiReadout, gearReadout, gforceReadout;
      let movableLineElement, linePositionElement;
      let currentX = 135;
      const minX = 130;
      const maxX = 590;
      let rpmData = [], wpData = [], asData = [], tpsData = [], psiData = [], gearData = [], gforceData = [];
      let isRecording = false;  // Track recording state
      let isPlaying = false;
      let playInterval = null;
      let currentRPM = 0, currentWheelSpeed = 0, currentAirSpeed = 0, currentTPS = 0, currentPSI = 0, currentGear = 0, currentGForce = 0;
      let maxRPM = 16000;
      const secondsPerUnit = (maxX - minX) / 20;

      // Initialize Drag Pass Timers
      scope.initializeDragPassTimers = function() {
        scope.start_time_330ft = 0;
        scope.timer_330ft = 0;
        scope.ready_330ft = false;
        scope.distance_330ft = 0;

        scope.start_time_660ft = 0;
        scope.timer_660ft = 0;
        scope.ready_660ft = false;
        scope.distance_660ft = 0;

        scope.start_time_1000ft = 0;
        scope.timer_1000ft = 0;
        scope.ready_1000ft = false;
        scope.distance_1000ft = 0;

        scope.start_time_60ft = 0;
        scope.timer_60ft = 0;
        scope.ready_60ft = false;
        scope.distance_60ft = 0;

        scope.start_time_1320ft = 0;
        scope.timer_1320ft = 0;
        scope.ready_1320ft = false;
        scope.distance_1320ft = 0;
      };

      // Update Drag Pass Timers Logic
      // Update Drag Pass Timers Logic
scope.updateDragPassTimers = function(streams) {
  // Only update the timers if the logger is recording
  if (!isRecording) {
    console.log("Logger is not recording. Drag pass timers will not run.");
    return;  // Exit early if not recording
  }

        const speedMs = streams.electrics.airspeed;
        const stopThreshold = 0.1;  // Small threshold to treat the car as stopped

        // Use time delta to calculate distance traveled
        const newTime = performance.now();
        const deltaTime = (newTime - scope.lastUpdateTime) / 1000; // Time in seconds since last update
        scope.lastUpdateTime = newTime;

        const distanceTraveled = speedMs * deltaTime;

        // 330ft Timer Logic
        if (scope.ready_330ft && speedMs >= stopThreshold) {
          scope.distance_330ft += distanceTraveled;

          if (scope.distance_330ft >= scope.goalEnd_330ft) {
            console.log("330ft reached! Timer: " + scope.timer_330ft + "ms");
            scope.ready_330ft = false;  // Stop the timer
            scope.distance_330ft = 0;   // Reset distance
          } else {
            scope.timer_330ft += deltaTime * 1000;  // Update the timer in milliseconds
          }

          console.log("330ft: Recording, Distance: " + scope.distance_330ft + "m, Timer: " + scope.timer_330ft + "ms");
        } else if (speedMs < stopThreshold) {
          console.log("330ft: Car stopped, ready to record");
          scope.ready_330ft = true;
          scope.timer_330ft = 0;  // Reset timer when stopped
          scope.distance_330ft = 0; // Reset distance when stopped
        }

        // (Repeat similar logic for 60ft, 660ft, 1000ft, and 1320ft)
        // Similar checks can be added to the logic below

        // 660ft Timer Logic
        if (scope.ready_660ft && speedMs >= stopThreshold) {
          scope.distance_660ft += distanceTraveled;

          if (scope.distance_660ft >= scope.goalEnd_660ft) {
            console.log("660ft reached! Timer: " + scope.timer_660ft + "ms");
            scope.ready_660ft = false;  // Stop the timer
            scope.distance_660ft = 0;   // Reset distance
          } else {
            scope.timer_660ft += deltaTime * 1000;  // Update the timer in milliseconds
          }

          console.log("660ft: Recording, Distance: " + scope.distance_660ft + "m, Timer: " + scope.timer_660ft + "ms");
        } else if (speedMs < stopThreshold) {
          console.log("660ft: Car stopped, ready to record");
          scope.ready_660ft = true;
          scope.timer_660ft = 0;  // Reset timer when stopped
          scope.distance_660ft = 0; // Reset distance when stopped
        }

        // 60ft Timer Logic
        if (scope.ready_60ft && speedMs >= stopThreshold) {
          scope.distance_60ft += distanceTraveled;

          if (scope.distance_60ft >= scope.goalEnd_60ft) {
            console.log("60ft reached! Timer: " + scope.timer_60ft + "ms");
            scope.ready_60ft = false;  // Stop the timer
            scope.distance_60ft = 0;   // Reset distance
          } else {
            scope.timer_60ft += deltaTime * 1000;  // Update the timer in milliseconds
          }

          console.log("60ft: Recording, Distance: " + scope.distance_60ft + "m, Timer: " + scope.timer_60ft + "ms");
        } else if (speedMs < stopThreshold) {
          console.log("60ft: Car stopped, ready to record");
          scope.ready_60ft = true;
          scope.timer_60ft = 0;  // Reset timer when stopped
          scope.distance_60ft = 0; // Reset distance when stopped
        }

        // 1000ft Timer Logic
        if (scope.ready_1000ft && speedMs >= stopThreshold) {
          scope.distance_1000ft += distanceTraveled;

          if (scope.distance_1000ft >= scope.goalEnd_1000ft) {
            console.log("1000ft reached! Timer: " + scope.timer_1000ft + "ms");
            scope.ready_1000ft = false;  // Stop the timer
            scope.distance_1000ft = 0;   // Reset distance
          } else {
            scope.timer_1000ft += deltaTime * 1000;  // Update the timer in milliseconds
          }

          console.log("1000ft: Recording, Distance: " + scope.distance_1000ft + "m, Timer: " + scope.timer_1000ft + "ms");
        } else if (speedMs < stopThreshold) {
          console.log("1000ft: Car stopped, ready to record");
          scope.ready_1000ft = true;
          scope.timer_1000ft = 0;  // Reset timer when stopped
          scope.distance_1000ft = 0; // Reset distance when stopped
        }

        // 1320ft Timer Logic
        if (scope.ready_1320ft && speedMs >= stopThreshold) {
          scope.distance_1320ft += distanceTraveled;

          if (scope.distance_1320ft >= scope.goalEnd_1320ft) {
            console.log("1320ft reached! Timer: " + scope.timer_1320ft + "ms");
            scope.ready_1320ft = false;  // Stop the timer
            scope.distance_1320ft = 0;   // Reset distance
          } else {
            scope.timer_1320ft += deltaTime * 1000;  // Update the timer in milliseconds
          }

          console.log("1320ft: Recording, Distance: " + scope.distance_1320ft + "m, Timer: " + scope.timer_1320ft + "ms");
        } else if (speedMs < stopThreshold) {
          console.log("1320ft: Car stopped, ready to record");
          scope.ready_1320ft = true;
          scope.timer_1320ft = 0;  // Reset timer when stopped
          scope.distance_1320ft = 0; // Reset distance when stopped
        }
      };

      element.on('load', function() {
        svgDocument = element[0].contentDocument;
        rpmLine = svgDocument.getElementById('rpmLine');
        wpLine = svgDocument.getElementById('wpLine');
        asLine = svgDocument.getElementById('asLine');
        tpsLine = svgDocument.getElementById('tpsLine');
        psiLine = svgDocument.getElementById('psiLine');
        gearLine = svgDocument.getElementById('gearLine');
        gforceLine = svgDocument.getElementById('gforceLine');

        rpmReadout = svgDocument.getElementById('rpmReadout');
        wheelSpeedReadout = svgDocument.getElementById('wheelSpeed');
        airSpeedReadout = svgDocument.getElementById('airSpeed');
        tpsReadout = svgDocument.getElementById('tpsReadout');
        psiReadout = svgDocument.getElementById('psiReadout');
        gearReadout = svgDocument.getElementById('gearReadout');
        gforceReadout = svgDocument.getElementById('gforceReadout');

        movableLineElement = svgDocument.getElementById('movableLine');
        linePositionElement = svgDocument.getElementById('linePosition');

        const leftArrowInner = svgDocument.getElementById('leftArrowInner');
        const rightArrowInner = svgDocument.getElementById('rightArrowInner');
        const leftArrowOuter = svgDocument.getElementById('leftArrowOuter');
        const rightArrowOuter = svgDocument.getElementById('rightArrowOuter');
        const playPauseButton = svgDocument.getElementById('playPauseButton');  // Play/Pause button
        const playSymbol = svgDocument.getElementById('playSymbol');  // Play symbol
        const pauseSymbol = svgDocument.getElementById('pauseSymbol');  // Pause symbol

        const Record = svgDocument.getElementById('Record');  // Group containing the button
        const RecordRect = Record.querySelector('rect');  // The <rect> element for color
        const RecordText = Record.querySelector('text');  // The <text> element for label
        let rpmCheckbox = svgDocument.getElementById('rpmCheckbox');
        let wpCheckbox = svgDocument.getElementById('wpCheckbox');
        let asCheckbox = svgDocument.getElementById('asCheckbox');
        let tpsCheckbox = svgDocument.getElementById('tpsCheckbox');
        let psiCheckbox = svgDocument.getElementById('psiCheckbox');
        let gearCheckbox = svgDocument.getElementById('gearCheckbox');
        let gforceCheckbox = svgDocument.getElementById('gforceCheckbox');

        function toggleCheckbox(checkbox, line) {
          let isChecked = checkbox.getAttribute('fill') === 'green';
          checkbox.setAttribute('fill', isChecked ? 'red' : 'green');  // Change checkbox color
          line.style.display = isChecked ? 'none' : 'inline';  // Toggle line visibility
        }

        rpmCheckbox.addEventListener('click', function() {
          toggleCheckbox(rpmCheckbox, rpmLine);
        });

        wpCheckbox.addEventListener('click', function() {
          toggleCheckbox(wpCheckbox, wpLine);
        });

        asCheckbox.addEventListener('click', function() {
          toggleCheckbox(asCheckbox, asLine);
        });

        tpsCheckbox.addEventListener('click', function() {
          toggleCheckbox(tpsCheckbox, tpsLine);
        });

        psiCheckbox.addEventListener('click', function() {
          toggleCheckbox(psiCheckbox, psiLine);
        });

        gearCheckbox.addEventListener('click', function() {
          toggleCheckbox(gearCheckbox, gearLine);
        });

        gforceCheckbox.addEventListener('click', function() {
          toggleCheckbox(gforceCheckbox, gforceLine);
        });

        function updateGraph() {
          let rpmPoints = rpmData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - (data.rpm / maxRPM) * (263 - 110);
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          rpmLine.setAttribute('points', rpmPoints);

          let wpPoints = wpData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - (data.wheelSpeed * 2.23694 / 400) * (263 - 50);
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          wpLine.setAttribute('points', wpPoints);

          let asPoints = asData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - (data.airSpeed * 2.23694 / 400) * (263 - 50);
            if (isNaN(x) || isNaN(y)) return '';
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          asLine.setAttribute('points', asPoints);

          let tpsPoints = tpsData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - ((data.tps * 100) / 100) * (263 - 90);
            if (isNaN(x) || isNaN(y)) return '';
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          tpsLine.setAttribute('points', tpsPoints);

          let psiPoints = psiData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - ((data.psi + 14.7) / (150 + 14.7)) * (263 - 50);
            if (isNaN(x) || isNaN(y)) return '';
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          psiLine.setAttribute('points', psiPoints);

          let gearPoints = gearData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - ((data.gear + 1) / 11) * (263 - 50);
            if (isNaN(x) || isNaN(y)) return '';
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          gearLine.setAttribute('points', gearPoints);

          let gforcePoints = gforceData.map(data => {
            let x = 130 + (data.time / 20) * (590 - 128);
            let y = 263 - ((data.gforce + 3) / 15) * (263 - 50);
            if (isNaN(x) || isNaN(y)) return '';
            return `${x},${y}`;
          }).filter(point => point !== '').join(' ');
          gforceLine.setAttribute('points', gforcePoints);
        }

        function updateRPMReadout(timeInSeconds) {
          const closestDataPoint = rpmData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, rpmData[0]);

          if (closestDataPoint) {
            rpmReadout.textContent = ' ' + closestDataPoint.rpm.toFixed(2);
          }
        }

        function updateWheelSpeedReadout(timeInSeconds) {
          const closestWPData = wpData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, wpData[0]);

          if (closestWPData) {
            wheelSpeedReadout.textContent = ' ' + (closestWPData.wheelSpeed * 2.23694).toFixed(2) + ' mph';
          }
        }

        function updateAirSpeedReadout(timeInSeconds) {
          const closestASData = asData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, asData[0]);

          if (closestASData) {
            airSpeedReadout.textContent = ' ' + (closestASData.airSpeed * 2.23694).toFixed(2) + ' mph';
          }
        }

        function updateTPSReadout(timeInSeconds) {
          const closestTPSData = tpsData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, tpsData[0]);

          if (closestTPSData) {
            tpsReadout.textContent = ' ' + (closestTPSData.tps * 100).toFixed(2) + ' %';
          }
        }

        function updatePSIReadout(timeInSeconds) {
          const closestPSIData = psiData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, psiData[0]);

          if (closestPSIData) {
            psiReadout.textContent = ' ' + closestPSIData.psi.toFixed(2) + ' psi';
          }
        }

        function updateGearReadout(timeInSeconds) {
          const closestGearData = gearData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, gearData[0]);

          if (closestGearData) {
            gearReadout.textContent = ' ' + closestGearData.gear;
          }
        }

        function updateGForceReadout(timeInSeconds) {
          const closestGForceData = gforceData.reduce((prev, curr) => {
            return (Math.abs(curr.time - timeInSeconds) < Math.abs(prev.time - timeInSeconds) ? curr : prev);
          }, gforceData[0]);

          if (closestGForceData) {
            gforceReadout.textContent = ' ' + closestGForceData.gforce.toFixed(2);
          }
        }

        function updatePositionDisplay() {
          const seconds = ((currentX - minX) / secondsPerUnit).toFixed(2);
          linePositionElement.textContent = seconds + 's';
          updateRPMReadout(seconds);
          updateWheelSpeedReadout(seconds);
          updateAirSpeedReadout(seconds);
          updateTPSReadout(seconds);
          updatePSIReadout(seconds);
          updateGearReadout(seconds);
          updateGForceReadout(seconds);
        }

        function updateLinePosition() {
          movableLineElement.setAttribute('x1', currentX);
          movableLineElement.setAttribute('x2', currentX);
          updatePositionDisplay();
        }

        function startRecording() {
          isRecording = true;
          currentX = minX;  // Move the line to the beginning
          updateLinePosition();  // Update the line position to the start

          let currentTime = 0;
          rpmData = [], wpData = [], asData = [], tpsData = [], psiData = [], gearData = [], gforceData = [];

          let interval = setInterval(function() {
              if (currentTime >= 20 || !isRecording) {  // Stop recording when time reaches or user clicks stop
                  clearInterval(interval);
                  isRecording = false;

                  // Move the line back to the center when done recording
                  currentX = (minX + maxX) / 2;
                  updateLinePosition();

                  // Change button back to green Start
                  RecordRect.setAttribute('fill', '#00FF00');
                  RecordText.textContent = 'Record';
                  return;
              }
            currentTime += 0.010;

            currentX = minX + (currentTime / 20) * (maxX - minX);  // Move the line with time
            updateLinePosition();  // Update the line position along with recording

            rpmData.push({ time: currentTime, rpm: currentRPM });
            wpData.push({ time: currentTime, wheelSpeed: currentWheelSpeed });
            asData.push({ time: currentTime, airSpeed: currentAirSpeed });
            tpsData.push({ time: currentTime, tps: currentTPS });
            psiData.push({ time: currentTime, psi: currentPSI });
            gearData.push({ time: currentTime, gear: currentGear });
            gforceData.push({ time: currentTime, gforce: currentGForce });

            updateGraph();
          }, 10);
        }

        // Toggle Start/Stop button functionality
     Record.addEventListener('click', function() {
         if (!isRecording) {
             // Start recording
             startRecording();

             // Change button to red Stop
             RecordRect.setAttribute('fill', 'red');
             RecordText.textContent = 'Stop';
             isRecording = true;
         } else {
             // Stop recording
             isRecording = false;  // Stop the recording

             // Change button back to green Start
             RecordRect.setAttribute('fill', '#00FF00');
             RecordText.textContent = 'Record';
         }
     });

        function togglePlayPause() {
          if (isPlaying) {
            // Pause the playback
            clearInterval(playInterval);
            isPlaying = false;
            playSymbol.style.display = 'inline';  // Show the play triangle
            pauseSymbol.style.display = 'none';   // Hide the pause bars
          } else {
            // Start playing
            playInterval = setInterval(function() {
              if (currentX < maxX) {
                currentX += (secondsPerUnit / 100); // Adjust for playback speed
                if (currentX > maxX) {
                  currentX = maxX;
                  clearInterval(playInterval);
                }
                updateLinePosition();
              } else {
                clearInterval(playInterval);  // Stop playback at the end
              }
            }, 10); // Adjust this for speed control (10ms = smooth real-time)
            isPlaying = true;
            playSymbol.style.display = 'none';   // Hide the play triangle
            pauseSymbol.style.display = 'inline'; // Show the pause bars
          }
        }

        playPauseButton.addEventListener('click', function() {
          togglePlayPause();  // Toggle play or pause when the button is clicked
        });

        // Event listeners for the inner and outer arrows
        leftArrowInner.addEventListener('mousedown', function(event) {
          if (event.button === 0) {  // Left click
            if (currentX > minX) {
              currentX -= secondsPerUnit;
              if (currentX < minX) currentX = minX;  // Bound check
              updateLinePosition();
            }
          } else if (event.button === 2) {  // Right click
            if (currentX > minX) {
              currentX -= secondsPerUnit / 2;
              if (currentX < minX) currentX = minX;
              updateLinePosition();
            }
          }
        });

        rightArrowInner.addEventListener('mousedown', function(event) {
          if (event.button === 0) {  // Left click
            if (currentX < maxX) {
              currentX += secondsPerUnit;
              if (currentX > maxX) currentX = maxX;  // Bound check
              updateLinePosition();
            }
          } else if (event.button === 2) {  // Right click
            if (currentX < maxX) {
              currentX += secondsPerUnit / 2;
              if (currentX > maxX) currentX = maxX;
              updateLinePosition();
            }
          }
        });

        leftArrowOuter.addEventListener('mousedown', function(event) {
          if (event.button === 0) {  // Left click
            if (currentX > minX) {
              currentX -= (secondsPerUnit / 10);
              if (currentX < minX) currentX = minX;
              updateLinePosition();
            }
          } else if (event.button === 2) {  // Right click
            if (currentX > minX) {
              currentX -= (secondsPerUnit / 100);
              if (currentX < minX) currentX = minX;
              updateLinePosition();
            }
          }
        });

        rightArrowOuter.addEventListener('mousedown', function(event) {
          if (event.button === 0) {  // Left click
            if (currentX < maxX) {
              currentX += (secondsPerUnit / 10);
              if (currentX > maxX) currentX = maxX;
              updateLinePosition();
            }
          } else if (event.button === 2) {  // Right click
            if (currentX < maxX) {
              currentX += (secondsPerUnit / 100);
              if (currentX > maxX) currentX = maxX;
              updateLinePosition();
            }
          }
        });

        svgDocument.addEventListener('contextmenu', function(event) {
          event.preventDefault();
        });

        scope.$on('streamsUpdate', function(event, streams) {
          if (streams.engineInfo && streams.engineInfo.length > 4) {
            currentRPM = streams.engineInfo[4];
            currentWheelSpeed = streams.electrics.wheelspeed;
            currentAirSpeed = streams.electrics.airspeed;
            currentTPS = streams.electrics.throttle;
            currentPSI = streams.electrics.boost;
            currentGear = streams.electrics.gear;

            if (streams.engineInfo.length > 1) {
              maxRPM = streams.engineInfo[1] || 16000;
            }

            const gravity = streams.sensors.gravity || 9.81;
            const gx2 = streams.sensors.gx2 || 0;
            const gy2 = streams.sensors.gy2 || 0;
            const gz2 = streams.sensors.gz2 || 0;

            currentGForce = Math.sqrt(gx2 * gx2 + gy2 * gy2 + (gz2 + 9.81) * (gz2 + 9.81)) / 9.81;
          }

          // Update drag pass timers with the stream data
          scope.updateDragPassTimers(streams);
        });

        scope.$on('$destroy', function() {
          saveData();
          rpmLine = null;
          wpLine = null;
          asLine = null;
          tpsLine = null;
          psiLine = null;
          gearLine = null;
          gforceLine = null;
          rpmReadout = null;
          wheelSpeedReadout = null;
          airSpeedReadout = null;
          tpsReadout = null;
          psiReadout = null;
          gearReadout = null;
          gforceReadout = null;
          movableLineElement = null;
          linePositionElement = null;
        });

        loadData();
        updateLinePosition(); // Restore the vertical line position on load
        updateGraph(); // Restore the graph data on load
        scope.initializeDragPassTimers(); // Initialize drag pass timers on load
      });
    }
  };
}]);
