// Copyright 2015 Google Inc. 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) {
  this.INFO = window.debugHub.LOG_INFO;
  this.WARNING = window.debugHub.LOG_WARNING;
  this.ERROR = window.debugHub.LOG_ERROR;
  this.ERROR_REPORT = window.debugHub.LOG_ERROR_REPORT;
  this.FATAL = window.debugHub.LOG_FATAL;
  this.INTERACTIVE = window.debugHub.LOG_FATAL + 1;
  // 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.style.whiteSpace = 'pre';
  var text = document.createTextNode(message);

  if (severity == this.INFO) {
    elem.style.color = '#A0FFA0';
  } else if (severity == this.WARNING) {
    elem.style.color = '#FFFF80';
  } else if (severity == this.ERROR ||
             severity == this.ERROR_REPORT ||
             severity == this.FATAL) {
    elem.style.color = '#FF9080';
  } else {
    elem.style.color = '#FFFFFF';
  }
  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.pageUp = function() {
  this.displayPos += this.SCROLL_SIZE;
  var max = this.buffer.size - this.DISPLAY_AT_HEAD;
  if (this.displayPos > max) {
    this.displayPos = max;
  }
  this.displayMessages();
}

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

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

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

