export class BatteryLifeCalculator {
  timeRunSeconds: number;
  timeSleepSeconds: number;
  consumptionActiveMilliAmpHours: number;
  consumptionSleepMilliAmpHours: number;
  powerBatteryTotalMilliAmpHours: number;
  powerBatteryBufferBeforeEmptyPercent: number;

  constructor(
    timeRunSeconds: number,
    timeSleepSeconds: number,
    consumptionActiveMilliAmpHours: number,
    consumptionSleepMilliAmpHours: number,
    powerBatteryTotalMilliAmpHours: number,
    powerBatteryBufferBeforeEmptyPercent: number = 20
  ) {
    this.timeRunSeconds = timeRunSeconds;
    this.timeSleepSeconds = timeSleepSeconds;
    this.consumptionActiveMilliAmpHours = consumptionActiveMilliAmpHours;
    this.consumptionSleepMilliAmpHours = consumptionSleepMilliAmpHours;
    this.powerBatteryTotalMilliAmpHours = powerBatteryTotalMilliAmpHours;
    this.powerBatteryBufferBeforeEmptyPercent = powerBatteryBufferBeforeEmptyPercent;

    console.log(
      "The source of this battery calc is here: https://github.com/simonneutert/batterylife-calculator\nI was too lazy to make the math myself."
    );
  }

  // public API

  milliAmpToMicroAmp(milliAmps: number): number {
    return milliAmps * 1000;
  }

  microAmpToMilliAmp(milliAmps: number): number {
    return milliAmps * 0.001;
  }

  calculate(): {
    powerAveragePerHour: number;
    runtimeHoursEstimated: number;
    runtimeDaysEstimated: number;
    runtimeDaysRemainingHoursEstimated: number;
  } {
    return {
      powerAveragePerHour: this.powerEstimatedHourly(),
      runtimeHoursEstimated: this.runtimeHoursEstimated(),
      runtimeDaysEstimated: this.runtimeDaysEstimated(),
      runtimeDaysRemainingHoursEstimated: this.runtimeDaysRemainingHoursEstimated(),
    };
  }

  powerEstimatedHourly(): number {
    return this.calcPowerEst(
      this.powerRun(),
      this.consumptionActiveMilliAmpHours,
      this.powerSleep(),
      this.consumptionSleepMilliAmpHours
    );
  }

  runtimeHoursEstimated(): number {
    return parseInt((this.powerLipo() / this.powerEstimatedHourly()).toString(), 10);
  }

  runtimeDaysEstimated(): number {
    return parseInt((this.runtimeHoursEstimated() / 24).toString(), 10);
  }

  runtimeDaysRemainingHoursEstimated(): number {
    return parseInt((this.runtimeHoursEstimated() % 24).toString(), 10);
  }

  // private methods

  private roundOff(x: number): number {
    return Math.round(x * 100.0) / 100.0;
  }

  private calcPowerLipo(x: number, y: number): number {
    return parseFloat(((x * (100 - y)) / 100).toString());
  }

  private calcRuns(x: number, y: number): number {
    return parseFloat((60 / (x + y)).toString());
  }

  private calcRunsHour(x: number, y: number): number {
    return parseFloat((3600 / (x + y)).toString());
  }

  private calcPowerRun(x: number, y: number): number {
    return parseFloat(((x / (x + y)) * 3600).toString());
  }

  private calcPowerSleep(x: number, y: number): number {
    return parseFloat(((y / (x + y)) * 3600).toString());
  }

  powerLipo(): number {
    return this.calcPowerLipo(this.powerBatteryTotalMilliAmpHours, this.powerBatteryBufferBeforeEmptyPercent);
  }

  runs(): number {
    return this.calcRuns(this.timeRunSeconds, this.timeSleepSeconds);
  }

  runsHour(): number {
    return this.calcRunsHour(this.timeRunSeconds, this.timeSleepSeconds);
  }

  powerRun(): number {
    return this.calcPowerRun(this.timeRunSeconds, this.timeSleepSeconds);
  }

  powerSleep(): number {
    return this.calcPowerSleep(this.timeRunSeconds, this.timeSleepSeconds);
  }

  private calcPowerEst(a: number, b: number, c: number, d: number): number {
    return parseFloat(((a / 3600) * b + (c / 3600) * d).toString());
  }
}
