// Copyright (c) 2013 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.

'use strict';

/**
 * @fileoverview Displays an analysis of the selection.
 */
base.requireStylesheet('tracing.analysis.analysis_view');

base.require('base.guid');
base.require('tracing.analysis.analysis_results');
base.require('tracing.analysis.analyze_selection');
base.require('tracing.analysis.default_object_view');
base.require('tracing.analysis.object_instance_view');
base.require('tracing.analysis.object_snapshot_view');
base.require('tracing.analysis.slice_view');
base.require('tracing.analysis.util');
base.require('ui');
base.exportTo('tracing.analysis', function() {

  var AnalysisView = ui.define('div');

  AnalysisView.prototype = {
    __proto__: HTMLDivElement.prototype,

    decorate: function() {
      this.className = 'analysis-view';

      this.currentView_ = undefined;
      this.currentSelection_ = undefined;
      this.selections_ = [];
      this.guid_ = base.GUID.allocate();

      window.addEventListener('popstate', this.onPopState.bind(this));
    },

    changeViewType: function(viewType) {
      if (this.currentView_ instanceof viewType)
        return;
      this.textContent = '';
      try {
        this.currentView_ = new viewType();
        this.appendChild(this.currentView_);
      } catch (e) {
        this.currentView_ = undefined;
        throw e;
      }
      if (this.currentView_ instanceof tracing.analysis. AnalysisResults)
        this.classList.remove('viewing-object');
      else
        this.classList.add('viewing-object');
    },

    get currentView() {
      return this.currentView_;
    },

    get selection() {
      return this.currentSelection_;
    },

    set selection(selection) {
      this.selections_.push(selection);

      var state = {
        view_guid: this.guid_,
        selection_guid: selection.guid
      };
      window.history.pushState(state);

      this.processSelection(selection);
    },

    clearSelectionHistory: function() {
      this.selections_ = [];
    },

    onPopState: function(event) {
      if ((event.state === null) ||
          (event.state.view_guid !== this.guid_))
        return;

      var idx;
      for (idx = 0; idx < this.selections_.length; ++idx) {
        if (this.selections_[idx].guid === event.state.selection_guid)
          break;
      }

      if (idx >= this.selections_.length)
        return;

      this.processSelection(this.selections_[idx]);
      event.stopPropagation();
    },

    processSelection: function(selection) {
      var hitsByType = selection.getHitsOrganizedByType();
      if (selection.length == 1 &&
          hitsByType.counterSamples.length == 0) {
        if (this.tryToProcessSelectionUsingCustomViewer(selection[0]))
          return;
      }

      this.changeViewType(tracing.analysis.AnalysisResults);
      this.currentView.clear();
      this.currentSelection_ = selection;
      tracing.analysis.analyzeHitsByType(this.currentView, hitsByType);
    },

    tryToProcessSelectionUsingCustomViewer: function(hit) {
      var obj;
      var typeName;
      var viewBaseType;
      var defaultViewType;
      var viewProperty;
      var obj = hit.modelObject;
      if (hit instanceof tracing.SelectionObjectSnapshotHit) {
        typeName = obj.objectInstance.typeName;
        viewBaseType = tracing.analysis.ObjectSnapshotView;
        defaultViewType = tracing.analysis.DefaultObjectSnapshotView;
      } else if (hit instanceof tracing.SelectionObjectInstanceHit) {
        typeName = obj.typeName;
        viewBaseType = tracing.analysis.ObjectInstanceView;
        defaultViewType = tracing.analysis.DefaultObjectInstanceView;
      } else if (hit instanceof tracing.SelectionSliceHit) {
        typeName = obj.title;
        viewBaseType = tracing.analysis.SliceView;
        defaultViewType = undefined;
      } else {
        return false;
      }

      var customViewInfo = viewBaseType.getViewInfo(typeName);

      var viewType = customViewInfo ?
          customViewInfo.constructor : defaultViewType;

      // Some view types don't have default viewers. In those cases, we fall
      // back to the standard analysis sytem.
      if (!viewType)
        return false;

      this.changeViewType(viewType);
      this.currentView.modelObject = obj;
      return true;
    }
  };

  return {
    AnalysisView: AnalysisView
  };
});