text: /**
   * @file
   * Example 029: Apply brand to envelope
   * @author DocuSign
   */
  
  const path = require('path')
      , fs = require('fs-extra')
      , docusign = require('docusign-esign')
      , validator = require('validator')
      , dsConfig = require('../../config/index.js').config
      ;
  
  const eg029ApplyBrandToEnvelope = exports
      , eg = 'eg029' // This example reference
      , mustAuthenticate = '/ds/mustAuthenticate'
      , minimumBufferMin = 3
      , demoDocsPath = path.resolve(__dirname, '../../demo_documents')
      , doc2File = 'World_Wide_Corp_Battle_Plan_Trafalgar.docx'
      , doc3File = 'World_Wide_Corp_lorem.pdf'
      ;
  
  /**
   * Create the envelope
   * @param {object} req Request obj
   * @param {object} res Response obj
   */
  eg029ApplyBrandToEnvelope.createController = async (req, res) => {
      // Check the token
      // At this point we should have a good token. But we
      // double-check here to enable a better UX to the user
      let tokenOK = req.dsAuth.checkToken(minimumBufferMin);
      if (! tokenOK) {
          req.flash('info', 'Sorry, you need to re-authenticate.');
          // Save the current operation so it will be resumed after authentication
          req.dsAuth.setEg(req, eg);
          res.redirect(mustAuthenticate);
      }
  
      // Step 2. Call the worker method
      let body = req.body
          // Additional data validation might also be appropriate
        , signerEmail = validator.escape(body.signerEmail)
        , signerName = validator.escape(body.signerName)
        , brandId = validator.escape(body.brandId)
        , envelopeArgs = {
              signerEmail: signerEmail,
              signerName: signerName,
              brandId,
              status: "sent" }
        , args = {
              accessToken: req.user.accessToken,
              basePath: req.session.basePath,
              accountId: req.session.accountId,
              envelopeArgs: envelopeArgs
          }
        , results = null
        ;
  
      try {
          results = await eg029ApplyBrandToEnvelope.worker (args)
      }
      catch (error) {
          let errorBody = error && error.response && error.response.body
              // We can pull the DocuSign error code and message from the response body
            , errorCode = errorBody && errorBody.errorCode
            , errorMessage = errorBody && errorBody.message
            ;
          // In production, you may want to provide customized error messages and
          // remediation advice to the user
          res.render('pages/error', {err: error, errorCode: errorCode, errorMessage: errorMessage});
      }
      if (results) {
          req.session.envelopeId = results.envelopeId;
          // Save for use by other examples that need an envelopeId
          res.render('pages/example_done', {
              title: "Envelope sent",
              h1: "Envelope sent",
              message: `The envelope has been created and sent!<br/>Envelope ID ${results.envelopeId}.`
          });
      }
  }
  
  /**
   * This function does the work of creating the envelope
   */
  // ***DS.snippet.0.start
  eg029ApplyBrandToEnvelope.worker = async (args) => {
      // Data for this method
      // args.basePath
      // args.accessToken
      // args.accountId
  
      let dsApiClient = new docusign.ApiClient();
      dsApiClient.setBasePath(args.basePath);
  
      // Step 2. Construct your API headers
      dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
      let envelopesApi = new docusign.EnvelopesApi(dsApiClient)
        , results = null;
  
      // Step 3. Contstruct the request body
      let envelope = makeEnvelope(args.envelopeArgs)
  
      // Step 4. call the eSignature REST API
      // Exceptions will be caught by the calling function
      results = await envelopesApi.createEnvelope(args.accountId,
          {envelopeDefinition: envelope});
      let envelopeId = results.envelopeId;
  
      console.log(`Envelope was created. EnvelopeId ${envelopeId}`);
      return ({envelopeId: envelopeId})
  }
  
  /**
   * Creates envelope
   * @function
   * @param {Object} args parameters for the envelope
   * @returns {Envelope} An envelope definition
   * @private
   */
  function makeEnvelope(args){
      console.log(args.brandId)
      // Data for this method
      // args.signerEmail
      // args.signerName
      // args.brandId
      // args.status
      // demoDocsPath (module constant)
      // doc2File (module constant)
      // doc3File (module constant)
  
  
      // document 1 (html) has tag **signature_1**
      // document 2 (docx) has tag /sn1/
      // document 3 (pdf) has tag /sn1/
      //
      // The envelope has two recipients.
      // recipient 1 - signer
      // The envelope will be sent first to the signer
  
      let doc2DocxBytes, doc3PdfBytes;
      // Read files from a local directory
      // The reads could raise an exception if the file is not available!
      doc2DocxBytes = fs.readFileSync(path.resolve(demoDocsPath, doc2File));
      doc3PdfBytes = fs.readFileSync(path.resolve(demoDocsPath, doc3File));
  
      // Create the envelope definition
      let env = new docusign.EnvelopeDefinition();
      env.emailSubject = 'Please sign this document set';
  
      // Add the documents
      let doc1 = new docusign.Document()
        , doc1b64 = Buffer.from(document1(args)).toString('base64')
        , doc2b64 = Buffer.from(doc2DocxBytes).toString('base64')
        , doc3b64 = Buffer.from(doc3PdfBytes).toString('base64')
        ;
  
      doc1.documentBase64 = doc1b64;
      doc1.name = 'Order acknowledgement'; // Can be different from actual file name
      doc1.fileExtension = 'html'; // Source data format. Signed docs are always PDF
      doc1.documentId = '1'; // A label used to reference the doc
  
      // Alternate pattern: using constructors for docs 2 and 3...
      let doc2 = new docusign.Document.constructFromObject({
              documentBase64: doc2b64,
              name: 'Battle Plan', // Can be different from actual file name
              fileExtension: 'docx',
              documentId: '2'});
  
      let doc3 = new docusign.Document.constructFromObject({
              documentBase64: doc3b64,
              name: 'Lorem Ipsum', // Can be different from actual file name
              fileExtension: 'pdf',
              documentId: '3'});
  
      // The order in the docs array determines the order in the envelope
      env.documents = [doc1, doc2, doc3];
  
      // Create a signer recipient to sign the document, identified by name and email
      // We're setting the parameters via the object constructor
      let signer1 = docusign.Signer.constructFromObject({
          email: args.signerEmail,
          name: args.signerName,
          recipientId: '1',
          routingOrder: '1'});
      // routingOrder (lower means earlier) determines the order of deliveries
      // to the recipients. Parallel routing order is supported by using the
      // same integer as the order for two or more recipients
  
      // Create signHere fields (also known as tabs) on the documents,
      // We're using anchor (autoPlace) positioning
      //
      // The DocuSign platform searches throughout your envelope's
      // documents for matching anchor strings. So the
      // signHere2 tab will be used in both document 2 and 3 since they
      // use the same anchor string for their "signer 1" tabs
      let signHere1 = docusign.SignHere.constructFromObject({
          anchorString: '**signature_1**',
          anchorYOffset: '10', anchorUnits: 'pixels',
          anchorXOffset: '20'})
      , signHere2 = docusign.SignHere.constructFromObject({
          anchorString: '/sn1/',
          anchorYOffset: '10', anchorUnits: 'pixels',
          anchorXOffset: '20'})
      ;
  
      // Tabs are set per recipient/signer
      let signer1Tabs = docusign.Tabs.constructFromObject({
      signHereTabs: [signHere1, signHere2]});
      signer1.tabs = signer1Tabs;
  
      // Add the recipients to the envelope object
      let recipients = docusign.Recipients.constructFromObject({
      signers: [signer1]});
      env.recipients = recipients;
  
      // Request that the envelope be sent by setting status to "sent".
      // To request that the envelope be created as a draft, set status to "created"
      env.status = args.status;
      env.brandId = args.brandId;
  
      return env;
  }
  
  /**
   * Creates document 1
   * @function
   * @private
   * @param {Object} args parameters for the envelope
   * @returns {string} A document in HTML format
   */
  
  function document1(args) {
      // Data for this method
      // args.signerEmail
      // args.signerName
  
      return `
      <!DOCTYPE html>
      <html>
          <head>
            <meta charset="UTF-8">
          </head>
          <body style="font-family:sans-serif;margin-left:2em;">
          <h1 style="font-family: 'Trebuchet MS', Helvetica, sans-serif;
              color: darkblue;margin-bottom: 0;">World Wide Corp</h1>
          <h2 style="font-family: 'Trebuchet MS', Helvetica, sans-serif;
            margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;
            color: darkblue;">Order Processing Division</h2>
          <h4>Ordered by ${args.signerName}</h4>
          <p style="margin-top:0em; margin-bottom:0em;">Email: ${args.signerEmail}</p>
          <p style="margin-top:3em;">
    Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie. Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée. Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice. Donut jujubes oat cake jelly-o. Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.
          </p>
          <!-- Note the anchor tag for the signature field is in white. -->
          <h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
          </body>
      </html>
    `
    }
  // ***DS.snippet.0.end
  
  /**
   * Form page for this application
   */
  eg029ApplyBrandToEnvelope.getController = async (req, res) => {
      // Check that the authentication token is okay with a long buffer time.
      // If needed, now is the best time to ask the user to authenticate,
      // since they have not yet entered any information into the form
      let tokenOK = req.dsAuth.checkToken()
  
      if (tokenOK) {
          let dsApiClient = new docusign.ApiClient();
          dsApiClient.setBasePath(req.session.basePath);
          dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + req.user.accessToken);
  
          let brandApi = new docusign.AccountsApi(dsApiClient)
          brandsResponse = await brandApi.listBrands(req.session.accountId)
  
          res.render('pages/examples/eg029ApplyBrandToEnvelope', {
              eg: eg, csrfToken: req.csrfToken(),
              title: "Signing request by email",
              sourceFile: path.basename(__filename),
              sourceUrl: dsConfig.githubExampleUrl + 'eSignature/' + path.basename(__filename),
              documentation: dsConfig.documentation + eg,
              showDoc: dsConfig.documentation,
              brands: brandsResponse.brands || []
          });
      } else {
          // Save the current operation so it will be resumed after authentication
          req.dsAuth.setEg(req, eg);
          res.redirect(mustAuthenticate);
      }
  }
  