
const Message = require('./message');
const Edi = require('./edi');
const {segments, elements} = require("./iso16033");
const _ = require("lodash");

/** Order16033
 *  a parser for ORDERS according to ISO16033
 */
class Order16033 extends Message {
  constructor(){
    super('UNOC',segments,elements);

    this._currentNAD = undefined;
    // properties of the order 
    this.data = {
      lines: [],
      party: {}
    };
  }

  /**
   * reset must be call before interpreting a new message.
   */
  reset() {
    this.data = {
      messages: []
    };
  }
  
  segmentUNB(s) {
    this.expectVal(0,0,'UNOC');
    this.expectVal(0,1,'1');
  
    this.data.senderIdentification = s.val(1,0);
    this.data.recipientIdentification = s.val(2,0);
    this.data.dateOfPreparation = Edi.datetime(s.val(3));
    this.data.interchangeReference = s.val(4,0);
    this.data.applicationReference = s.val(6,0);
    this.data.testIndicator = s.val(9,0) || '0';
  
  }
  
  segmentUNH(s) {
    this._currentMessage = {lines:[],party:{}};
    this.data.messages.push(this._currentMessage);
    this._currentMessage.messageReferenceNumber = s.val(0,0);
    this._segmentNumberInMessage = 1;
    this._section = 'Header'; // or Detail or Summary  cf(https://service.unece.org/trade/untdid/d00a/trmd/orders_c.htm)
    this.expect(s.val(1,0),'ORDERS','message type identifier');
    this.expect(s.val(1,1),'D','message type version number');
    this.expect(s.val(1,2),'96B','message type release number');
    this.expect(s.val(1,3),'UN','controlling Agency');
    this.expect(s.val(1,4),'INFO32','association assigned code');
  };
  
  segmentDTM(s) {
    this.expect(s.val(0,0),'4','date time qualifier');
    this._currentMessage.dateOfOrder = Edi.datetime(s.val(0,1));
    this.expect(s.val(0,2),'203','date time format qualifier');
  };
  
  segmentBGM(s) {
    if (s.val(0,0) !== '105') {
      this.notImplemented('only purchase order (BGM+105) are implemented');
    }
    this._currentMessage.documentNumber = s.val(1,0);
    if (this._currentMessage.documentNumber === undefined) {
      this.unexpected('document number must be specified');
    }
  }
  
  
  segmentUNS(s){
    this.expect(s.val(0,0),'S');
    this._section = 'Summary'
    this._currentLine = undefined;
  }
  
  
  segmentNAD(s) {
    let nad = {};
    this.setProp(nad,'partyId',1,0);
    this.setProp(nad,'codeListQualifier',1,1);
    this.setProp(nad,'codeListResponsibleAgency',1,2);
    this.setProp(nad,'nameAndAddress',2);
    this.setProp(nad,'partyName',3);
    this.setProp(nad,'street',4);
    this.setProp(nad,'cityName',5,0);
    this.setProp(nad,'countrySubEntityDetails',6);
    this.setProp(nad,'postalIdentificationCode',7,0);
    this.setProp(nad,'countryNameCode',8,0);
    const partyQualifier = s.val(0,0);
    const context = this._currentLine || this._currentMessage;
    context.party = context.party || {};
    context.party[partyQualifier] = nad;
    this._currentNAD = nad;
    this._currentCTA = undefined;
  };

  // segment group 5 http://www.unece.org/fileadmin/DAM/trade/untdid/d01a/trmd/orders_c.htm#0220_X

  segmentCTA(s) {
    if (this._currentNAD === undefined){
      this.unexpected('got a CTA segment before any NAD.');
    }
    this._currentNAD.CTA = this._currentNAD.CTA || {};
    this._currentCTA = {};
    this.setProp(this._currentCTA,'departmentOrEmployee',1,1);
    this.setProp(this._currentCTA,'departmentOrEmployeeIdentification',1,0);
    this._currentNAD.CTA[s.val(0,0)] = this._currentCTA;
  }

  segmentCOM(s){
    if (this._currentCTA === undefined){
      this.unexpected('got a COM segment before any CTA.');
    }
    _.set(this._currentCTA,['COM',s.val(0,1)],s.val(0,0));
  }



  segmentRFF(s) {
    const context = this._currentLine || this._currentMessage;
    if (context === undefined) {
      this.unexpected('got a RFF segment out of a order message (BGM) or a line (LIN) context')
    }
    switch (s.val(0,0)) {
    case 'FI':
      this.expect(s.val(0,1),['3','4'],'Type of line must be either 3=contacto or 4=other (including solutions)');
      context.typeOfLine=s.val(0,1);
      break;
    
    case 'AEG':
      context.opticianReferenceNumber = s.val(0,1);
      break;
    default:
      this.notImplemented(`reference qualifier ${s.val(0,0)} of RFF`);
    }
    
  };
  
  segmentIMD(s) {
    this.expect(s.val(0,0),'F','item DescriptionCode must be "F"=Free form');
    this.expect(s.val(1,0),'8','item characteristic coded must be "8"= product');
    this._currentLine.itemDescription1 = s.val(2,3);
    this._currentLine.itemDescription2 = s.val(2,4);
  };
  
  segmentLIN(s) {
    if (this._section === 'Header') {
      this._section = 'Detail';
      this._announcedNumberOfLine = parseInt(s.val(0,0));
      this.expect(s.val(2,0),this._currentMessage.documentNumber,'plan number must equal document number');
      this.expect(s.val(3,0),'0','introduction line');
    }
    else {
      this._currentLine = {lineItemNumber:parseInt(s.val(0,0))};
      this._currentMessage.lines.push(this._currentLine);
      if (this._currentMessage.lines.length > this._announcedNumberOfLine) {
        this.unexpected(`announced number of lines was ${this._announcedNumberOfLine} and found line number LIN+${lineNr}`);
      }      
      this.setProp(this._currentLine,'actionCoded',1,0);
      this.setProp(this._currentLine,'itemNumber',2,0);
      this.setProp(this._currentLine,'itemNumberType',2,1);
      this.setProp(this._currentLine,'codeListQualifier',2,2);
      this.setProp(this._currentLine,'codeListResponsibleAgency',2,3);
      this.setProp(this._currentLine,'subLineIndicator',3,0);
      this.setProp(this._currentLine,'subLineItemNumber',3,1);
      this.setProp(this._currentLine,'configurationLevel',4,0);
      this.setProp(this._currentLine,'configuration',5,0);
    }
  }
  
  segmentPIA(s) {
    if (s.val(0,0) === '5') {
      this._currentLine.ItemNumber = s.val(1,0);
      this._currentLine.ItemNumberType = this.expect(s.val(1,1),['SA','EN'],`ItemNumberType`);
    }
    else if (s.val(0,0) === '1') {
      // nothing to do
    }
    else {
      this.notImplemented(`product qualifer != 5 or 1`);
    }
  }
  
  segmentQTY(s) {
    this.expect(s.val(0,0),'21','qualifier');
    this._currentLine.quantity = s.val(0,1)
    this.expect(s.val(0,2),'CU','measure unit qualifier');
  }
  
  segmentCCI(s) {
    this.expect(s.val(2,0),'ABO',`caracteristic`);
    this._currentCCI = s.val(2,3);
  }
  
  segmentMEA(s) {
    if (s.val(0,0) !== 'AAE') {
      this.notImplemented(`qualifier MEA+${s[0][0]}`);
    }
    this._currentLine[this._currentCCI] = s.val(2,1);
  }

  segmentMOA(s) {
    //TODO
  }

  segmentPRI(s) {
    //TODO
  }

  segmentCNT(s) {
    //TODO
  }
  
  segmentUNT(s){
    this.expect(parseInt(s.val(0,0)),this._segmentNumberInMessage,'number of segment in message');
    this.expect(s.val(1,0),this._currentMessage.messageReferenceNumber,'message reference number');
    this._currentLine = undefined;
    this._currentNAD = undefined;
    this._currentCCI = undefined;
  }
  
  segmentUNZ(s){
    this.expect(s.val(0,0),this.data.messages.length.toString(),'interchange message count must match the number of message');
    this.expect(s.val(1,0),this.data.interchangeReference,'interchange reference must match with UNB segment');
  }

}

module.exports = Order16033;
