"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 Audit = require('./audit');
var Checkout = require('./checkout');
var FamilyReference = require('./family-reference');
var InventoryReference = require('./inventory-reference');
var Transfer = require('./transfer');
var Location = require('../core/location');
var Helper = require('../../helper/helper');
var UNITS_CONVERSION = require('../../constant/chemical/units-conversion.constant');
var UNITS = require('../../constant/chemical/units.constant');
var Container = /*#__PURE__*/function () {
  function Container(opt) {
    _classCallCheck(this, Container);
    this._id = new ObjectId();
    this.substance = {
      _id: null
    };
    this.family = null;
    this.inventory = null;
    this.location = null;
    this.size = null;
    this.amount = null;
    this.units = null;
    this.physicalState = null;
    this.type = null;
    this.openedDate = null;
    this.receivedDate = null;
    this.expirationDate = null;
    this.lastTestedDate = null;
    this.isPrivate = false;
    this.barcode = null;
    this.customBarcode = null;
    this.audits = [];
    this.tags = [];
    this.comments = null;
    this.checkout = null;
    this.normalizedSize = {
      gram: null,
      liter: null
    };
    this.normalizedAmount = {
      gram: null,
      liter: null
    };
    this.transfer = null;
    this.solvent = null;
    this.concentration = null;
    this.concentrationUnits = null;
    this.exemption = null;
    this.exemptionNotes = null;
    this.active = true;
    this.createdByUserId = null;
    if (opt) {
      this.fillObject(clone(opt));
    }
  }
  _createClass(Container, [{
    key: "fillObject",
    value: function fillObject(opt) {
      var _this = this;
      this._id = new ObjectId(opt._id);
      // eslint-disable-next-line no-underscore-dangle
      this._createdDate = this._id.getTimestamp();
      this.substance = {
        _id: opt.substance && opt.substance._id ? new ObjectId(opt.substance._id) : null,
        name: opt.substance && opt.substance.name ? opt.substance.name : null,
        vendor: opt.substance && opt.substance.vendor ? opt.substance.vendor : null
      };
      this.family = new FamilyReference(opt.family);
      this.inventory = new InventoryReference(opt.inventory);
      this.location = opt.location ? new Location(opt.location) : null;
      this.size = parseFloat(opt.size || 0, 10);
      this.amount = parseFloat(!isNaN(opt.amount) && opt.amount !== null ? opt.amount : opt.size, 10); // eslint-disable-line
      this.units = opt.units || null;
      this.physicalState = opt.physicalState || null;
      this.type = opt.type || null;
      this.openedDate = opt.openedDate ? new Date(opt.openedDate) : null;
      this.receivedDate = opt.receivedDate ? new Date(opt.receivedDate) : null;
      this.expirationDate = opt.expirationDate ? new Date(opt.expirationDate) : null;
      this.lastTestedDate = opt.lastTestedDate ? new Date(opt.lastTestedDate) : null;
      this.isPrivate = opt.isPrivate || false;
      this.barcode = opt.barcode || null;
      this.customBarcode = opt.customBarcode || null;
      this.comments = opt.comments || null;
      this.checkout = opt.checkout ? new Checkout(opt.checkout) : null;
      this.transfer = opt.transfer ? new Transfer(opt.transfer) : null;
      this.solvent = opt.solvent || null;
      this.concentration = opt.concentration ? parseFloat(opt.concentration) || null : null;
      this.concentrationUnits = opt.concentrationUnits || null;
      this.exemption = opt.exemption || null;
      this.exemptionNotes = opt.exemptionNotes || null;
      this.active = typeof opt.active === 'boolean' ? opt.active : this.active;
      this.createdByUserId = opt.createdByUserId;
      if (opt.audits) {
        this.audits = opt.audits.map(function (obj) {
          return new Audit(obj);
        });
      }
      if (opt.tags) {
        opt.tags.forEach(function (tag) {
          return _this.tags.push(tag);
        });
      }
      var _this$normalizeSizeAn = this.normalizeSizeAndAmount(this.size, this.amount, this.units, this.family.density && this.family.density.value ? this.family.density.value : 1),
        normalizedSize = _this$normalizeSizeAn.normalizedSize,
        normalizedAmount = _this$normalizeSizeAn.normalizedAmount;
      this.normalizedSize = normalizedSize;
      this.normalizedAmount = normalizedAmount;
    }
  }, {
    key: "validate",
    value: function validate() {
      var barcodePattern = Helper.getBarcodePattern(this.inventory);
      var validation = tv4.validateMultiple(this, Container.schema(barcodePattern));
      if (this.receivedDate && !Helper.validateDate(this.receivedDate)) {
        validation.valid = false;
        validation.errors.push(new Error('Received Date must be between the year 999 and 3000'));
      }
      if (this.openedDate && !Helper.validateDate(this.openedDate)) {
        validation.valid = false;
        validation.errors.push(new Error('Opened Date must be between the year 999 and 3000'));
      }
      if (this.expirationDate && !Helper.validateDate(this.expirationDate)) {
        validation.valid = false;
        validation.errors.push(new Error('Expiration Date must be between the year 999 and 3000'));
      }
      if (this.lastTestedDate && !Helper.validateDate(this.lastTestedDate)) {
        validation.valid = false;
        validation.errors.push(new Error('Last Tested Date Date must be between the year 999 and 3000'));
      }
      return validation;
    }

    // eslint-disable-next-line class-methods-use-this
  }, {
    key: "normalizeSizeAndAmount",
    value: function normalizeSizeAndAmount(size, amount, units) {
      var density = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
      var normalizedSize = {
        gram: null,
        liter: null
      };
      var normalizedAmount = {
        gram: null,
        liter: null
      };
      var conversion = UNITS_CONVERSION[units];
      if (conversion) {
        switch (conversion.type) {
          case 'mass':
            normalizedSize.gram = size * conversion.conversionFactor;
            normalizedSize.liter = size * conversion.conversionFactor * 0.001 / density; // eslint-disable-line
            normalizedAmount.gram = amount * conversion.conversionFactor;
            normalizedAmount.liter = amount * conversion.conversionFactor * 0.001 / density; // eslint-disable-line
            break;
          case 'volume':
            normalizedSize.gram = size * conversion.conversionFactor * density * 1000 || null;
            normalizedSize.liter = size * conversion.conversionFactor;
            normalizedAmount.gram = amount * conversion.conversionFactor * density * 1000 || null;
            normalizedAmount.liter = amount * conversion.conversionFactor;
            break;
          default:
            break;
        }
      }
      return {
        normalizedSize: normalizedSize,
        normalizedAmount: normalizedAmount
      };
    }
  }], [{
    key: "schema",
    value: function schema(pattern) {
      return {
        $schema: 'http://json-schema.org/draft-04/schema#',
        id: 'container.schema.json',
        type: 'object',
        properties: {
          _id: {
            type: 'object'
          },
          substance: {
            type: 'object'
          },
          family: {
            $ref: 'family-reference.schema.json'
          },
          inventory: {
            $ref: 'inventory-reference.schema.json'
          },
          location: {
            $ref: 'location.schema.json'
          },
          size: {
            type: 'number'
          },
          amount: {
            type: 'number'
          },
          normalizedSize: {
            type: 'object',
            properties: {
              gram: {
                type: ['number', 'null']
              },
              liter: {
                type: ['number', 'null']
              }
            }
          },
          normalizedAmount: {
            type: 'object',
            properties: {
              gram: {
                type: ['number', 'null']
              },
              liter: {
                type: ['number', 'null']
              }
            }
          },
          units: {
            "enum": UNITS.map(function (unit) {
              return unit.value;
            })
          },
          physicalState: {
            type: ['string', 'null']
          },
          type: {
            type: 'string'
          },
          openedDate: {
            type: ['object', 'null']
          },
          receivedDate: {
            type: ['object', 'null']
          },
          expirationDate: {
            type: ['object', 'null']
          },
          lastTestedDate: {
            type: ['object', 'null']
          },
          isPrivate: {
            type: 'boolean'
          },
          barcode: {
            type: ['string', 'null'],
            pattern: "".concat(pattern)
          },
          customBarcode: {
            type: ['string', 'null']
          },
          audits: {
            type: 'array',
            item: {
              type: 'object'
            }
          },
          tags: {
            type: 'array',
            item: {
              type: 'string'
            }
          },
          comments: {
            type: ['string', 'null']
          },
          solvent: {
            type: ['string', 'null']
          },
          concentration: {
            type: ['number', 'null']
          },
          concentrationUnits: {
            type: ['string', 'null']
          },
          exemption: {
            type: ['string', 'null']
          },
          exemptionNotes: {
            type: ['string', 'null']
          },
          active: {
            type: 'boolean'
          },
          createdByUserId: {
            type: ['string']
          },
          checkout: {
            anyOf: [{
              $ref: 'checkout.schema.json'
            }, {
              type: ['null']
            }]
          },
          transfer: {
            anyOf: [{
              $ref: 'transfer.schema.json'
            }, {
              type: ['null']
            }]
          }
        },
        required: Object.keys(new Container())
      };
    }
  }]);
  return Container;
}();
tv4.addSchema(FamilyReference.schema());
tv4.addSchema(InventoryReference.schema());
tv4.addSchema(Location.schema());
tv4.addSchema(Checkout.schema());
module.exports = Container;