const { ObjectId } = require('bson');
const tv4 = require('tv4');
const clone = require('clone');

const LineItem = require('./line-item');

const PersonReference = require('../core/person-reference');

class PurchaseOrder {
  constructor(opt) {
    this._id = null;
    this.purchaseOrderNumber = null;
    this.createdDate = null;
    this.revisionDate = null;
    this.priority = null;
    this.items = [];
    this.supplier = {
      id: null,
      name: null,
      number: null,
    };
    this.orderedBy = null;
    this.shippingInfo = {
      address: null,
      city: null,
      state: null,
      postalCode: null,
      country: null,
    };
    this.billingInfo = {
      name: null,
      address: null,
      city: null,
      state: null,
      postalCode: null,
      country: null,
    };
    this.organizationCodes = [];
    this.deptCodes = [];
    this.speedtype = null;
    this.chartstring = null;

    if (opt) {
      this.fillObject(clone(opt));
    }
  }

  fillObject(opt) {
    this._id = new ObjectId(opt._id);
    this.purchaseOrderNumber = opt.purchaseOrderNumber || null;
    this.createdDate = opt.createdDate ? new Date(opt.createdDate) : null;
    this.revisionDate = opt.revisionDate ? new Date(opt.revisionDate) : null;
    this.priority = opt.priority || null;
    this.supplier = {
      id: opt.supplier && opt.supplier.id ? opt.supplier.id : null,
      name: opt.supplier && opt.supplier.name ? opt.supplier.name : null,
      number: opt.supplier && opt.supplier.number ? opt.supplier.number : null,
    };
    this.orderedBy = opt.orderedBy ? new PersonReference(opt.orderedBy) : null;
    this.shippingInfo = {
      address: opt.shippingInfo && opt.shippingInfo.address ? opt.shippingInfo.address : [],
      city: opt.shippingInfo && opt.shippingInfo.city ? opt.shippingInfo.city : null,
      state: opt.shippingInfo && opt.shippingInfo.state ? opt.shippingInfo.state : null,
      postalCode: opt.shippingInfo && opt.shippingInfo.postalCode ? opt.shippingInfo.postalCode : null,
      country: opt.shippingInfo && opt.shippingInfo.country ? opt.shippingInfo.country : null,
    };
    this.billingInfo = {
      name: opt.billingInfo && opt.billingInfo.name ? opt.billingInfo.name : null,
      address: opt.billingInfo && opt.billingInfo.address ? opt.billingInfo.address : [],
      city: opt.billingInfo && opt.billingInfo.city ? opt.billingInfo.city : null,
      state: opt.billingInfo && opt.billingInfo.state ? opt.billingInfo.state : null,
      postalCode: opt.billingInfo && opt.billingInfo.postalCode ? opt.billingInfo.postalCode : null,
      country: opt.billingInfo && opt.billingInfo.country ? opt.billingInfo.country : null,
    };
    this.organizationCodes = opt.organizationCodes ? opt.organizationCodes : [];
    this.deptCodes = opt.deptCodes ? opt.deptCodes : [];
    this.speedtype = opt.speedtype || null;
    this.chartstring = opt.chartstring || null;

    if (opt.items) {
      this.items = opt.items.map((item) => new LineItem(item));
    }
  }

  validate() {
    return tv4.validateMultiple(this, PurchaseOrder.schema());
  }

  static schema() {
    return {
      $schema: 'http://json-schema.org/draft-04/schema#',
      id: 'purchase-order.schema.json',
      type: 'object',
      additionalProperties: false,
      properties: {
        _id: { type: 'object' },
        purchaseOrderNumber: { type: 'string' },
        createdDate: { type: 'object' },
        priority: { type: 'string' },
        items: { anyOf: [{ $ref: 'line-item.schema.json' }, { type: ['null'] }] },
        supplier: { type: 'object' },
        orderedBy: { $ref: 'person-reference.schema.json' },
        shippingInfo: { type: ['object', 'null'] },
        billingInfo: { type: ['object', 'null'] },
      },
      required: ['_id', 'createdDate', 'items'],
    };
  }
}

tv4.addSchema(LineItem.schema());
tv4.addSchema(PersonReference.schema());

module.exports = PurchaseOrder;
