function Terminal(settings) {
  this.prefixChar = settings.prompt || "";
  this.cursorChar = settings.cursor || "|";
  this.target = settings.target;
  this.autoplay = settings.auto || true;
  this.position = -1;
  this.continue = true;
  var script = []
  var spans = this.target.querySelector(".history").getElementsByTagName("span")
  for (var i = 0; i < spans.length; i++) {
    var datavals = spans[i].dataset;
    var scriptNode = {};
    for (var key in datavals) {
      scriptNode[key] = datavals[key];
    }
    if (scriptNode.action) {
      script.push(scriptNode);
    }
  }

  this.script = script;
  this.target.innerHTML = "";

  var head = document.createElement("header")
  var button1 = document.createElement("div")
  button1.className = "button red"
  head.appendChild(button1);
  var button2 = document.createElement("div")
  button2.className = "button yellow"
  head.appendChild(button2);
  var button3 = document.createElement("div")
  button3.className = "button green"
  head.appendChild(button3);
  this.target.appendChild(head);

  var sect = document.createElement("section")
  sect.className = "terminal"
  var his = document.createElement("div")
  his.className = "history"
  sect.appendChild(his);
  var pre = document.createElement("span")
  pre.className = "prefix"
  sect.appendChild(pre);
  this.promptName = "prompt" + Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);

  var prom = document.createElement("span")
  prom.className = this.promptName
  sect.appendChild(prom);
  this.target.appendChild(sect);


  this.prompt = this.target.querySelector("." + this.promptName);
  this.prefix = this.target.querySelector(".prefix");
  this.history = this.target.querySelector(".history");

  this.MoveToHis = function(callback) {
    var history = this.history.innerHTML;
    if (this.script[this.position]["action"] == "prompt") {
      this.history.innerHTML = history + this.prefix.innerHTML + this.prompt.innerHTML + "<br>"
    } else {
      this.history.innerHTML = history + this.prefixChar + this.prompt.innerHTML + "<br>"
    }

    this.position = this.position + 1;
    this.prefix.innerHTML = this.prefixChar;
    this.prompt.textContent = "";
    callback()

  }

  this.TypeCallback = function() {
    if (this.position == -1) {
      this.position = this.position + 1;
      if (this.autoplay) {
        this.Play()
      }
      return
    }
    var bound = this.Play.bind(this);
    var hist = this.MoveToHis.bind(this);
    var delay = parseInt(this.script[this.position].delay) || 1000;
    setTimeout(function() {
      hist(bound)
    }, delay);
  }

  this.maketyper = function() {
    this.prefix.innerHTML = this.prefixChar;
    var bound = this.TypeCallback.bind(this);

    this.typer = new Typed("." + this.promptName, {
      strings: [""],
      cursorChar: this.cursorChar,
      typeSpeed: 30,
      onComplete: bound,
    })
    this.cursor = this.target.querySelector(".typed-cursor");

  }

  this.maketyper();

  this.Prompt = function() {
    this.prefix.innerHTML = this.script[this.position].prompt;
    this.cursor.textContent = "";
    this.typer.strings = this.script[this.position]["strings"].split(':;');
    this.typer.reset();

  }


  this.Print = function() {
    this.prefix.innerHTML = "";
    this.cursor.textContent = "";
    var history = this.history.innerHTML;
    this.history.innerHTML = history + this.script[this.position]["strings"] + "<br>"

    this.prompt.innerHTML;
    var bound = this.Play.bind(this);
    this.position = this.position + 1;

    section = this.target.querySelector("section");
    section.scrollBy(0, section.scrollTopMax)

    if (this.position < this.script.length) {
      setTimeout(bound, this.script[this.position - 1].delay || 0);
    }

  }

  this.Type = function() {
    this.prefix.html = this.prefixChar;
    this.cursor.textContent = "";
    this.typer.strings = this.script[this.position]["strings"].split(':;');
    this.typer.reset();

  }

  this.Empty = function() {
    this.prefix.html = this.prefixChar;
    this.cursor.textContent = "";
  }

  this.Test = function() {
    this.Step(2)
  }

  this.Step = function(pos) {
    this.continue = false
    this.position = pos;
    switch (this.script[this.position]["action"]) {
      case "type":
        this.Type()
        break;
      case "prompt":
        this.Prompt();
        break;
      case "print":
        this.Print();
        break;
    }
  }

  this.Restart = function() {
    this.position = 0;
    this.history.html("");
    this.Play();
  }

  this.Play = function() {
    // scroll to bottom of screen
    section = this.target.querySelector(".terminal");
    section.scrollBy(0, section.scrollTopMax)

    if (this.position >= this.script.length - 1) {
      this.position = 0;

      var bound = this.Restart.bind(this);

      setTimeout(bound, 15000);
      return;
    }

    if (this.continue) {
      switch (this.script[this.position]["action"]) {
        case "type":
          this.Type()
          break;
        case "prompt":
          this.Prompt();
          break;
        case "print":
          this.Print();
          break;
        case "empty":
          this.Empty();
          break;
      }
    }

  }
}