// 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) {
  // 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;
}

// Log levels defined by the 'level' property of LogEntry
// https://chromedevtools.github.io/devtools-protocol/1-3/Log#type-LogEntry
MessageLog.VERBOSE = "verbose";
MessageLog.INFO = "info";
MessageLog.WARNING = "warning";
MessageLog.ERROR = "error";
// Custom level used internally by the console.
MessageLog.INTERACTIVE = "interactive";
// Prefix on severity for messages from the JS console.
MessageLog.CONSOLE = '*';

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(MessageLog.CONSOLE)) {
    severity = severity.substr(MessageLog.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();
}

