// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('cert_viewer', function() {
  'use strict';

  /**
   * Initialize the certificate viewer dialog by wiring up the close button,
   * substituting in translated strings and requesting certificate details.
   */
  function initialize() {
    cr.ui.decorate('tabbox', cr.ui.TabBox);

    var args = JSON.parse(chrome.getVariableValue('dialogArguments'));
    getCertificateInfo(args);

    /**
     * Initialize the second tab's contents.
     * This is a 'oneShot' function, meaning it will only be invoked once,
     * no matter how many times it is called.  This is done for unit-testing
     * purposes in case a test needs to initialize the tab before the timer
     * fires.
     */
    var initializeDetailTab = oneShot(function() {
      initializeTree($('hierarchy'), showCertificateFields);
      initializeTree($('cert-fields'), showCertificateFieldValue);
      createCertificateHierarchy(args.hierarchy);
    });

    // The second tab's contents aren't visible on startup, so we can
    // shorten startup by not populating those controls until after we
    // have had a chance to draw the visible controls the first time.
    // The value of 200ms is quick enough that the user couldn't open the
    // tab in that time but long enough to allow the first tab to draw on
    // even the slowest machine.
    setTimeout(initializeDetailTab, 200);

    $('tabbox').addEventListener('selectedChange', function f(e) {
      $('tabbox').removeEventListener('selectedChange', f);
      initializeDetailTab();
    }, true);

    stripGtkAccessorKeys();

    $('export').onclick = exportCertificate;
  }

  /**
   * Decorate a function so that it can only be invoked once.
   */
  function oneShot(fn) {
    var fired = false;
    return function() {
       if (fired) return;
       fired = true;
       fn();
    };
  }

  /**
   * Initialize a cr.ui.Tree object from a given element using the specified
   * change handler.
   * @param {HTMLElement} tree The HTMLElement to style as a tree.
   * @param {function()} handler Function to call when a node is selected.
   */
  function initializeTree(tree, handler) {
    cr.ui.decorate(tree, cr.ui.Tree);
    tree.detail = {payload: {}, children: {}};
    tree.addEventListener('change', handler);
  }

  /**
   * The tab name strings in the languages file have accessor keys indicated
   * by a preceding & sign. Strip these out for now.
   * TODO(flackr) These accessor keys could be implemented with Javascript or
   *     translated strings could be added / modified to remove the & sign.
   */
  function stripGtkAccessorKeys() {
    // Copy all the tab labels into an array.
    var nodes = Array.prototype.slice.call($('tabs').childNodes, 0);
    nodes.push($('export'));
    for (var i = 0; i < nodes.length; i++)
      nodes[i].textContent = nodes[i].textContent.replace('&', '');
  }

  /**
   * Expand all nodes of the given tree object.
   * @param {cr.ui.Tree} tree The tree object to expand all nodes on.
   */
  function revealTree(tree) {
    tree.expanded = true;
    for (var key in tree.detail.children) {
      revealTree(tree.detail.children[key]);
    }
  }

  /**
   * This function is called from certificate_viewer_ui.cc with the certificate
   * information. Display all returned information to the user.
   * @param {Object} certInfo Certificate information in named fields.
   */
  function getCertificateInfo(certInfo) {
    for (var key in certInfo.general) {
      $(key).textContent = certInfo.general[key];
    }
  }

  /**
   * This function populates the certificate hierarchy.
   * @param {Object} hierarchy A dictionary containing the hierarchy.
   */
  function createCertificateHierarchy(hierarchy) {
    var treeItem = $('hierarchy');
    var root = constructTree(hierarchy[0]);
    treeItem.detail.children['root'] = root;
    treeItem.add(root);

    // Select the last item in the hierarchy (really we have a list here - each
    // node has at most one child).  This will reveal the parent nodes and
    // populate the fields view.
    var last = root;
    while (last.detail.children && last.detail.children[0])
      last = last.detail.children[0];
    last.selected = true;
  }

  /**
   * Constructs a cr.ui.TreeItem corresponding to the passed in tree
   * @param {Object} tree Dictionary describing the tree structure.
   * @return {cr.ui.TreeItem} Tree node corresponding to the input dictionary.
   */
  function constructTree(tree)
  {
    var treeItem = new cr.ui.TreeItem({
        label: tree.label,
        detail: {payload: tree.payload ? tree.payload : {},
            children: {}
        }});
    if (tree.children) {
      for (var i = 0; i < tree.children.length; i++) {
        treeItem.add(treeItem.detail.children[i] =
            constructTree(tree.children[i]));
      }
    }
    return treeItem;
  }

  /**
   * Clear any previous certificate fields in the tree.
   */
  function clearCertificateFields() {
    var treeItem = $('cert-fields');
    for (var key in treeItem.detail.children) {
      treeItem.remove(treeItem.detail.children[key]);
      delete treeItem.detail.children[key];
    }
  }

  /**
   * Request certificate fields for the selected certificate in the hierarchy.
   */
  function showCertificateFields() {
    clearCertificateFields();
    var item = $('hierarchy').selectedItem;
    if (item && item.detail.payload.index !== undefined)
      chrome.send('requestCertificateFields', [item.detail.payload.index]);
  }

  /**
   * Show the returned certificate fields for the selected certificate.
   * @param {Object} certFields A dictionary containing the fields tree
   *     structure.
   */
  function getCertificateFields(certFields) {
    clearCertificateFields();
    var treeItem = $('cert-fields');
    treeItem.add(treeItem.detail.children['root'] =
        constructTree(certFields[0]));
    revealTree(treeItem);
    // Ensure the list is scrolled to the top by selecting the first item.
    treeItem.children[0].selected = true;
  }

  /**
   * Show certificate field value for a selected certificate field.
   */
  function showCertificateFieldValue() {
    var item = $('cert-fields').selectedItem;
    if (item && item.detail.payload.val)
      $('cert-field-value').textContent = item.detail.payload.val;
    else
      $('cert-field-value').textContent = '';
  }

  /**
   * Export the selected certificate.
   */
  function exportCertificate() {
    var item = $('hierarchy').selectedItem;
    if (item && item.detail.payload.index !== undefined)
      chrome.send('exportCertificate', [item.detail.payload.index]);
  }

  return {
    initialize: initialize,
    getCertificateFields: getCertificateFields,
  };
});

document.addEventListener('DOMContentLoaded', cert_viewer.initialize);
