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

/**
 * This view displays options for importing data from a log file.
 */
var ImportView = (function() {
  'use strict';

  // This is defined in index.html, but for all intents and purposes is part
  // of this view.
  var LOAD_LOG_FILE_DROP_TARGET_ID = 'import-view-drop-target';

  // We inherit from DivView.
  var superClass = DivView;

  /**
   * @constructor
   */
  function ImportView() {
    assertFirstConstructorCall(ImportView);

    // Call superclass's constructor.
    superClass.call(this, ImportView.MAIN_BOX_ID);

    this.loadedDiv_ = $(ImportView.LOADED_DIV_ID);

    this.loadFileElement_ = $(ImportView.LOAD_LOG_FILE_ID);
    this.loadFileElement_.onchange = this.logFileChanged.bind(this);
    this.loadStatusText_ = $(ImportView.LOAD_STATUS_TEXT_ID);

    var dropTarget = $(LOAD_LOG_FILE_DROP_TARGET_ID);
    dropTarget.ondragenter = this.onDrag.bind(this);
    dropTarget.ondragover = this.onDrag.bind(this);
    dropTarget.ondrop = this.onDrop.bind(this);
  }

  ImportView.TAB_ID = 'tab-handle-import';
  ImportView.TAB_NAME = 'Import';
  ImportView.TAB_HASH = '#import';

  // IDs for special HTML elements in import_view.html.
  ImportView.MAIN_BOX_ID = 'import-view-tab-content';
  ImportView.LOADED_DIV_ID = 'import-view-loaded-div';
  ImportView.LOAD_LOG_FILE_ID = 'import-view-load-log-file';
  ImportView.LOAD_STATUS_TEXT_ID = 'import-view-load-status-text';
  // Used in tests.
  ImportView.LOADED_INFO_USER_COMMENTS_ID = 'import-view-user-comments';

  cr.addSingletonGetter(ImportView);

  ImportView.prototype = {
    // Inherit the superclass's methods.
    __proto__: superClass.prototype,

    /**
     * Called when a log file is loaded, after clearing the old log entries and
     * loading the new ones.  Returns true to indicate the view should
     * still be visible.
     */
    onLoadLogFinish: function(polledData, unused, logDump) {
      var input = new JsEvalContext(logDump);
      jstProcess(input, $(ImportView.LOADED_DIV_ID));

      setNodeDisplay(this.loadedDiv_, true);
      return true;
    },

    /**
     * Called when something is dragged over the drop target.
     *
     * Returns false to cancel default browser behavior when a single file is
     * being dragged.  When this happens, we may not receive a list of files for
     * security reasons, which is why we allow the |files| array to be empty.
     */
    onDrag: function(event) {
      // NOTE: Use Array.prototype.indexOf here is necessary while WebKit
      // decides which type of data structure dataTransfer.types will be
      // (currently between DOMStringList and Array). These have different APIs
      // so assuming one type or the other was breaking things. See
      // http://crbug.com/115433. TODO(dbeam): Remove when standardized more.
      var indexOf = Array.prototype.indexOf;
      return indexOf.call(event.dataTransfer.types, 'Files') == -1 ||
             event.dataTransfer.files.length > 1;
    },

    /**
     * Called when something is dropped onto the drop target.  If it's a single
     * file, tries to load it as a log file.
     */
    onDrop: function(event) {
      var indexOf = Array.prototype.indexOf;
      if (indexOf.call(event.dataTransfer.types, 'Files') == -1 ||
          event.dataTransfer.files.length != 1) {
        return;
      }
      event.preventDefault();

      // Loading a log file may hide the currently active tab.  Switch to the
      // import tab to prevent this.
      document.location.hash = 'import';

      this.loadLogFile(event.dataTransfer.files[0]);
    },

    /**
     * Called when a log file is selected.
     *
     * Gets the log file from the input element and tries to read from it.
     */
    logFileChanged: function() {
      this.loadLogFile(this.loadFileElement_.files[0]);
    },

    /**
     * Attempts to read from the File |logFile|.
     */
    loadLogFile: function(logFile) {
      if (logFile) {
        this.setLoadFileStatus('Loading log...', true);
        var fileReader = new FileReader();

        fileReader.onload = this.onLoadLogFile.bind(this, logFile);
        fileReader.onerror = this.onLoadLogFileError.bind(this);

        fileReader.readAsText(logFile);
      }
    },

    /**
     * Displays an error message when unable to read the selected log file.
     * Also clears the file input control, so the same file can be reloaded.
     */
    onLoadLogFileError: function(event) {
      this.loadFileElement_.value = null;
      this.setLoadFileStatus(
          'Error ' + getKeyWithValue(FileError, event.target.error.code) +
              '.  Unable to read file.',
          false);
    },

    onLoadLogFile: function(logFile, event) {
      var result = log_util.loadLogFile(event.target.result, logFile.name);
      this.setLoadFileStatus(result, false);
    },

    /**
     * Sets the load from file status text, displayed below the load file
     * button, to |text|.  Also enables or disables the load buttons based on
     * the value of |isLoading|, which must be true if the load process is still
     * ongoing, and false when the operation has stopped, regardless of success
     * of failure.  Also, when loading is done, replaces the load button so the
     * same file can be loaded again.
     */
    setLoadFileStatus: function(text, isLoading) {
      this.enableLoadFileElement_(!isLoading);
      this.loadStatusText_.textContent = text;

      if (!isLoading) {
        // Clear the button, so the same file can be reloaded.  Recreating the
        // element seems to be the only way to do this.
        var loadFileElementId = this.loadFileElement_.id;
        var loadFileElementOnChange = this.loadFileElement_.onchange;
        this.loadFileElement_.outerHTML = this.loadFileElement_.outerHTML;
        this.loadFileElement_ = $(loadFileElementId);
        this.loadFileElement_.onchange = loadFileElementOnChange;
      }

      // Style the log output differently depending on what just happened.
      var pos = text.indexOf('Log loaded.');
      if (isLoading) {
        this.loadStatusText_.className = 'import-view-pending-log';
      } else if (pos == 0) {
        this.loadStatusText_.className = 'import-view-success-log';
      } else if (pos != -1) {
        this.loadStatusText_.className = 'import-view-warning-log';
      } else {
        this.loadStatusText_.className = 'import-view-error-log';
      }
    },

    enableLoadFileElement_: function(enabled) {
      this.loadFileElement_.disabled = !enabled;
    },
  };

  return ImportView;
})();