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

      var streamsList = ['engineThermalData', 'electrics', 'sensors'];
      StreamsManager.add(streamsList);

      element[0].querySelector('object').addEventListener('load', function () {
        $timeout(function () {
          svg = element[0].querySelector('object').contentDocument;

          if (!svg) return;

          let needle = svg.getElementById('needle');
          if (!needle) return;

          function calculateOilPressure(tempCelsius, rpm, oilMass, gForce, oilStarvingXY, oilStarvingZ, maxSafeG) {
            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;
            }

            const tempLow = 15.6;
            const tempHigh = 165.6;

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

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

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

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

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

          function mapPressureToRotation(pressure) {
            if (pressure <= 20) {
              return -280 + (pressure / 20) * (8);
            } else if (pressure <= 40) {
              return -272 + ((pressure - 20) / 20) * (30);
            } else if (pressure <= 80) {
              return -242 + ((pressure - 40) / 40) * (57);
            } else if (pressure <= 120) {
              return -185 + ((pressure - 80) / 40) * (52);
            } else if (pressure <= 160) {
              return -133 + ((pressure - 120) / 40) * (55);
            } else {
              return -78 + ((pressure - 160) / 40) * (58);
            }
          }

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

            let rotationDegree = mapPressureToRotation(currentPressure);
            needle.setAttribute('transform', `rotate(${rotationDegree}, 1, -20)`);
          }

          scope.$on('streamsUpdate', function (event, data) {
            if (svg && needle) {
              let oilTempCelsius;
              let rpm;
              let oilMass;
              let gForce = 0;
              let oilStarvingXY = 0;
              let oilStarvingZ = 0;
              let 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;
                let gy2 = data.sensors.gy2;
                let 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);
              }

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

          scope.$on('$destroy', function () {
            StreamsManager.remove(streamsList);
          });
        }, 500);
      });
    }
  };
}]);
