text: const joi = require('joi');
  const {
    ALL_DOCUMENT_TYPES,
    ALL_EVENT_CODES,
    DOCUMENT_EXTERNAL_CATEGORIES_MAP,
    MAX_FILE_SIZE_MB,
  } = require('../EntityConstants');
  const {
    ExternalDocumentFactory,
  } = require('../externalDocument/ExternalDocumentFactory');
  const {
    joiValidationDecorator,
    validEntityDecorator,
  } = require('../JoiValidationDecorator');
  const {
    VALIDATION_ERROR_MESSAGES,
  } = require('../externalDocument/ExternalDocumentInformationFactory');
  const { JoiValidationConstants } = require('../JoiValidationConstants');
  
  DocketEntryFactory.VALIDATION_ERROR_MESSAGES = {
    ...VALIDATION_ERROR_MESSAGES,
    dateReceived: [
      {
        contains: 'must be less than or equal to',
        message: 'Received date cannot be in the future. Enter a valid date.',
      },
      'Enter a valid date received',
    ],
    documentTitle:
      'Document title must be 3000 characters or fewer. Update this document title and try again.',
    eventCode: 'Select a document type',
    filers: 'Select a filing party',
    lodged: 'Enter selection for filing status.',
    otherFilingParty: 'Enter other filing party name.',
    primaryDocumentFileSize: [
      {
        contains: 'must be less than or equal to',
        message: `Your document file size is too big. The maximum file size is ${MAX_FILE_SIZE_MB}MB.`,
      },
      'Your document file size is empty.',
    ],
    secondaryDocumentFile: 'A file was not selected.',
  };
  
  /**
   * @param {object} rawProps the raw docket entry data
   * @constructor
   */
  function DocketEntryFactory(rawProps) {
    /**
     * bare constructor for entity factory
     */
    function entityConstructor() {}
  
    entityConstructor.prototype.init = function init(rawPropsParam) {
      this.additionalInfo = rawPropsParam.additionalInfo;
      this.additionalInfo2 = rawPropsParam.additionalInfo2;
      this.addToCoversheet = rawPropsParam.addToCoversheet;
      this.attachments = rawPropsParam.attachments;
      this.certificateOfService = rawPropsParam.certificateOfService;
      this.certificateOfServiceDate = rawPropsParam.certificateOfServiceDate;
      this.dateReceived = rawPropsParam.dateReceived;
      this.documentTitle = rawPropsParam.documentTitle;
      this.documentType = rawPropsParam.documentType;
      this.eventCode = rawPropsParam.eventCode;
      this.filers = rawPropsParam.filers;
      this.freeText = rawPropsParam.freeText;
      this.hasOtherFilingParty = rawPropsParam.hasOtherFilingParty;
      this.hasSupportingDocuments = rawPropsParam.hasSupportingDocuments;
      this.isAutoGenerated = rawPropsParam.isAutoGenerated;
      this.isDocumentRequired = rawPropsParam.isDocumentRequired;
      this.lodged = rawPropsParam.lodged;
      this.objections = rawPropsParam.objections;
      this.ordinalValue = rawPropsParam.ordinalValue;
      this.otherFilingParty = rawPropsParam.otherFilingParty;
      this.partyIrsPractitioner = rawPropsParam.partyIrsPractitioner;
      this.partyPrivatePractitioner = rawPropsParam.partyPrivatePractitioner;
      this.previousDocument = rawPropsParam.previousDocument;
      this.primaryDocumentFile = rawPropsParam.primaryDocumentFile;
      this.primaryDocumentFileSize = rawPropsParam.primaryDocumentFileSize;
      this.secondaryDocumentFile = rawPropsParam.secondaryDocumentFile;
      this.serviceDate = rawPropsParam.serviceDate;
      this.trialLocation = rawPropsParam.trialLocation;
  
      const { secondaryDocument } = rawPropsParam;
      if (secondaryDocument) {
        this.secondaryDocument = ExternalDocumentFactory(secondaryDocument);
      }
    };
  
    let schema = joi.object().keys({
      addToCoversheet: joi.boolean(),
      additionalInfo: JoiValidationConstants.STRING.max(500),
      additionalInfo2: JoiValidationConstants.STRING.max(500),
      attachments: joi.boolean(),
      certificateOfService: joi.boolean(),
      dateReceived: JoiValidationConstants.ISO_DATE.max('now').required(),
      documentTitle: JoiValidationConstants.DOCUMENT_TITLE.optional(),
      documentType: JoiValidationConstants.STRING.valid(
        ...ALL_DOCUMENT_TYPES,
      ).optional(),
      eventCode: JoiValidationConstants.STRING.valid(
        ...ALL_EVENT_CODES,
      ).required(),
      freeText: JoiValidationConstants.STRING.optional(),
      hasOtherFilingParty: joi.boolean().optional(),
      hasSupportingDocuments: joi.boolean(),
      isAutoGenerated: joi.boolean().optional(),
      isDocumentRequired: joi.boolean().optional(),
      lodged: joi.boolean(),
      ordinalValue: JoiValidationConstants.STRING.optional(),
      otherFilingParty: JoiValidationConstants.STRING.when(
        'hasOtherFilingParty',
        {
          is: true,
          otherwise: joi.optional(),
          then: joi.required(),
        },
      ).description(
        'When someone other than the petitioner or respondent files a document, this is the name of the person who filed that document',
      ),
      previousDocument: joi.object().optional(),
      primaryDocumentFile: joi.object().when('isDocumentRequired', {
        is: true,
        otherwise: joi.optional(),
        then: joi.required(),
      }),
      primaryDocumentFileSize: JoiValidationConstants.MAX_FILE_SIZE_BYTES.when(
        'primaryDocumentFile',
        {
          is: joi.exist().not(null),
          otherwise: joi.optional().allow(null),
          then: joi.required(),
        },
      ),
      serviceDate: JoiValidationConstants.ISO_DATE.max('now').optional(),
      trialLocation: JoiValidationConstants.STRING.optional(),
    });
  
    let schemaOptionalItems = {
      certificateOfServiceDate:
        JoiValidationConstants.ISO_DATE.max('now').required(),
      filers: joi
        .array()
        .items(JoiValidationConstants.UUID.required())
        .required(),
      objections: JoiValidationConstants.STRING.required(),
      partyIrsPractitioner: joi.boolean().required(),
      partyPrivatePractitioner: joi.boolean().required(),
      secondaryDocumentFile: joi.object().optional(),
    };
  
    const addToSchema = itemName => {
      schema = schema.keys({
        [itemName]: schemaOptionalItems[itemName],
      });
    };
  
    const exDoc = ExternalDocumentFactory(rawProps);
    const docketEntryExternalDocumentSchema = exDoc.getSchema();
  
    schema = schema.concat(docketEntryExternalDocumentSchema).concat(
      joi.object({
        category: JoiValidationConstants.STRING.optional(), // omitting category
      }),
    );
  
    if (rawProps.certificateOfService === true) {
      addToSchema('certificateOfServiceDate');
    }
  
    const objectionDocumentTypes = [
      ...DOCUMENT_EXTERNAL_CATEGORIES_MAP['Motion'].map(entry => {
        return entry.documentType;
      }),
      'Motion to Withdraw Counsel (filed by petitioner)',
      'Motion to Withdraw as Counsel',
      'Application to Take Deposition',
    ];
  
    if (
      objectionDocumentTypes.includes(rawProps.documentType) ||
      (['AMAT', 'ADMT'].includes(rawProps.eventCode) &&
        objectionDocumentTypes.includes(rawProps.previousDocument.documentType))
    ) {
      addToSchema('objections');
    }
  
    if (
      rawProps.scenario &&
      rawProps.scenario.toLowerCase().trim() === 'nonstandard h'
    ) {
      addToSchema('secondaryDocumentFile');
    }
  
    if (
      rawProps.filers.length === 0 &&
      rawProps.partyIrsPractitioner !== true &&
      rawProps.partyPrivatePractitioner !== true &&
      rawProps.hasOtherFilingParty !== true &&
      !rawProps.isAutoGenerated
    ) {
      addToSchema('filers');
    }
  
    joiValidationDecorator(
      entityConstructor,
      schema,
      DocketEntryFactory.VALIDATION_ERROR_MESSAGES,
    );
  
    return new (validEntityDecorator(entityConstructor))(rawProps);
  }
  
  module.exports = { DocketEntryFactory };
  