"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
var ObjectId = require('bson').ObjectID;
var clone = require('clone');
var tv4 = require('tv4');
var AcuteToxicity = require('./acuteToxicity');
var Dot = require('./dot');
var FamilyBand = require('./family-band');
var Flag = require('./flag');
var Ghs = require('./ghs');
var HealthSymptoms = require('./health-symptoms');
var Nfpa = require('./nfpa');
var Storage = require('./storage');
var SubstanceComponent = require('./substance-component');
var SubstanceIdentifier = require('./substance-identifier');
var Substance = require('./substance');
var InventoryReference = require('./inventory-reference');
var FileReference = require('../procedure/file-reference');
var Family = /*#__PURE__*/function () {
  function Family(opt) {
    _classCallCheck(this, Family);
    this._id = null;
    this.hash = null;
    this.identifiers = new SubstanceIdentifier();
    this.appearance = null;
    this.attachments = [];
    this.bands = [];
    this.boilingPoint = {
      min: null,
      max: null,
      unit: null
    };
    this.components = [];
    this.density = {
      value: null,
      unit: null
    };
    this.description = null;
    this.dot = new Dot();
    this.firstAid = new HealthSymptoms();
    this.flags = [];
    this.flashPoint = {
      value: null,
      unit: null
    };
    this.form = null;
    this.formAtNtp = null;
    this.formNormalize = null;
    this.formula = null;
    this.ghs = [];
    this.inventory = null;
    this.healthSymptoms = new HealthSymptoms();
    this.inChi = null;
    this.inChiKey = null;
    this.isDataVerified = false;
    this.isFamilyVerified = false;
    this.iupacName = null;
    this.meltingPoint = {
      min: null,
      max: null,
      unit: null
    };
    this.molecularWeight = {
      value: null,
      unit: null
    };
    this.name = null;
    this.nfpa = new Nfpa();
    this.pH = null;
    this.pictograms = [];
    this.scope = null;
    this.shelfLife = null;
    this.smiles = null;
    this.storage = new Storage();
    this.synonyms = [];
    this.substances = [];
    this.sds = {
      activeBurnTimeBenchScale: {
        value: null,
        unit: null
      },
      activeBurnTimeIntermediateScale: {
        value: null,
        unit: null
      },
      acuteToxicity: [],
      composition: null,
      criticalPoint: {
        temperature: {
          value: null,
          unit: null
        },
        pressure: {
          value: null,
          unit: null
        }
      },
      dangerousGoodsDivision: [],
      decompositionInformation: null,
      diameterMetricParticle: {
        value: null,
        unit: null
      },
      evolvesToxicGas: false,
      flammabilityLimit: {
        lower: null,
        upper: null
      },
      heatOfMixing: {
        value: null,
        unit: null
      },
      ignitionPoint: {
        min: null,
        max: null,
        unit: null
      },
      instantaneousPowerDensity: {
        value: null,
        unit: null
      },
      maximumMassLossRate: {
        value: null,
        unit: null
      },
      particleDensity: {
        value: null,
        unit: null
      },
      particleSize: {
        min: null,
        max: null,
        unit: null
      },
      peakConvectionHeatRelease: {
        value: null,
        unit: null
      },
      rateOfBurn: {
        value: null,
        unit: null
      },
      rateOfEvolutionOfFlammableGas: {
        oneMinute: {
          value: null,
          unit: null
        },
        oneHour: {
          value: null,
          unit: null
        }
      },
      skinCorrosion: null,
      // 4hr rabbit skin corrosion test OECD Guideline 40
      vaporPressure: {
        temperature: {
          value: null,
          unit: null
        },
        pressure: {
          value: null,
          unit: null
        }
      },
      vaporDensity: null
    };
    if (opt) {
      this.fillObject(clone(opt));
    }
  }
  _createClass(Family, [{
    key: "fillObject",
    value: function fillObject(opt) {
      var _this = this;
      Object.keys(this).forEach(function (prop) {
        if (_this[prop]) {
          Object.assign(_this[prop], opt[prop]);
        } else {
          _this[prop] = opt[prop] || null;
        }
      });
      this._id = new ObjectId(opt._id);
      this.sds.acuteToxicity = opt.sds && Array.isArray(opt.sds.acuteToxicity) ? opt.sds.acuteToxicity.map(function (item) {
        return new AcuteToxicity(item);
      }) : [];
      this.sds.dangerousGoodsDivision = opt.sds && opt.sds.dangerousGoodsDivision ? opt.sds.dangerousGoodsDivision : [];
      this.attachments = opt.attachments && opt.attachments.length ? opt.attachments.map(function (item) {
        return new FileReference(item);
      }) : [];
      this.bands = Array.isArray(opt.bands) ? opt.bands.map(function (band) {
        return new FamilyBand(band);
      }) : [];
      this.components = Array.isArray(opt.components) ? opt.components.map(function (item) {
        return new SubstanceComponent(item);
      }) : [];
      if (!this.density.value && this.formNormalize === 'GAS' && this.molecularWeight.value) {
        // P = 1 atm
        // T = 293.15 K
        // R = 8.20578 X 10-2 L atm K-1 mol-1
        this.density = {
          value: this.molecularWeight.value / (0.0825078 * 293.15 * 1000),
          // d = PM/RT * 1L / 1000mL
          unit: 'g/mL'
        };
      }
      this.dot = new Dot(opt.dot);
      this.firstAid = new HealthSymptoms(opt.firstAid);
      this.flags = Array.isArray(opt.flags) ? opt.flags.map(function (flag) {
        return new Flag(flag);
      }) : [];
      this.ghs = Array.isArray(opt.ghs) ? opt.ghs.map(function (item) {
        return new Ghs(item);
      }) : [];
      this.inventory = opt.inventory ? new InventoryReference(opt.inventory) : null;
      this.hash = this.hash || this._id.toString();
      this.healthSymptoms = new HealthSymptoms(opt.healthSymptoms);
      this.identifiers = new SubstanceIdentifier(opt.identifiers);
      this.isDataVerified = opt.isDataVerified || false;
      this.isFamilyVerified = opt.isFamilyVerified || false;
      this.nfpa = new Nfpa(opt.nfpa);
      this.pH = opt.pH ? parseFloat(opt.pH, 10) : null;
      this.storage = new Storage(opt.storage);
      this.substances = Array.isArray(opt.substances) ? opt.substances.map(function (item) {
        return new Substance(item);
      }) : [];
      if (!this.formAtNtp && this.formNormalize) {
        this.formAtNtp = this.formNormalize;
      }
    }
  }, {
    key: "validate",
    value: function validate() {
      return tv4.validateMultiple(this, Family.schema());
    }
  }], [{
    key: "schema",
    value: function schema() {
      var family = new Family();
      var requiredFamily = Object.keys(family);
      var requiredSds = Object.keys(family.sds);
      var minMaxSchema = {
        type: 'object',
        properties: {
          min: {
            type: ['null', 'number']
          },
          max: {
            type: ['null', 'number']
          },
          unit: {
            type: ['null', 'string']
          }
        },
        required: ['min', 'max', 'unit']
      };
      var valueUnitSchema = {
        type: 'object',
        properties: {
          value: {
            type: ['number', 'null']
          },
          unit: {
            type: ['string', 'null']
          }
        },
        required: ['value', 'unit']
      };
      return {
        $schema: 'http://json-schema.org/draft-04/schema#',
        id: 'family.schema.json',
        type: 'object',
        properties: {
          _id: {
            type: 'object'
          },
          hash: {
            type: 'string'
          },
          identifiers: {
            $ref: 'substance-identifier.schema.json'
          },
          appearance: {
            type: ['string', 'null']
          },
          attachments: {
            type: 'array',
            item: {
              $ref: 'file-reference.schema.json'
            }
          },
          bands: {
            type: 'array',
            item: {
              $ref: 'family-band.schema.json'
            }
          },
          boilingPoint: minMaxSchema,
          components: {
            type: 'array',
            item: {
              $ref: 'substance-component.schema.json'
            }
          },
          density: valueUnitSchema,
          description: {
            type: ['string', 'null']
          },
          dot: {
            $ref: 'dot.schema.json'
          },
          flags: {
            type: 'array',
            item: {
              $ref: 'flag.schema.json'
            }
          },
          flashPoint: valueUnitSchema,
          firstAid: {
            $ref: 'health-symptoms.schema.json'
          },
          form: {
            type: ['string', 'null']
          },
          formAtNtp: {
            type: ['string', 'null']
          },
          formNormalize: {
            type: ['string', 'null']
          },
          formula: {
            type: ['string', 'null']
          },
          ghs: {
            type: 'array',
            item: {
              $ref: 'ghs.schema.json'
            }
          },
          healthSymptoms: {
            $ref: 'health-symptoms.schema.json'
          },
          inChi: {
            type: ['string', 'null']
          },
          inChiKey: {
            type: ['string', 'null']
          },
          inventory: {
            anyOf: [{
              type: ['null']
            }, {
              $ref: 'inventory-reference.schema.json'
            }]
          },
          isDataVerified: {
            type: 'boolean'
          },
          isFamilyVerified: {
            type: 'boolean'
          },
          iupacName: {
            type: ['string', 'null']
          },
          meltingPoint: minMaxSchema,
          molecularWeight: valueUnitSchema,
          name: {
            type: ['string', 'null']
          },
          nfpa: {
            $ref: 'nfpa.schema.json'
          },
          packaging: {
            type: ['string', 'null']
          },
          pH: {
            type: ['number', 'null']
          },
          pictograms: {
            type: 'array',
            item: {
              type: 'string'
            }
          },
          sds: {
            type: 'object',
            properties: {
              activeBurnTimeBenchScale: valueUnitSchema,
              // 30g bench scale exposure test
              activeBurnTimeIntermediateScale: valueUnitSchema,
              // intermediate scale exposure test
              acuteToxicity: {
                type: 'array',
                item: {
                  $ref: 'acute-toxicity.schema.json'
                }
              },
              composition: {
                type: ['string', 'null']
              },
              criticalPoint: {
                type: 'object',
                properties: {
                  temperature: valueUnitSchema,
                  pressure: valueUnitSchema
                }
              },
              dangerousGoodsDivision: {
                type: 'array',
                item: {
                  type: 'string'
                }
              },
              diameterMetricParticle: valueUnitSchema,
              decompositionInformation: {
                type: ['string', 'null']
              },
              evolvesToxicGas: {
                type: 'boolean'
              },
              flammabilityLimit: {
                type: 'object',
                properties: {
                  lower: {
                    type: ['number', 'null']
                  },
                  upper: {
                    type: ['number', 'null']
                  }
                }
              },
              heatOfMixing: valueUnitSchema,
              ignitionPoint: minMaxSchema,
              instantaneousPowerDensity: valueUnitSchema,
              maximumMassLossRate: valueUnitSchema,
              particleDensity: valueUnitSchema,
              particleSize: minMaxSchema,
              peakConvectionHeatRelease: valueUnitSchema,
              rateOfBurn: valueUnitSchema,
              rateOfEvolutionOfFlammableGas: {
                type: 'object',
                properties: {
                  oneMinute: valueUnitSchema,
                  oneHour: valueUnitSchema
                }
              },
              skinCorrosion: {
                type: ['string', 'null']
              },
              vaporPressure: {
                type: 'object',
                properties: {
                  temperature: valueUnitSchema,
                  pressure: valueUnitSchema
                }
              },
              vaporDensity: {
                type: ['number', 'null']
              }
            },
            required: requiredSds
          },
          scope: {
            type: ['string', 'null']
          },
          shelfLife: {
            type: ['number', 'null']
          },
          smiles: {
            type: ['string', 'null']
          },
          storage: {
            $ref: 'storage.schema.json'
          },
          synonyms: {
            type: 'array',
            item: {
              type: 'string'
            }
          },
          substances: {
            type: 'array',
            item: {
              $ref: 'substance-reference.schema.json'
            }
          }
        },
        required: requiredFamily
      };
    }
  }]);
  return Family;
}();
tv4.addSchema(AcuteToxicity.schema());
tv4.addSchema(Dot.schema());
tv4.addSchema(FamilyBand.schema());
tv4.addSchema(Flag.schema());
tv4.addSchema(Ghs.schema());
tv4.addSchema(HealthSymptoms.schema());
tv4.addSchema(InventoryReference.schema());
tv4.addSchema(Nfpa.schema());
tv4.addSchema(Storage.schema());
tv4.addSchema(SubstanceComponent.schema());
tv4.addSchema(SubstanceIdentifier.schema());
tv4.addSchema(Substance.schema());
tv4.addSchema(FileReference.schema());
module.exports = Family;