angular.module('gaugesScreen', [])
.controller('GaugesScreenController', function($scope, $window, $timeout) {
    $scope.data = {
        mphVal: "Bork",
        gear: "Bork",
        rpm: "Bork",
        coolantTempVal: "Bork",
        boostVal: "Bork",
        blackout: false,
        oilTempVal: "Bork",
        oilPressVal: "Bork",
        waterVal: "Bork",
        voltsVal: "Bork",
        afrVal: "Bork",
        showOilPressRec: false,
        showWaterRec: false,
        showRpmRec: false,
        showSplashScreen: false,
        showVoltsRec: false,
        dangerToManifold: false,
        puffScreen: false,
        oilPressureDebris: false,
        currentWarmBase: undefined,
        showBoostWarningRec: false,
        showAfrRec: false
    };

    const afrDecelValue = 11.2,
          afrAccelValue = 12.5,
          afrIdleValue = 13.9,
          coldOilTempF = 70,
          warmOilTempF = 190,
          hotOilTempF = 250,
          coldOilPressure = 72,
          warmOilPressure = 49,
          hotOilPressure = 5,
          coldRPMPressureIncrease = 20,
          warmRPMPressureIncrease = 10,
          lowRPMThreshold = 500,
          nearZeroRPMThreshold = 25;

    function getRandomAFR(baseValue, variance) {
        return (baseValue + (Math.random() * (variance * 2) - variance)).toFixed(1);
    }

    $window.updateData = (data) => {
        $scope.$evalAsync(function () {
            if ($scope.data.currentWarmBase === undefined) {
                $scope.data.currentWarmBase = warmOilPressure;
            }
            const previousIgnState = $scope.data.ign || 0;
            $scope.data.ign = data.ign;
            if (previousIgnState === 0 && (data.ign === 1 || data.ign === 3)) {
                $scope.data.showSplashScreen = true;
                $timeout(() => {
                    $scope.data.showSplashScreen = false;
                }, 3000);
            }
            $scope.data.blackout = data.ign <= 0.1;
            if ($scope.data.blackout) {
                $scope.data.mphVal = "00";
                $scope.data.gear = "00";
                $scope.data.rpm = "00";
                $scope.data.coolantTempVal = "00";
                $scope.data.boostVal = "00";
                $scope.data.oilTempVal = "00";
                $scope.data.waterVal = "00";
                $scope.data.voltsVal = "00";
                $scope.data.afrVal = "00";
                $scope.data.showOilPressRec = $scope.data.showWaterRec = $scope.data.showRpmRec = false;
                return;
            }
            $scope.data.gear = data.gear === -1 ? "R" : data.gear === 0 ? "N" : data.gear;
            $scope.data.boostVal = data.boost.toFixed(0);
            $scope.data.rpm = data.ripems;
            $scope.data.mphVal = (data.speed * 2.23694).toFixed(0);
            $scope.data.gpsSpeedVal = (data.gps * 2.23694).toFixed(0);
            let coolantTempF = (data.watertemp * 1.8) + 32;
            let oilTempF = (data.oiltemp * 1.8) + 32;
            $scope.data.oilTempVal = oilTempF.toFixed(0);
            $scope.data.waterVal = coolantTempF.toFixed(0);
            $scope.data.voltsVal = data.voltsVal ? data.voltsVal.toFixed(1) : "00";
            $scope.data.showVoltsRec = parseFloat($scope.data.voltsVal) < 12.1;
            if (data.ripems < 500) {
                $scope.data.afrVal = 0;
            } else if (data.ripems >= 1300) {
                let accelAFRBase = 13.5;
                let factor = 0;
                if (coolantTempF > 32) {
                    factor = Math.min((coolantTempF - 32) / (240 - 32), 1);
                }
                accelAFRBase = 13.5 - (13.5 - 11.7) * factor;
                $scope.data.afrVal = getRandomAFR(accelAFRBase, 0.1);
            } else if (data.ripems < 1300) {
                $scope.data.afrVal = getRandomAFR(afrIdleValue, 0.1);
            } else {
                $scope.data.afrVal = getRandomAFR(afrDecelValue, 0.1);
            }
            $scope.data.showAfrRec = parseFloat($scope.data.afrVal) < 11.8;
            $scope.data.showBoostWarningRec = data.boost > 25;
            let mph = data.speed * 2.23694;
            if (data.ripems < 400) {
                $scope.data.oilPressureDebris = false;
                $scope.data.currentWarmBase = warmOilPressure;
            } else if (!$scope.data.oilPressureDebris && mph > 70 && data.boost > 20) {
                $scope.data.oilPressureDebris = true;
            }
            if ($scope.data.oilPressureDebris) {
                $scope.data.currentWarmBase = $scope.data.currentWarmBase + (15 - $scope.data.currentWarmBase) * 0.1;
            }
            let oilPressure;
            if (data.ripems === 0) {
                oilPressure = 0;
            } else if (oilTempF <= 70) {
                oilPressure = coldOilPressure + (data.ripems / 10000) * coldRPMPressureIncrease;
            } else if (oilTempF >= 250) {
                oilPressure = hotOilPressure;
            } else {
                let base = $scope.data.oilPressureDebris ? $scope.data.currentWarmBase : warmOilPressure;
                oilPressure = base + ((oilTempF - warmOilTempF) / (hotOilTempF - warmOilTempF)) * (hotOilPressure - base) + (data.ripems / 10000) * warmRPMPressureIncrease;
            }
            if (data.ripems < lowRPMThreshold) {
                let pressureDropFactor = data.ripems < nearZeroRPMThreshold ? 0 : data.ripems / lowRPMThreshold;
                oilPressure *= pressureDropFactor;
            }
            if (data.ripems !== 0) oilPressure += Math.random() * 2 - 1;
            $scope.data.oilPressVal = oilPressure.toFixed(0);
            $scope.data.showOilPressRec = parseFloat($scope.data.oilPressVal) < 20;
            $scope.data.showWaterRec = parseFloat($scope.data.waterVal) > 240;
            $scope.data.showRpmRec = data.ripems > ((data.maxRpm || 8000) - 400);
            $scope.data.dangerToManifold = data.boost > 28;
            $scope.data.puffScreen = data.ripems > ((data.maxRpm || 8000) - 400);
        });
    };
});
