'use strict';
angular.module('beamng.apps')
.directive('sgrGlowoilpress', ['$log', '$timeout', function ($log, $timeout) {
  return {
    template: '<object style="width:100%; height:100%;" type="image/svg+xml" data="/ui/modules/apps/sgrglowoilpress/sgrglowoilpress.svg"></object>',
    replace: true,
    restrict: 'EA',
    scope: true,
    link: function (scope, element) {
      element.css({ transition: 'opacity 0.3s ease' });
      let svg;
      let needle;
      let visible = false;
      let currentColorIndex = 0;
      let currentGlowLevelIndex = 0;
      let colorSyncEnabled = false;
      let holdTimeout;
      let colorSyncInterval;
      let currentPressure = 60;
      let pressureDropTimer = 0;
      const pressureDropDelay = 5;
      const pressureDropRate = 1;
      let isPressureAtZero = false;

      const colors = ['#0000FF', '#39ff14', '#ff0000', '#00ffff', '#ffff00', '#9400d3', '#ffffff'];
      const glowLevels = [
        { blur: 7, intensity: 1 },
        { blur: 11, intensity: 2 },
        { blur: 15, intensity: 3 }
      ];

      const minDegree = 0;
      const maxDegree = 265;
      const smoothFactor = 0.02;
      const streamsList = ['engineThermalData', 'electrics', 'sensors'];
      StreamsManager.add(streamsList);

      function calculateOilPressure(tempCelsius, rpm, oilMass, gForce, oilStarvingXY, oilStarvingZ, maxSafeG) {
        const tempLow = 15.6;
        const tempHigh = 165.6;

        if (oilMass < 1.0 || rpm <= 0 || oilStarvingXY > 0 || oilStarvingZ > 0 || gForce > maxSafeG) {
          if (!isPressureAtZero && pressureDropTimer <= 0) {
            pressureDropTimer = pressureDropDelay;
          }
        } else {
          pressureDropTimer = 0;
          isPressureAtZero = false;
        }

        if (pressureDropTimer > 0) {
          pressureDropTimer -= 0.05;
          if (pressureDropTimer <= 0) {
            isPressureAtZero = true;
          }
        }

        if (isPressureAtZero) {
          currentPressure -= pressureDropRate;
          if (currentPressure <= 0) {
            currentPressure = 0;
          }
          return currentPressure;
        }

        let basePressure;
        if (tempCelsius <= tempLow) {
          basePressure = 60;
        } else if (tempCelsius >= tempHigh) {
          basePressure = 0;
        } else {
          basePressure = 60 * (1 - (tempCelsius - tempLow) / (tempHigh - tempLow));
        }

        let rpmFactor = Math.pow(Math.min(rpm / 3000, 1), 1.5);
        let pressure = basePressure + (40 * rpmFactor);

        let gForceReduction = Math.min(gForce / 2, 15);
        pressure -= gForceReduction;

        return Math.max(0, Math.min(pressure, 200));
      }

      function smoothTransition(targetPressure, currentPressure, factor) {
        return currentPressure + (targetPressure - currentPressure) * factor;
      }

      function mapPressureToRotation(pressure) {
        const minPressure = 0;
        const maxPressure = 100;
        const minDegree = 0;
        const maxDegree = 265;
        pressure = Math.max(minPressure, Math.min(pressure, maxPressure));
        const ratio = (pressure - minPressure) / (maxPressure - minPressure);
        return minDegree + ratio * (maxDegree - minDegree);
      }

      function updateNeedleRotation(tempCelsius, rpm, oilMass, gForce, oilStarvingXY, oilStarvingZ, maxSafeG) {
        let targetPressure = calculateOilPressure(tempCelsius, rpm, oilMass, gForce, oilStarvingXY, oilStarvingZ, maxSafeG);
        currentPressure = smoothTransition(targetPressure, currentPressure, smoothFactor);

        let rotationDegree = mapPressureToRotation(currentPressure);
        if (needle) {
          needle.setAttribute('transform', `rotate(${rotationDegree}, 0, 0)`);
        }
      }

      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 loadSavedSyncState() {
        const savedSyncState = localStorage.getItem('sgrGlowoilpressSyncEnabled');
        if (savedSyncState !== null) {
          colorSyncEnabled = savedSyncState === 'true';
        }
        if (colorSyncEnabled) {
          colorSyncInterval = setInterval(function () {
            loadSharedColorAndGlow();
          }, 200);
        }
      }

      function saveSyncState() {
        localStorage.setItem('sgrGlowoilpressSyncEnabled', 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 loadSavedColor() {
        const savedColorIndex = localStorage.getItem('sgrGlowoilpressColorIndex');
        if (savedColorIndex !== null) {
          currentColorIndex = parseInt(savedColorIndex, 10);
        }
        updateColor();
      }

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

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

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

      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);
        }
      }

      function updateGlowIntensity() {
        const { blur } = glowLevels[currentGlowLevelIndex];
        const glowFilter = svg.querySelector('filter#ring-glow feGaussianBlur');
        if (glowFilter) {
          glowFilter.setAttribute('stdDeviation', blur);
        }
      }

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

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

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

        const colorButton = svg.getElementById('color');
        const resetButton = svg.getElementById('reset');

        needle = svg.getElementById('needle');

        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();
          });
        }

        if (resetButton) {
          resetButton.addEventListener('mousedown', (event) => {
          });
        }

        loadSavedColor();
        loadSavedGlowLevel();
        updateGlowIntensity();
        loadSavedSyncState();

        if (!visible) {
          element[0].style.opacity = 1;
          visible = true;
        }

        scope.$on('streamsUpdate', function (event, data) {
          let oilTempCelsius, rpm, oilMass, gForce = 0, oilStarvingXY = 0, oilStarvingZ = 0, maxSafeG = Infinity;

          if (data.electrics && data.electrics.oiltemp !== undefined) oilTempCelsius = data.electrics.oiltemp;
          if (data.electrics && data.electrics.rpm !== undefined) rpm = data.electrics.rpm;
          if (data.engineThermalData && data.engineThermalData.oilMass !== undefined) oilMass = data.engineThermalData.oilMass;
          if (data.sensors && data.sensors.gx2 !== undefined && data.sensors.gy2 !== undefined && data.sensors.gz2 !== undefined) {
            let gx2 = data.sensors.gx2, gy2 = data.sensors.gy2, gz2 = data.sensors.gz2;
            gForce = Math.sqrt(gx2 * gx2 + gy2 * gy2 + (gz2 + 9.81) * (gz2 + 9.81)) / 9.81;
          }
          if (data.engineThermalData && data.engineThermalData.oilStarvingSevernessXY !== undefined) oilStarvingXY = data.engineThermalData.oilStarvingSevernessXY;
          if (data.engineThermalData && data.engineThermalData.oilStarvingSevernessZ !== undefined) oilStarvingZ = data.engineThermalData.oilStarvingSevernessZ;
          if (data.engineThermalData && data.engineThermalData.maximumSafeG !== undefined) maxSafeG = data.engineThermalData.maximumSafeG;

          if (oilTempCelsius !== undefined && rpm !== undefined && oilMass !== undefined) {
            updateNeedleRotation(oilTempCelsius, rpm, oilMass, gForce, oilStarvingXY, oilStarvingZ, maxSafeG);
          }
        });

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

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