import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/pond";
import { or } from "utils/types";
import { cloneDeep } from "lodash";
import { Component } from "models";
import { describeMeasurement } from "pbHelpers/MeasurementDescriber";

export class Pressure {
  public settings: pond.ComponentSettings = pond.ComponentSettings.create();
  public status: pond.ComponentStatus = pond.ComponentStatus.create();
  public pascals: number = 0;
  public fanId: number = 0;

  public static create(comp: Component): Pressure {
    let my = new Pressure();
    my.settings = comp.settings;
    my.status = comp.status ? comp.status : pond.ComponentStatus.create();
    my.fanId = comp.settings.fanId;
    //getting the value from the unitmeasurements in status instead of the old style measurements in the status
    if (comp.status.measurement.length > 0) {
      comp.status.measurement.forEach(um => {
        if (um.values[0] && um.values[0].values.length > 0) {
          if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE) {
            my.pascals = um.values[0].values[0];
          }
          //TODO-CS: could expand this to have the fan cfm in the pressure model as well
          // if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_CFM){
          //   my.fanCFM = um.values[0].values[0]
          // }
        }
      });
    } else {
      //if no unit measurements in status use the old measurements in status
      let pre = comp.status?.lastMeasurement?.measurement?.pressure?.pascals;
      if (pre) {
        my.pascals = pre;
      }
    }
    return my;
  }

  public static createPond(comp: pond.Component): Pressure {
    let my = new Pressure();
    my.settings = comp.settings ? comp.settings : pond.ComponentSettings.create();
    my.status = comp.status ? comp.status : pond.ComponentStatus.create();
    //getting the value from the unitmeasurement part of the component instead of the old style measurements in the status
    if (comp.lastMeasurement.length > 0) {
      comp.lastMeasurement.forEach(um => {
        if (um.values[0] && um.values[0].values[0]) {
          if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE) {
            my.pascals = um.values[0].values[0];
          }
          //TODO-CS: could expand this to have the fan cfm in the pressure model as well
          // if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_CFM){
          //   my.fanCFM = um.values[0].values[0]
          // }
        }
      });
    } else {
      //if last measurements is not in the component from the pond use the status measurement
      let pre = comp.status?.lastMeasurement?.measurement?.pressure?.pascals;
      if (pre) {
        my.pascals = pre;
      }
    }
    return my;
  }

  public static any(data: any): Pressure {
    let comp = pond.Component.fromObject(cloneDeep(data));
    let my = Pressure.createPond(comp);
    let pre = comp.status?.lastMeasurement?.measurement?.pressure?.pascals;
    if (pre) {
      my.pascals = pre;
    }
    return my;
  }

  public update(other: Pressure) {
    this.settings = other.settings;
    this.status = other.status;
  }

  public static colour() {
    return describeMeasurement(
      quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE,
      quack.ComponentType.COMPONENT_TYPE_PRESSURE
    ).colour();
  }

  public name(): string {
    return this.settings.name !== "" ? this.settings.name : "Component " + this.key();
  }

  public key(): string {
    return this.settings.key;
  }

  public location(): quack.ComponentID {
    return quack.ComponentID.fromObject({
      type: this.settings.type,
      addressType: this.settings.addressType,
      address: this.settings.address
    });
  }

  public locationString(): string {
    return (
      or(this.settings.type, 0).toString() +
      "-" +
      or(this.settings.addressType, 0).toString() +
      "-" +
      or(this.settings.address, 0).toString()
    );
  }

  public type(): quack.ComponentType {
    return this.settings.type;
  }

  public subType(): number {
    return this.settings.subtype;
  }

  public getPressureString(unit = pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER): string {
    let p: number = this.pascals;
    let unitString: string = "Pa";
    if (unit === pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER) {
      unitString = "iwg";
      p = p / 249;
    }
    if (unit === pond.PressureUnit.PRESSURE_UNIT_KILOPASCALS) {
      unitString = "kPa";
      p = p / 1000;
    }
    return p.toFixed(2) + unitString;
  }

  public asComponent(): Component {
    let c = Component.create();
    c.settings = this.settings;
    c.status = this.status;
    return c;
  }
}
