// 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.

// Help functions
//
// Convert a string with wildcard pattern to RegExp.
// It takes backwards compatible into account, e.g. it replaces empty string
// with '*' to match the previous behavior.
function createRegExpFromPattern(patternToMatch) {
  if (!patternToMatch) {
    // Empty string matches everything.
    patternToMatch = '*';
  } else if (patternToMatch.indexOf('*') < 0) {
    // When wilecard is not used, match any string that contains it.
    patternToMatch = '*' + patternToMatch + '*';
  }
  regExpToMatch = patternToMatch.replace(/\./g, '\\.').replace(/\*/g, '.*');
  return new RegExp('^' + regExpToMatch + '$');
}

// Convert a string with space separated wildcard patterns to RegExps.
function createRegExpsFromPatterns(spaceSeparatedPatternsToMatch) {
  let patternsToMatch;
  if (spaceSeparatedPatternsToMatch) {
    patternsToMatch = spaceSeparatedPatternsToMatch.split(/(\s+)/);
  } else {
    // Matches everything if the string is empty, to match the previous
    // behavior.
    patternsToMatch = ['*'];
  }
  let regExpsToMatch = [];
  patternsToMatch.forEach(function(element) {
    let trimmedElement = element.trim();
    if (trimmedElement) {
      regExpsToMatch.push(createRegExpFromPattern(trimmedElement));
    }
  });
  return regExpsToMatch;
}

// Return whether |string| matches one of the RegExps specified in |regExps|.
function matchStringToRegExps(string, regExps) {
  for (let i = 0; i < regExps.length; i++) {
    if (string.match(regExps[i])) {
      return true;
    }
  }

  return false;
}

// Console values constructor
function ConsoleValues() {
  // Use a prefix on all WLS keys to ensure uniqueness.
  this.KEY_PREFIX = 'cobalt.debugConsole.consoleValues';
  // Default key used for auto-save, or if the user doesn't specify another.
  this.DEFAULT_KEY = 'default';
  // Reduced space-separated list of CVal prefixes to display at start-up.
  this.DEFAULT_ACTIVE_SET =
      'Cobalt Memory.CPU Memory.MainWebModule Memory.JS Memory.Font ' +
      'Count.MainWebModule.ImageCache.Resource ' +
      'Count.MainWebModule.DOM.HtmlElement Count.MainWebModule.Layout.Box ' +
      'Event.Count.MainWebModule.KeyDown.DOM.HtmlElement.Document.Added ' +
      'Event.Count.MainWebModule.KeyDown.Layout.Box.Created ' +
      'Event.Count.MainWebModule.KeyDown.Layout.Box.Destroyed ' +
      'Event.Duration.MainWebModule.DOM.VideoStartDelay ' +
      'Event.Duration.MainWebModule.KeyDown'

  this.allCVals = window.debugHub.cVal.keys();
  // If true, we will always pull our list of CVals from
  // this.DEFAULT_ACTIVE_SET.
  this.useDefaultActiveSet = true;

  // Do a single update to initialize everything.
  this.update();
}

// Console value tree node constructor
function ConsoleValueNode() {
  this.value = null;
  this.children = null;
}

// Helper function for addToTree.
// Finds a child node with a specified name, or creates it if necessary.
ConsoleValues.prototype.findOrCreateNode = function (name, node) {
  var child = null;
  if (node.children.hasOwnProperty(name)) {
    child = node.children[name];
  } else {
    child =  new ConsoleValueNode;
    node.children[name] = child;
  }
  return child;
}

// Adds a single console value to the tree.
// Console value names are split into components by dot separator. If a name
// has a single component, it is added directly at this level of the tree with
// its value, retrieved from Cobalt. If the name has multiple components, a node
// is created for the first component, then this function is called recursively
// on the remainder of the name, passing in the prefix (prior components) so the
// full name can be constructed for evaluation.
ConsoleValues.prototype.addToTree = function(cval, tree, prefix) {
  if (tree.children == null) {
    tree.children = new Object;
  }
  if (prefix == null) {
    prefix = '';
  }
  var components = cval.split('.');
  if (components.length == 1) {
    var node = this.findOrCreateNode(cval, tree);
    var fullName = prefix.length > 0 ? prefix + '.' + cval : cval;
    node.value = window.debugHub.cVal.getPrettyValue(fullName);
  } else {
    var newPrefix = components[0];
    var suffix = cval.substring(newPrefix.length + 1);
    node = this.findOrCreateNode(newPrefix, tree);
    if (prefix.length > 0) {
      prefix += '.';
    }
    prefix += newPrefix;
    this.addToTree(suffix, node, prefix);
  }
  return tree;
}

// Creates a tree from the console values.
// Each console value name consists of one or more dot-separated components.
// The last component of each console value name corresponds to a leaf node in
// the tree; other components correspond to branch nodes.
// A display string is then created from this tree, where leaf nodes with
// a common ancestor are displayed more compactly.
// This function assumes names are sorted alphabetically.
ConsoleValues.prototype.buildTree = function(cvals) {
  var root = new ConsoleValueNode;
  for (var i = 0; i < cvals.length; i++) {
    this.addToTree(cvals[i], root, '');
  }
  return root;
}

// Helper function for consoleValueTreeToString.
// Creates the formatted string for a single console value node. In the simplest
// case, where the node has no children, this will just be the name and value.
// If the node has a single child, we call this function recursively to output
// that child, with the full name of this node as a prefix. If the node has
// multiple children, we enclose those children in braces and recursively call
// treeToString on the sub-tree.
ConsoleValues.prototype.nodeToString = function(name, node, prefix) {
  var result  = '';
  var value = node.value;
  var children = node.children;
  var childNames = children != null ? Object.keys(children) : null;
  var numChildren = childNames != null ? childNames.length : 0;
  if (prefix.length > 0) {
    name = prefix + '.' + name;
  }
  if (value != null || numChildren > 1) {
    result += name + ': ';
  }
  if (value != null) {
    result += value;
    if (numChildren > 0) {
      result += ', ';
    }
  }
  if (numChildren == 1) {
    result += this.nodeToString(childNames[0], children[childNames[0]], name);
  } else if (numChildren > 1) {
    result += '{';
    result += this.treeToString(children, null);
    result += '}';
  }
  return result;
}

// Generates a formatted string from the parsed console value tree.
// Uses the helper function nodeToString to process each node.
// This function may in turn be called recursively by nodeToString
// to generate the string for a sub-tree (when a node has multiple children).
ConsoleValues.prototype.treeToString = function(cvalTree, prefix) {
  if (prefix == null) {
    prefix = '';
  }
  var result = '';
  var names = Object.keys(cvalTree);
  var numNames = names ? names.length : 0;
  for (var i = 0; i < numNames; i++) {
    result += this.nodeToString(names[i], cvalTree[names[i]], prefix)
    if (i < numNames - 1) {
      result += ', ';
    }
  }
  return result;
}

// Updates the complete list of registered CVals.
// If any active CVals are no longer registered, remove them from the active
// set.
ConsoleValues.prototype.updateRegistered = function() {
  if (this.useDefaultActiveSet) {
    this.setActiveSetToDefault();
  }

  this.allCVals = window.debugHub.cVal.keys();
  for (var i = 0; i < this.activeCVals.length; i++) {
    if (this.allCVals.indexOf(this.activeCVals[i]) < 0) {
      this.activeCVals.splice(i, 1);
    }
  }
}

// Updates the tree.
ConsoleValues.prototype.update = function() {
  this.updateRegistered();
  this.cvalTree = this.buildTree(this.activeCVals);
}

// Creates a formatted string from the current tree.
ConsoleValues.prototype.toString = function() {
  if (this.cvalTree && this.cvalTree.children) {
    return this.treeToString(this.cvalTree.children, null);
  } else {
    return 'No CVals to display.';
  }
}

// Lists registered cvals that match one of the patterns in
// |spaceSeparatedPatternsToMatch|.
ConsoleValues.prototype.list = function(spaceSeparatedPatternsToMatch) {
  var result = '';
  var regExps = createRegExpsFromPatterns(spaceSeparatedPatternsToMatch);
  var count = 0;
  for (var i = 0; i < this.allCVals.length; i++) {
    if (matchStringToRegExps(this.allCVals[i], regExps)) {
      result += this.allCVals[i] + '\n';
      ++count;
    }
  }
  result += '\n' + count + ' cvals total';
  return result;
}

// Adds a single CVal to the active set.
ConsoleValues.prototype.addSingleActive = function(cval) {
  if (this.activeCVals.indexOf(cval) < 0) {
    this.activeCVals.push(cval);
    return 'Added cval "' + cval + '" to display list.';
  } else {
    return '"' + cval + '" already in display list.';
  }
}

// Removes a single CVal from the active set.
ConsoleValues.prototype.removeSingleActive = function(cval) {
  var idx = this.activeCVals.indexOf(cval);
  if (idx >= 0) {
    this.activeCVals.splice(idx, 1);
    return 'Removed cval "' + cval + '" from display list.';
  } else {
    return '"' + cval + '" not in display list.';
  }
}

// Adds/removes one or more cvals from the active set.
// Each console value is matched against the space-separated list of patterns
// and the specified method run on each match.
ConsoleValues.prototype.updateActiveSet =
    function(onMatch, spaceSeparatedPatternsToMatch) {
  var result = '';
  var regExps = createRegExpsFromPatterns(spaceSeparatedPatternsToMatch);
  var processedCvals = [];
  for (var i = 0; i < regExps.length; ++i) {
    var found = false;
    for (var j = 0; j < this.allCVals.length; j++) {
      if (this.allCVals[j].match(regExps[i])) {
        found = true;
        if (processedCvals.indexOf(this.allCVals[j]) === -1) {
          processedCvals.push(this.allCVals[j]);
          result += onMatch.call(this, this.allCVals[j]) + '\n';
        }
      }
    }
    if (!found) {
      result += '"' + regExps[i] + '" matched no registered cvals.\n';
    }
  }
  this.activeCVals.sort();
  return result;
}


// Saves the current active set using the web local storage.
ConsoleValues.prototype.saveActiveSet = function(key) {
  if (this.useDefaultActiveSet) {
    // If we are using the default CVals and we go to save our CVal set, lock
    // it in to the currently displayed list.
    this.updateRegistered();
    this.useDefaultActiveSet = false;
  }

  if (!key || !key.length) {
    key = this.DEFAULT_KEY;
  }
  var longKey = this.KEY_PREFIX + '.' + key;
  var value = '';
  for (var i = 0; i < this.activeCVals.length; i++) {
    value += this.activeCVals[i];
    if (i < this.activeCVals.length - 1) {
      value += ' ';
    }
  }
  window.localStorage.setItem(longKey, value);
  return 'Stored current CVal display set to "' + longKey + '"';
}

// Loads an active set from web local storage.
ConsoleValues.prototype.loadActiveSet = function(key) {
  if (!key || !key.length) {
    key = this.DEFAULT_KEY;
  }
  var longKey = this.KEY_PREFIX + '.' + key;
  var value = window.localStorage.getItem(longKey);
  if (value && value.length > 0) {
    // If we load CVals from disk, we no longer use the default set.
    this.useDefaultActiveSet = false;
    this.activeCVals = value.split(' ');
    return 'Loaded CVal display set from "' + longKey + '"';
  } else {
    return 'Could not load CVal display set from "' + longKey + '"';
  }
}

// Sets the CVal active set to the set of CVals the match the default prefixes.
// Any of the registered console values that match one of the space-separated
ConsoleValues.prototype.setActiveSetToDefault = function() {
  this.activeCVals = [];
  this.updateActiveSet(this.addSingleActive, this.DEFAULT_ACTIVE_SET);
}

// Adds one or more CVals to the active list.
// Any of the registered console values that match one of the space-separated
// set of patterns will be added to the active set.
ConsoleValues.prototype.addActive = function(spaceSeparatedPatternsToMatch) {
  if (this.useDefaultActiveSet) {
    // If we modify our list of CVals, we should no longer rely on the defaults.
    this.updateRegistered();
    this.useDefaultActiveSet = false;
  }
  return this.updateActiveSet(this.addSingleActive,
                              spaceSeparatedPatternsToMatch);
}

// Removes one or more CVals from the active list.
// Any of the registered console values that match one of the space-separated
// set of patterns will be removed from the active set.
ConsoleValues.prototype.removeActive = function(spaceSeparatedPatternsToMatch) {
  if (this.useDefaultActiveSet) {
    // If we modify our list of CVals, we should no longer rely on the defaults.
    this.updateRegistered();
    this.useDefaultActiveSet = false;
  }
  return this.updateActiveSet(this.removeSingleActive,
                              spaceSeparatedPatternsToMatch);
}
