// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

function onModelLoaded() {
  viewer.globalMode = true;
  viewer.model = model;
}

function clearTimeline() {
  viewer.model = undefined;
}

function onImportFail() {
  var overlay = new tr.ui.b.Overlay();
  overlay.textContent = tr.b.normalizeException(err).message;
  overlay.title = 'Import error';
  overlay.visible = true;
  console.log('import failed');
}

function updateTimeline(events) {
  model = new tr.Model();
  var importer = new tr.importer.Import(model);
  var p = importer.importTracesWithProgressDialog([events]);
  p.then(onModelLoaded, onImportFail);
}

function registerForMessages() {
  window.addEventListener("message", onMessage, false);
}

function fetchUri(uri, onLoad, onError) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', uri, true);
  xhr.responseType = 'text';
  xhr.addEventListener("load", onLoad);
  xhr.addEventListener("error", onError);
  xhr.send();
  console.log('GET ' + uri);
}


var traceObject;
var pendingRequests;

function gotReponse() {
  pendingRequests--;
  if (pendingRequests == 0) {
    console.log("Got all timeline parts");
    updateTimeline(traceObject);
  }
}

function fetchTimelineOnLoad(event) {
  var xhr = event.target;
  var response = JSON.parse(xhr.responseText);
  var result = response['result'];
  var newStackFrames = result['stackFrames'];  // Map.
  var newTraceEvents = result['traceEvents'];  // List.

  // Merge in timeline events.
  traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents);
  for (var key in newStackFrames) {
    if (newStackFrames.hasOwnProperty(key)) {
      traceObject.stackFrames[key] = newStackFrames[key];
    }
  }

  gotReponse();
}

function fetchTimelineOnError(event) {
  var xhr = event.target;
  console.log(xhr.statusText);
  gotReponse();
}

function fetchTimeline(vmAddress, isolateIds) {
  // Reset combined timeline.
  traceObject = {
    'stackFrames': {},
    'traceEvents': []
  };
  pendingRequests = 1 + isolateIds.length;

  var parser = document.createElement('a');
  parser.href = vmAddress;
  var requestUri = 'http://' +
                   parser.hostname +
                   ':' +
                   parser.port +
                   '/_getVMTimeline';
  fetchUri(requestUri, fetchTimelineOnLoad, fetchTimelineOnError);

  for (var i = 0; i < isolateIds.length; i++) {
    var isolateId = isolateIds[i];
    var requestUri = 'http://' +
                     parser.hostname +
                     ':' +
                     parser.port +
                     '/_getCpuProfileTimeline?tags=VMUser&isolateId=' +
                     isolateId;
    fetchUri(requestUri, fetchTimelineOnLoad, fetchTimelineOnError);
  }
}

function saveTimeline() {
  if (pendingRequests > 0) {
    var overlay = new tr.ui.b.Overlay();
    overlay.textContent = 'Cannot save timeline while fetching one.';
    overlay.title = 'Save error';
    overlay.visible = true;
    console.log('cannot save timeline while fetching one.');
    return;
  }
  if (!traceObject ||
      !traceObject.traceEvents ||
      (traceObject.traceEvents.length == 0)) {
    var overlay = new tr.ui.b.Overlay();
    overlay.textContent = 'Cannot save an empty timeline.';
    overlay.title = 'Save error';
    overlay.visible = true;
    console.log('Cannot save an empty timeline.');
    return;
  }
  var blob = new Blob([JSON.stringify(traceObject)],
                      {type: 'application/json'});
  var blobUrl = URL.createObjectURL(blob);
  var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
  link.href = blobUrl;
  var now = new Date();
  var defaultFilename = "dart-timeline-" +
                        now.getFullYear() +
                        "-" +
                        now.getMonth() +
                        "-" +
                        now.getDate() +
                        ".json";
  var filename = window.prompt('Save as', defaultFilename);
  if (filename) {
    link.download = filename;
    link.click();
  }
}

function loadTimeline() {
  if (pendingRequests > 0) {
    var overlay = new tr.ui.b.Overlay();
    overlay.textContent = 'Cannot load timeline while fetching one.';
    overlay.title = 'Save error';
    overlay.visible = true;
    console.log('Cannot load timeline while fetching one.');
    return;
  }
  var inputElement = document.createElement('input');
  inputElement.type = 'file';
  inputElement.multiple = false;

  var changeFired = false;
  inputElement.addEventListener('change', function(e) {
    if (changeFired)
      return;
    changeFired = true;

    var file = inputElement.files[0];
    var reader = new FileReader();
    reader.onload = function(event) {
      try {
        traceObject = JSON.parse(event.target.result);
        updateTimeline(traceObject);
      } catch (error) {
        tr.ui.b.Overlay.showError('Error while loading file: ' + error);
      }
    };
    reader.onerror = function(event) {
      tr.ui.b.Overlay.showError('Error while loading file: ' + event);
    };
    reader.onabort = function(event) {
      tr.ui.b.Overlay.showError('Error while loading file: ' + event);
    }
    reader.readAsText(file);
  });
  inputElement.click();
}

function onMessage(event) {
  var request = JSON.parse(event.data);
  var method = request['method'];
  var params = request['params'];
  switch (method) {
    case 'refresh':
      fetchTimeline(params['vmAddress'], params['isolateIds']);
    break;
    case 'clear':
      clearTimeline();
    break;
    case 'save':
      saveTimeline();
    break;
    case 'load':
      loadTimeline();
    break;
    default:
      console.log('Unknown method:' + method + '.');
  }
}

document.addEventListener('DOMContentLoaded', function() {
  var container = document.createElement('track-view-container');
  container.id = 'track_view_container';
  viewer = document.createElement('tr-ui-timeline-view');
  viewer.track_view_container = container;
  viewer.appendChild(container);
  viewer.id = 'trace-viewer';
  viewer.globalMode = true;
  document.body.appendChild(viewer);
  registerForMessages();
});

console.log('loaded');
