'use strict';
angular.module('beamng.apps')
.directive('sgrGlowspeedo', ['$log', '$timeout', '$interval', function ($log, $timeout, $interval) {
  return {
    template: '<object style="width:100%; height:100%;" type="image/svg+xml" data="/ui/modules/apps/sgrglowspeedo/sgrglowspeedo.svg"></object>',
    replace: true,
    restrict: 'EA',
    scope: true,
    link: function (scope, element) {
      element.css({ transition: 'opacity 0.3s ease' });
      let visible = false;
      let svg;
      let totalDistance = 0;
      let lastUpdateTime = null;
      let resetHoldStartTime = null;
      let resetCountdownInterval;
      let resetFlashInterval;
      let resetTimeout;
      let countdownActive = false;
      let holdTimeout;
      let colorSyncEnabled = false;
      let colorSyncInterval;
      const countdownDuration = 5;
      const flashCount = 6;
      const flashInterval = 500;
      let currentColorIndex = 0;
      let currentGlowLevelIndex = 0;
      const colors = ['#0000FF', '#39ff14', '#ff0000', '#00ffff', '#ffff00', '#9400d3', '#ffffff'];

      const glowLevels = [
        { blur: 7, intensity: 1 },
        { blur: 11, intensity: 2 },
        { blur: 15, intensity: 3 }
      ];

      function loadSavedOdometer() {
        const savedDistance = localStorage.getItem('sgrGlowspeedoOdometerDistance');
        if (savedDistance) {
          totalDistance = parseFloat(savedDistance);
        }
      }

      function saveOdometer() {
        localStorage.setItem('sgrGlowspeedoOdometerDistance', totalDistance);
      }

      function loadSavedColor() {
        const savedColorIndex = localStorage.getItem('sgrGlowspeedoColorIndex');
        if (savedColorIndex !== null && !colorSyncEnabled) {
          currentColorIndex = parseInt(savedColorIndex, 10);
        }
        updateColor();
      }

      function saveColor() {
        if (colorSyncEnabled) {
          saveSharedColorAndGlow();
        } else {
          localStorage.setItem('sgrGlowspeedoColorIndex', currentColorIndex);
        }
      }

      function loadSavedGlowLevel() {
        const savedGlowLevelIndex = localStorage.getItem('sgrGlowspeedoGlowLevelIndex');
        if (savedGlowLevelIndex !== null && !colorSyncEnabled) {
          currentGlowLevelIndex = parseInt(savedGlowLevelIndex, 10);
        }
        updateGlowIntensity();
      }

      function saveGlowLevel() {
        if (colorSyncEnabled) {
          saveSharedColorAndGlow();
        } else {
          localStorage.setItem('sgrGlowspeedoGlowLevelIndex', currentGlowLevelIndex);
        }
      }

      function loadSavedSyncState() {
        const savedSyncState = localStorage.getItem('sgrGlowspeedoSyncEnabled');
        if (savedSyncState !== null) {
          colorSyncEnabled = savedSyncState === 'true';
        }
        if (colorSyncEnabled) {
          startColorSync();
        }
      }

      function saveSyncState() {
        localStorage.setItem('sgrGlowspeedoSyncEnabled', colorSyncEnabled);
      }

      function loadSharedColorAndGlow() {
        const sharedColorIndex = localStorage.getItem('colorSyncColorIndex');
        const sharedGlowLevelIndex = localStorage.getItem('colorSyncGlowLevelIndex');

        if (sharedColorIndex !== null) {
          currentColorIndex = parseInt(sharedColorIndex, 10);
          updateColor();
        }

        if (sharedGlowLevelIndex !== null) {
          currentGlowLevelIndex = parseInt(sharedGlowLevelIndex, 10);
          updateGlowIntensity();
        }
      }

      function saveSharedColorAndGlow() {
        localStorage.setItem('colorSyncColorIndex', currentColorIndex);
        localStorage.setItem('colorSyncGlowLevelIndex', currentGlowLevelIndex);
      }

      function injectFontStyle() {
        const styleElement = document.createElement('style');
        styleElement.textContent = `
          @font-face {
            font-family: 'DS-Digital';
            src: url('/ui/common/DS-DIGII.ttf') format('truetype');
          }
          text {
            font-family: 'DS-Digital', sans-serif;
          }
        `;
        const svgRoot = svg.querySelector('svg');
        if (svgRoot) {
          svgRoot.appendChild(styleElement);
        }
      }

      function updateColor() {
        const newColor = colors[currentColorIndex];

        const backgroundCircle = svg.getElementById('background_circle');
        if (backgroundCircle) {
          backgroundCircle.setAttribute('fill', newColor);
        }

        const glowingOuterRing = svg.getElementById('glowing_outer_ring');
        if (glowingOuterRing) {
          glowingOuterRing.setAttribute('stroke', newColor);
        }

        const glowingInnerRing = svg.getElementById('glowing_inner_ring');
        if (glowingInnerRing) {
          glowingInnerRing.setAttribute('stroke', newColor);
        }

        const tripText = svg.getElementById('triptext');
        const odometerDigits = [
          svg.getElementById('odometerDigit1'),
          svg.getElementById('odometerDigit2'),
          svg.getElementById('odometerDigit3'),
          svg.getElementById('odometerDigit4'),
          svg.getElementById('odometerDigit5'),
          svg.getElementById('odometerDecimalPoint')
        ];

        if (tripText) {
          tripText.style.fill = newColor;
        }

        odometerDigits.forEach((digit) => {
          if (digit) {
            digit.style.fill = newColor;
          }
        });
      }

      function updateGlowIntensity() {
        const { blur } = glowLevels[currentGlowLevelIndex];

        const glowFilter = svg.querySelector('filter#ring-glow feGaussianBlur');
        if (glowFilter) {
          glowFilter.setAttribute('stdDeviation', blur);
        }

        const mergeNodes = svg.querySelectorAll('filter#ring-glow feMergeNode');
        if (mergeNodes.length > 1) {
          mergeNodes[1].setAttribute('in', 'coloredBlur');
        }
      }

      function applyOffsetIfOne(digitElement, value) {
        if (value === '1') {
          digitElement.setAttribute('dx', '5');
        } else {
          digitElement.setAttribute('dx', '0');
        }
      }

      function updateOdometerDisplay(distanceInMiles) {
        let distanceString = distanceInMiles.toFixed(1).padStart(6, '0');
        const odometerDigits = [
          svg.getElementById('odometerDigit1'),
          svg.getElementById('odometerDigit2'),
          svg.getElementById('odometerDigit3'),
          svg.getElementById('odometerDigit4'),
          svg.getElementById('odometerDigit5')
        ];
        const odometerDecimalPoint = svg.getElementById('odometerDecimalPoint');
        for (let i = 0; i < 3; i++) {
          if (odometerDigits[i]) {
            odometerDigits[i].textContent = distanceString[i];
            applyOffsetIfOne(odometerDigits[i], distanceString[i]);
          }
        }
        if (odometerDigits[3]) {
          odometerDigits[3].textContent = distanceString[3];
          applyOffsetIfOne(odometerDigits[3], distanceString[3]);
        }
        if (odometerDigits[4]) {
          odometerDigits[4].textContent = distanceString[5];
          applyOffsetIfOne(odometerDigits[4], distanceString[5]);
        }
        if (odometerDecimalPoint) {
          odometerDecimalPoint.textContent = '.';
        }
      }

      function showDashes() {
        const odometerDigits = [
          svg.getElementById('odometerDigit1'),
          svg.getElementById('odometerDigit2'),
          svg.getElementById('odometerDigit3'),
          svg.getElementById('odometerDigit4'),
          svg.getElementById('odometerDigit5')
        ];
        odometerDigits.forEach((digit) => {
          if (digit) {
            digit.textContent = '-';
            digit.setAttribute('dx', '0');
          }
        });
      }

      function startImmediateCountdown() {
        if (countdownActive) return;
        countdownActive = true;
        let countdown = countdownDuration;
        resetCountdownInterval = $interval(() => {
          const odometerDigits = [
            svg.getElementById('odometerDigit1'),
            svg.getElementById('odometerDigit2'),
            svg.getElementById('odometerDigit3'),
            svg.getElementById('odometerDigit4'),
            svg.getElementById('odometerDigit5')
          ];
          if (countdown > 0) {
            if (odometerDigits[5 - countdown]) {
              odometerDigits[5 - countdown].textContent = '';
            }
            countdown--;
          } else {
            $interval.cancel(resetCountdownInterval);
            flashResetIndicator();
          }
        }, 1000);
      }

      function flashResetIndicator() {
        const resetWord = ['R', 'E', 'S', 'E', 'T'];
        let flashCountRemaining = flashCount;
        resetFlashInterval = $interval(() => {
          const odometerDigits = [
            svg.getElementById('odometerDigit1'),
            svg.getElementById('odometerDigit2'),
            svg.getElementById('odometerDigit3'),
            svg.getElementById('odometerDigit4'),
            svg.getElementById('odometerDigit5')
          ];
          if (flashCountRemaining % 2 === 0) {
            for (let i = 0; i < resetWord.length; i++) {
              if (odometerDigits[i]) {
                odometerDigits[i].textContent = resetWord[i];
              }
            }
          } else {
            odometerDigits.forEach((digit) => {
              if (digit) digit.textContent = '';
            });
          }
          flashCountRemaining--;
          if (flashCountRemaining <= 0) {
            $interval.cancel(resetFlashInterval);
            resetOdometer();
          }
        }, flashInterval);
      }

      function resetOdometer() {
        totalDistance = 0;
        updateOdometerDisplay(totalDistance);
        saveOdometer();
        countdownActive = false;
      }

      function updateNeedleRotation(currentSpeed) {
        let rotationDegree;
        if (currentSpeed <= 140) {
          rotationDegree = (currentSpeed / 140) * 272;
        } else {
          rotationDegree = (currentSpeed / 140) * 272;
        }
        const needle = svg.getElementById('needle');
        if (needle) {
          needle.setAttribute('transform', `rotate(${rotationDegree}, 0, 0)`);
        }
      }

      function detectLongPress(event) {
        if (event.button === 0) {
          holdTimeout = $timeout(function () {
            toggleColorSync();
          }, 1000);
        }
      }

      function cancelLongPress() {
        $timeout.cancel(holdTimeout);
      }

      function flashIndicator(color) {
  const backgroundCircle = svg.getElementById('background_circle');
  if (!backgroundCircle) return;

  const flashDuration = color === '#006400' ? 700 : 500;
  const resetDuration = color === '#006400' ? 400 : 300;

  for (let i = 0; i < 3; i++) {
    $timeout(function () {
      backgroundCircle.setAttribute('fill', color);
    }, flashDuration * i);

    $timeout(function () {
      backgroundCircle.setAttribute('fill', colors[currentColorIndex]);
    }, flashDuration * i + resetDuration);
  }

  $timeout(function () {
    backgroundCircle.setAttribute('fill', colors[currentColorIndex]);
  }, flashDuration * 3);
}

function toggleColorSync() {
  colorSyncEnabled = !colorSyncEnabled;
  saveSyncState();

  if (colorSyncEnabled) {
    flashIndicator('#006400');

    $timeout(function () {
      colorSyncInterval = setInterval(function () {
        loadSharedColorAndGlow();
      }, 200);
    }, 1800);
  } else {
    flashIndicator('#8B0000');

    clearInterval(colorSyncInterval);
    loadSavedColor();
    loadSavedGlowLevel();
  }
}


      function startColorSync() {
        colorSyncInterval = setInterval(function () {
          loadSharedColorAndGlow();
        }, 200);
      }

      function stopColorSync() {
        clearInterval(colorSyncInterval);
        loadSavedColor();
        loadSavedGlowLevel();
      }

      function initializeSvg() {
        svg = element[0].contentDocument;
        if (!svg) return;

        const colorButton = svg.getElementById('color');
        if (colorButton) {
          colorButton.addEventListener('mousedown', detectLongPress);
          colorButton.addEventListener('mouseup', cancelLongPress);
          colorButton.addEventListener('mouseleave', cancelLongPress);
          colorButton.addEventListener('click', (event) => {
            if (event.button === 0) {
              currentColorIndex = (currentColorIndex + 1) % colors.length;
              updateColor();
              saveColor();
            }
          });

          colorButton.addEventListener('contextmenu', (event) => {
            event.preventDefault();
            currentGlowLevelIndex = (currentGlowLevelIndex + 1) % glowLevels.length;
            updateGlowIntensity();
            saveGlowLevel();
          });
        }

        const resetButton = svg.getElementById('reset');
        if (resetButton) {
          resetButton.addEventListener('mousedown', (event) => {
            if (event.button === 0) {
              const odometerInMiles = totalDistance / 1609.34;
              if (odometerInMiles < 0.1) {
                return;
              }
              showDashes();
              startImmediateCountdown();
              resetHoldStartTime = Date.now();
              resetTimeout = $timeout(() => {
                flashResetIndicator();
              }, 5000);
            }
          });

          resetButton.addEventListener('mouseup', (event) => {
            if (event.button === 0 && resetTimeout) {
              const timeHeld = Date.now() - resetHoldStartTime;
              if (timeHeld < 5000) {
                $timeout.cancel(resetTimeout);
                $interval.cancel(resetCountdownInterval);
                $interval.cancel(resetFlashInterval);
                updateOdometerDisplay(totalDistance / 1609.34);
                countdownActive = false;
              }
            }
          });
        }

        loadSavedOdometer();
        updateOdometerDisplay(totalDistance / 1609.34);
        loadSavedColor();
        loadSavedGlowLevel();
        updateGlowIntensity();

        loadSavedSyncState();

        scope.$on('streamsUpdate', function (event, streams) {
          if (countdownActive || !svg) return;
          let currentSpeed = streams.electrics.wheelspeed;
          updateNeedleRotation(currentSpeed * 2.23694);
          let currentTime = Date.now();
          if (lastUpdateTime !== null) {
            let timeElapsed = (currentTime - lastUpdateTime) / 1000;
            let distanceIncrement = currentSpeed * timeElapsed;
            totalDistance += distanceIncrement;
            updateOdometerDisplay(totalDistance / 1609.34);
            saveOdometer();
          }
          lastUpdateTime = currentTime;
          if (!visible) {
            element[0].style.opacity = 1;
            injectFontStyle();
            visible = true;
          }
        });

        scope.$on('$destroy', function () {
          saveOdometer();
          if (colorSyncInterval) {
            clearInterval(colorSyncInterval);
          }
        });
      }

      element.on('load', initializeSvg);
    }
  };
}]);
