import * as fs from "node:fs";
import { Mission } from "../Aerofly/Mission.js";
import { Test } from "../Cli/Test.js";
import { MsfsPln } from "../Import/MsfsPln.js";
import { SimBrief } from "../Import/SimBrief.js";

export class SimBriefTest extends Test {
  constructor(protected process: NodeJS.Process, protected dieOnError = false) {
    super(process, dieOnError);
    this.testMsfsStatic();
    this.testAeroflyStatic();
    this.testAeroflyStaticDestination();
    this.testAeroflyStatic2();
    this.testAeroflyStaticDestination2();
  }

  static async init(process: NodeJS.Process, dieOnError = false): Promise<SimBriefTest> {
    const self = new SimBriefTest(process, dieOnError);
    await self.testMsfsLive("fjboes");
    await self.testMsfsLive("746243");
    await self.testAeroflyLive("fjboes");
    await self.testAeroflyLive("746243");
    return self;
  }

  async testMsfsLive(username: string): Promise<void> {
    this.group(SimBrief.name + ".testMsfsLive(" + username + ")");
    const simBrief = new SimBrief();
    const msfsPln = await simBrief.fetchMsfs(username);
    this.assert(msfsPln !== "", "Response not empty");

    const pln = new MsfsPln(msfsPln);
    this.assert(pln !== null, "is valid MSFS PLN");
  }

  testMsfsStatic(): void {
    this.group(SimBrief.name + ".testMsfsStatic()");

    const msfsPln = fs.readFileSync("./src/Tests/fixtures/simbrief-mfs.pln", "utf8");
    this.assert(msfsPln !== "", "Response not empty");

    const pln = new MsfsPln(msfsPln);
    this.assert(pln !== null, "is valid MSFS PLN");

    const mission = new Mission("TEST", "TEST");
    mission.fromGarminFpl(pln);

    this.assertEquals(mission.checkpoints.length, 11);
    this.assertEquals(mission.origin_icao, "KEYW");
    this.assertEquals(mission.destination_icao, "KMIA");
    this.assertEquals(mission.checkpoints[0].name, mission.origin_icao);
    this.assertEquals(mission.checkpoints[mission.checkpoints.length - 1].name, mission.destination_icao);
  }

  async testAeroflyLive(username: string): Promise<void> {
    this.group(SimBrief.name + ".testAeroflyLive(" + username + ")");

    const simBrief = new SimBrief();
    const mission = await simBrief.fetchMission(username, new Mission("TEST", "TEST"));
    this.assert(mission !== null, "Response not empty");
  }

  testAeroflyStatic(): void {
    this.group(SimBrief.name + ".testAeroflyStatic()");
    const simBrief = new SimBrief();
    const simbriefPayload = fs.readFileSync("./src/Tests/fixtures/simbrief-api.json", "utf8");
    const simbriefPayloadJson = JSON.parse(simbriefPayload);

    const mission = simBrief.convertMission(simbriefPayloadJson, new Mission("TEST", "TEST"));
    this.assert(mission !== null, "Response not empty");
    //console.log(mission);

    this.assertEquals(mission.checkpoints.length, 13);
    this.assertEquals(mission.origin_icao, "KEYW");
    this.assertEquals(mission.destination_icao, "KMIA");
    this.assertEquals(mission.checkpoints[0].name, mission.origin_icao);
    this.assertEquals(mission.checkpoints[0].icao_region, "K7");
    this.assertEquals(mission.checkpoints[2].name, "CARNU");
    this.assertEquals(mission.checkpoints[2].icao_region, "K7");
    this.assertEquals(mission.checkpoints[3].name, "SNDBR");
    this.assertEquals(mission.checkpoints[3].icao_region, "K7");
    this.assertEquals(mission.checkpoints[mission.checkpoints.length - 1].name, mission.destination_icao);
    this.assertEquals(mission.conditions.wind_speed, 5);
    this.assertEquals(mission.conditions.wind_gusts, 0);
    this.assertEquals(mission.conditions.wind_direction, 190);
    this.assertEquals(mission.conditions.cloud.cover, 0);
    this.assertEquals(mission.conditions.cloud.height, 0);
  }

  testAeroflyStaticDestination(): void {
    this.group(SimBrief.name + ".testAeroflyStaticDestination()");
    const simBrief = new SimBrief();
    const simbriefPayload = fs.readFileSync("./src/Tests/fixtures/simbrief-api.json", "utf8");
    const simbriefPayloadJson = JSON.parse(simbriefPayload);

    const mission = simBrief.convertMission(simbriefPayloadJson, new Mission("TEST", "TEST"), true);
    this.assertEquals(mission.conditions.wind_speed, 8);
    this.assertEquals(mission.conditions.wind_gusts, 0);
    this.assertEquals(mission.conditions.wind_direction, 190);
    this.assertEquals(mission.conditions.cloud.cover, 0);
    this.assertEquals(mission.conditions.cloud.height, 0);
  }

  testAeroflyStatic2(): void {
    this.group(SimBrief.name + ".testAeroflyStatic2()");
    const simBrief = new SimBrief();
    const simbriefPayload = fs.readFileSync("./src/Tests/fixtures/simbrief-api2.json", "utf8");
    const simbriefPayloadJson = JSON.parse(simbriefPayload);

    const mission = simBrief.convertMission(simbriefPayloadJson, new Mission("TEST", "TEST"));
    this.assert(mission !== null, "Response not empty");

    this.assertEquals(mission.checkpoints.length, 9);
    this.assertEquals(mission.origin_icao, "KEYW");
    this.assertEquals(mission.destination_icao, "KMIA");
    this.assertEquals(mission.checkpoints[0].name, mission.origin_icao);
    this.assertEquals(mission.checkpoints[mission.checkpoints.length - 1].name, mission.destination_icao);
    this.assertEquals(mission.conditions.wind_speed, 10);
    this.assertEquals(mission.conditions.wind_gusts, 20);
    this.assertEquals(mission.conditions.wind_direction, 80);
    this.assertEquals(mission.conditions.cloud.cover, 0.125);
    this.assertEqualsRounded(mission.conditions.cloud.height, 1036, 0);
  }

  testAeroflyStaticDestination2(): void {
    this.group(SimBrief.name + ".testAeroflyStaticDestination2()");
    const simBrief = new SimBrief();
    const simbriefPayload = fs.readFileSync("./src/Tests/fixtures/simbrief-api2.json", "utf8");
    const simbriefPayloadJson = JSON.parse(simbriefPayload);

    const mission = simBrief.convertMission(simbriefPayloadJson, new Mission("TEST", "TEST"), true);
    this.assertEquals(mission.conditions.wind_speed, 9);
    this.assertEquals(mission.conditions.wind_gusts, 0);
    this.assertEquals(mission.conditions.wind_direction, 100);
    this.assertEquals(mission.conditions.cloud.cover, 0.125);
    this.assertEqualsRounded(mission.conditions.cloud.height, 762, 0);
  }
}
