import ThemeProvider from '@mui/material/styles/ThemeProvider';
import { FC, StrictMode } from 'react';
import styles from './App.module.scss';
import { ArmsFreight, PayloadFreight } from './configs/freighter';
import { ArmsPax, PayloadPax } from './configs/pax';
import { ArmsFuel, EmptyArm, Fuel, toPercentMAC } from './configs/shared';

interface IAppProps {
  dataListener: ViewListener.ViewListener;
}

const App: FC<IAppProps> = () => {
  // TODO: Get from EFB settings
  const [unit, setUnit] = useState<'lbs' | 'kg'>('lbs');
  // TODO: Look into EFB, infer the same way
  const [aircraft, setAircraft] = useState<'f' | 'pax'>('f');
  const [payload, setPayload] = useState<PayloadPax | PayloadFreight>();
  const [fuel, setFuel] = useState<Fuel>();

  const [ZFWCG, setZFWCG] = useState(0);
  const [TOCG, setTOCG] = useState(0);

  const requestRef = useRef<number | undefined>(undefined);

  const mainLoop = () => {
    try {
      if (SimVar.IsReady()) {
        const conversion = SimVar.GetSimVarValue('FUEL WEIGHT PER GALLON', unit);
        const emptyWeight = SimVar.GetSimVarValue('EMPTY WEIGHT', unit);

        const payload: PayloadPax | PayloadFreight = {
          pilot: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:1', unit),
          firstOfficer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:2', unit),
          engineer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:3', unit),
          upper1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:4', unit),
          cabinCrewFront: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:4', unit),
          upper1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:5', unit),
          business1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:5', unit),
          upper2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:6', unit),
          business1Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:6', unit),
          upper2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:7', unit),
          business1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:7', unit),
          upper3Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:8', unit),
          business2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:8', unit),
          upper3Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:9', unit),
          business2Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:9', unit),
          upper4Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:10', unit),
          business2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:10', unit),
          upper4Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:11', unit),
          economy1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:11', unit),
          lowerForward: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:12', unit),
          economy1Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:12', unit),
          lowerRear: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:13', unit),
          economy1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:13', unit),
          leftAuxF: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:14', unit),
          economy2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:14', unit),
          rightAuxF: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:15', unit),
          economy2Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:15', unit),
          economy2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:16', unit),
          cabinCrewRear: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:17', unit),
          forwardCargo: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:18', unit),
          rearCargo: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:19', unit),
          leftAuxPax: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:20', unit),
          rightAuxPax: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:21', unit),
        };

        const fuel = {
          main1: SimVar.GetSimVarValue('FUEL TANK LEFT MAIN QUANTITY', 'gal') * conversion,
          main3: SimVar.GetSimVarValue('FUEL TANK RIGHT MAIN QUANTITY', 'gal') * conversion,
          main2: SimVar.GetSimVarValue('FUEL TANK CENTER QUANTITY', 'gal') * conversion,
          upperAux: SimVar.GetSimVarValue('FUEL TANK CENTER2 QUANTITY', 'gal') * conversion,
          lowerAux: SimVar.GetSimVarValue('FUEL TANK CENTER3 QUANTITY', 'gal') * conversion,
          main1Tip: SimVar.GetSimVarValue('FUEL TANK LEFT TIP QUANTITY', 'gal') * conversion,
          main3Tip: SimVar.GetSimVarValue('FUEL TANK RIGHT TIP QUANTITY', 'gal') * conversion,
          tail: SimVar.GetSimVarValue('FUEL TANK EXTERNAL1 QUANTITY', 'gal') * conversion,
          forwardAux1: SimVar.GetSimVarValue('FUEL TANK LEFT AUX QUANTITY', 'gal') * conversion,
          forwardAux2: SimVar.GetSimVarValue('FUEL TANK RIGHT AUX QUANTITY', 'gal') * conversion,
        };

        let totalMoment = EmptyArm * emptyWeight;
        let totalWeight = emptyWeight;
        const arms = aircraft === 'f' ? ArmsFreight : ArmsPax;
        for (const key in arms) {
          if (Object.prototype.hasOwnProperty.call(payload, key)) {
            const stationWeight = payload[key as keyof (PayloadFreight | PayloadPax)];
            const arm = arms[key as keyof typeof arms];

            totalWeight += stationWeight;
            totalMoment += arm * stationWeight;
          }
        }
        setZFWCG(toPercentMAC(totalMoment / totalWeight));

        for (const key in ArmsFuel) {
          if (Object.prototype.hasOwnProperty.call(fuel, key)) {
            const stationWeight = fuel[key as keyof Fuel];
            const arm = ArmsFuel[key as keyof typeof ArmsFuel];

            totalWeight += stationWeight;
            totalMoment += arm * stationWeight;
          }
        }
        setTOCG(toPercentMAC(totalMoment / totalWeight));

        setPayload(payload);
        setFuel(fuel);
      }
    } catch {}

    requestRef.current = requestAnimationFrame(mainLoop);
  };

  useEffect(() => {
    requestRef.current = requestAnimationFrame(mainLoop);

    if (requestRef.current !== undefined) return () => cancelAnimationFrame(requestRef.current as number);
  }, [unit, aircraft]);

  return (
    <StrictMode>
      <div className={styles.app}>
        <button onClick={() => (unit === 'lbs' ? setUnit('kg') : setUnit('lbs'))}>Change unit from {unit}</button>
        <button onClick={() => (aircraft === 'f' ? setAircraft('pax') : setAircraft('f'))}>
          Change aircraft from {aircraft}
        </button>
        <div style={{ display: 'flex' }}>
          <div>
            <pre>{JSON.stringify(payload, null, 2)}</pre>
            <strong>ZFWCG: {ZFWCG}</strong>
          </div>
          <div>
            <pre>{JSON.stringify(fuel, null, 2)}</pre>
            <strong>TOCG: {TOCG}</strong>
          </div>
        </div>
      </div>
    </StrictMode>
  );
};

export default App;
