// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// The MessageLog class manages the storage and display of all log messages in
// the debug console.
//
// Two primary components are used:
// 1. A buffer containing all the messages, MessageBuffer. This typically
//    contains many more messages than can be displayed on a single screen.
// 2. An HTML container filled with elements for each message. This container
//    is passed in to the MessageLog constructor.
//
// The MessageLog class creates a MessageBuffer object to contain the
// messages, and populates the HTML container to display the paginated
// messages. Each HTML element is not created until the corresponding message
// needs to be displayed, so if the debug console is initially invisible,
// no HTML nodes will be created until it becomes visible.

// Constructor for a single entry in the message buffer.
function BufferEntry(severity, message) {
  this.severity = severity;
  this.message = message;
  this.element = null;
}

// Constructor for the actual buffer used to store messages.
// This is implemented as a simple circular buffer of BufferEntry objects.
function MessageBuffer() {
  // The maximum number of entries that can be stored. Not all of these will
  // be simultaneously displayed.
  this.MAX_BUFFER_SIZE = 500;
  // Array of BufferEntry objects, used as a circular buffer.
  this.entries = [];
  // Current buffer insert position.
  this.insertPos = 0;
  // Current number of items in the buffer.
  this.size = 0;
}

// Add a new item to the message buffer at the current insert point.
MessageBuffer.prototype.insert = function(bufferEntry) {
  this.entries[this.insertPos] = bufferEntry;
  if (this.size < this.MAX_BUFFER_SIZE) {
    this.size += 1;
  }
  // Increment insert position with wraparound.
  this.insertPos = (this.insertPos + 1) % this.MAX_BUFFER_SIZE;
}

// Get an item from the message buffer at a logical index, where 0 corresponds
// to the last inserted item, and index N is the Nth last item to be inserted.
MessageBuffer.prototype.get = function(index) {
  if (index >= this.size) {
    return null;
  }
  // The index parameter is relative to the current insert position.
  var offsetIndex = (this.insertPos - 1 - index);
  // Buffer wraparound
  while (offsetIndex < 0) {
    offsetIndex += this.MAX_BUFFER_SIZE;
  }
  offsetIndex = offsetIndex % this.MAX_BUFFER_SIZE;
  return this.entries[offsetIndex];
}

// Constructor for the message log object itself.
function MessageLog(messageContainer) {
  // Log levels defined by the 'level' property of LogEntry
  // https://chromedevtools.github.io/devtools-protocol/1-3/Log#type-LogEntry
  this.VERBOSE = "verbose";
  this.INFO = "info";
  this.WARNING = "warning";
  this.ERROR = "error";
  // Custom level used internally by the console.
  this.INTERACTIVE = "interactive";
  // Prefix on severity for messages from the JS console.
  this.CONSOLE = '*';
  // Number of items to display on a single page.
  this.PAGE_SIZE = 50;
  // Number of items to scroll when the user pages up or down.
  this.SCROLL_SIZE = 20;
  // Number of lines to display when paging up to beginning of buffer.
  this.DISPLAY_AT_HEAD = 30;
  // The parent HTML element that holds the message elements.
  this.messageContainer = messageContainer;
  // The buffer that holds the message entries.
  this.buffer = new MessageBuffer();
  // Index of the item at the bottom of the currently displayed page.
  this.displayPos = 0;
  // Whether the message log is currently visible.
  this.visible = false;
}

MessageLog.prototype.setVisible = function(visible) {
  var wasVisible = this.visible;
  this.visible = visible;
  if (this.visible) {
    if (!wasVisible) {
      // Newly visible, display the messages on the current page.
      this.displayMessages();
    }
  } else {
    // Invisible. In theory, we might want to clear any HTML elements here,
    // but in practice, because of deferred GC, it doesn't gain us anything,
    // and in fact seems to result in more HTML nodes most of the time.
  }
}

// Creates the HTML element for a single message.
MessageLog.prototype.createMessageElement = function(severity, message) {
  // An empty message will result in an empty box occupying no space.
  // Insert a space into empty messages to preserve line formatting.
  if (message.length <= 0) {
    message = ' ';
  };

  // Create the new text element with the message.
  var elem = document.createElement('div');
  elem.className = 'message';
  var text = document.createTextNode(message);

  if (severity.startsWith(this.CONSOLE)) {
    severity = severity.substr(this.CONSOLE.length);
    elem.classList.add('console');
  }

  elem.classList.add(severity);

  elem.appendChild(text);

  return elem;
}

// Adds a new message to the log. Stores it in the buffer, and updates the
// display.
MessageLog.prototype.addMessage = function(severity, message) {
  // Split into lines and add one entry per line.
  // This makes it much simpler to manage layout with pagination.
  var lines = message.split('\n');
  var nLines = lines.length;
  // Ignore an empty line at the end - it just indicates a trailing newline.
  if (nLines >= 2 && lines[nLines - 1] == '') {
    nLines -= 1;
  }
  for (var l = 0; l < nLines; l++) {
    // Create the buffer entry and add it to the buffer.
    // Don't create the HTML element yet - defer until display.
    var newEntry = new BufferEntry(severity, lines[l]);
    this.buffer.insert(newEntry);
  }
  this.displayPos = 0;
  this.displayMessages();
}

// Completely repopulates the current message container, taking into account
// the current pagination settings.
MessageLog.prototype.displayMessages = function() {
  // Don't do anything if not currently visible.
  if (!this.visible) {
    return;
  }
  // Remove all currently displayed message elements and repopulate.
  while (this.messageContainer.firstChild) {
    this.messageContainer.removeChild(this.messageContainer.firstChild);
  }
  for (var n = this.PAGE_SIZE; n >= 0; n--) {
    var idx = n + this.displayPos;
    var bufferEntry = this.buffer.get(idx);
    if (bufferEntry) {
      // Create the HTML element if necessary.
      if (!bufferEntry.element) {
        bufferEntry.element = this.createMessageElement(bufferEntry.severity,
                                                        bufferEntry.message);
      }
      this.messageContainer.appendChild(bufferEntry.element);
    }
  }
}

MessageLog.prototype.scrollUp = function(size) {
  this.displayPos += size;
  var max = this.buffer.size - this.DISPLAY_AT_HEAD;
  if (this.displayPos > max) {
    this.displayPos = max;
  }
  this.displayMessages();
}

MessageLog.prototype.scrollDown = function(size) {
  this.displayPos -= size;
  if (this.displayPos < 0) {
    this.displayPos = 0;
  }
  this.displayMessages();
}

MessageLog.prototype.pageUp = function() {
  this.scrollUp(this.SCROLL_SIZE);
}

MessageLog.prototype.pageDown = function() {
  this.scrollDown(this.SCROLL_SIZE);
}

MessageLog.prototype.toHead = function() {
  this.displayPos = this.buffer.size - this.DISPLAY_AT_HEAD;
  this.displayMessages();
}

MessageLog.prototype.toTail = function() {
  this.displayPos = 0;
  this.displayMessages();
}

