text: 'use strict';
  var _ = require('lodash');
  var util = require('./readline');
  var cliWidth = require('cli-width');
  var stripAnsi = require('strip-ansi');
  var stringWidth = require('string-width');
  
  function height(content) {
    return content.split('\n').length;
  }
  
  function lastLine(content) {
    return _.last(content.split('\n'));
  }
  
  class ScreenManager {
    constructor(rl) {
      // These variables are keeping information to allow correct prompt re-rendering
      this.height = 0;
      this.extraLinesUnderPrompt = 0;
  
      this.rl = rl;
    }
  
    render(content, bottomContent, changedPrompt) {
      this.rl.output.unmute();
      this.clean(this.extraLinesUnderPrompt);
  
      /**
       * Write message to screen and setPrompt to control backspace
       */
  
      var promptLine = changedPrompt ? changedPrompt : lastLine(content);
      var rawPromptLine = stripAnsi(promptLine);
  
      // Remove the rl.line from our prompt. We can't rely on the content of
      // rl.line (mainly because of the password prompt), so just rely on it's
      // length.
      var prompt = rawPromptLine;
      if (this.rl.line.length) {
        prompt = prompt.slice(0, -this.rl.line.length);
      }
      this.rl.setPrompt(prompt);
  
      // SetPrompt will change cursor position, now we can get correct value
      var cursorPos = this.rl._getCursorPos();
      var width = this.normalizedCliWidth();
  
      content = this.forceLineReturn(content, width);
      if (bottomContent) {
        bottomContent = this.forceLineReturn(bottomContent, width);
      }
      // Manually insert an extra line if we're at the end of the line.
      // This prevent the cursor from appearing at the beginning of the
      // current line.
      if (rawPromptLine.length % width === 0) {
        content += '\n';
      }
      var fullContent = content + (bottomContent ? '\n' + bottomContent : '');
      this.rl.output.write(fullContent);
  
      /**
       * Re-adjust the cursor at the correct position.
       */
  
      // We need to consider parts of the prompt under the cursor as part of the bottom
      // content in order to correctly cleanup and re-render.
      var promptLineUpDiff = Math.floor(rawPromptLine.length / width) - cursorPos.rows;
      var bottomContentHeight =
        promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
      if (bottomContentHeight > 0) {
        util.up(this.rl, bottomContentHeight);
      }
  
      // Reset cursor at the beginning of the line
      util.left(this.rl, stringWidth(lastLine(fullContent)));
  
      // Adjust cursor on the right
      if (cursorPos.cols > 0) {
        util.right(this.rl, cursorPos.cols);
      }
  
      /**
       * Set up state for next re-rendering
       */
      this.extraLinesUnderPrompt = bottomContentHeight;
      this.height = height(fullContent);
  
      this.rl.output.mute();
    }
  
    clean(extraLines) {
      if (extraLines > 0) {
        util.down(this.rl, extraLines);
      }
      util.clearLine(this.rl, this.height);
    }
  
    done() {
      this.rl.setPrompt('');
      this.rl.output.unmute();
      this.rl.output.write('\n');
    }
  
    releaseCursor() {
      if (this.extraLinesUnderPrompt > 0) {
        util.down(this.rl, this.extraLinesUnderPrompt);
      }
    }
  
    normalizedCliWidth() {
      var width = cliWidth({
        defaultWidth: 80,
        output: this.rl.output
      });
      return width;
    }
  
    breakLines(lines, width) {
      // Break lines who're longer than the cli width so we can normalize the natural line
      // returns behavior across terminals.
      width = width || this.normalizedCliWidth();
      var regex = new RegExp('(?:(?:\\033[[0-9;]*m)*.?){1,' + width + '}', 'g');
      return lines.map(line => {
        var chunk = line.match(regex);
        // Last match is always empty
        chunk.pop();
        return chunk || '';
      });
    }
  
    forceLineReturn(content, width) {
      width = width || this.normalizedCliWidth();
      return _.flatten(this.breakLines(content.split('\n'), width)).join('\n');
    }
  }
  
  module.exports = ScreenManager;
  