/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

var htrace = htrace || {};

htrace.SearchResultsView = Backbone.View.extend({
  // The minimum time span we will allow between begin and end.
  MINIMUM_TIME_SPAN: 100,

  begin: 0,

  end: this.MINIMUM_TIME_SPAN,

  processNameFraction: 0.2,

  initialize: function(options) {
    this.searchResults = options.searchResults;
    this.el = options.el;
    var view = this;

    // Re-render the canvas when the window size changes.
    // Add a debouncer delay to avoid spamming render requests.
    $(window).on("resize", _.debounce(function()  {
      view.render();
    }, 250));
  },

  // Get the canvas X coordinate of a mouse click from the absolute event
  // coordinate.
  getCanvasX: function(e) {
    return e.pageX - $("#resultsCanvas").offset().left;
  },

  // Get the canvas Y coordinate of a mouse click from the absolute event
  // coordinate.
  getCanvasY: function(e) {
    return e.pageY - $("#resultsCanvas").offset().top;
  },

  handleMouseDown: function(e) {
    e.preventDefault();
    this.widgetManager.handle({
      type: "mouseDown",
      x: this.getCanvasX(e),
      y: this.getCanvasY(e),
      raw: e
    });
    this.draw();
  },

  handleMouseUp: function(e) {
    e.preventDefault();
    this.widgetManager.handle({
      type: "mouseUp",
      x: this.getCanvasX(e),
      y: this.getCanvasY(e),
      raw: e
    });
    this.draw();
  },

  handleMouseOut: function(e) {
    e.preventDefault();
    this.widgetManager.handle({
      type: "mouseOut"
    });
    this.draw();
  },

  handleMouseMove: function(e) {
    e.preventDefault();
    this.widgetManager.handle({
      type: "mouseMove",
      x: this.getCanvasX(e),
      y: this.getCanvasY(e),
      raw: e
    });
    this.draw();
  },

  handleDblclick: function(e) {
    e.preventDefault();
    this.widgetManager.handle({
      type: "dblclick",
      x: this.getCanvasX(e),
      y: this.getCanvasY(e),
      raw: e
    });
    this.draw();
  },

  render: function() {
    console.log("SearchResultsView#render.");
    $(this.el).html(_.template($("#search-results-view-template").html()));
    $('#selectedTime').attr('readonly', 'readonly');
    this.canvas = $("#resultsCanvas");
    this.ctx = this.canvas.get(0).getContext("2d");
    this.setupCoordinates();
    this.setupWidgets();
    this.scaleCanvas();
    this.draw();
    this.attachEvents();
    return this;
  },

  /*
   * Compute the ratio to use between the size of the canvas (i.e.
   * canvas.ctx.width, canvas.ctx.height) and the size in "HTML5 pixels." Note
   * that 'HTML5 pixels" don't actually correspond to screen pixels.  A line 1
   * "HTML5 pixel"  wide actually takes up multiple scren pixels, etc.
   *
   * TODO: fix this to be sharper
   */
  computeScaleFactor: function() {
    var backingStoreRatio = this.ctx.backingStorePixelRatio ||
          this.ctx.mozBackingStorePixelRatio ||
          this.ctx.msBackingStorePixelRatio ||
          this.ctx.webkitBackingStorePixelRatio ||
          this.ctx.oBackingStorePixelRatio ||
          this.ctx.backingStorePixelRatio || 1;
    return (window.devicePixelRatio || 1) / backingStoreRatio;
  },

  // Sets up the canvas size and scaling.
  scaleCanvas: function() {
    var ratio = this.computeScaleFactor();
    //console.log("scaleCanvas: cssX=" + cssX + ", cssY=" + cssY + ", ratio=" + ratio);
    $('#searchView').css('height', this.canvasY + "px");
    $('#resultsView').css('height', this.canvasY + "px");
    $('#resultsCanvas').css('height', this.canvasY + "px");
    this.ctx.canvas.width = this.viewX * ratio;
    this.ctx.canvas.height = this.canvasY * ratio;
    this.ctx.scale(ratio, ratio);
  },

  //
  // Set up the screen coordinates.
  //
  //  0              xB         xD                   xS         viewX
  //  +--------------+----------+--------------------+-----------+
  //  |TracerId      | Buttons  | Span Description   | Scrollbar |
  //  +--------------+----------+--------------------+-----------+
  //
  setupCoordinates: function() {
    this.viewX = this.canvas.parent().innerWidth();
    this.viewY = $(window).innerHeight() - $("#header").innerHeight() - 50;
    this.xB = Math.floor(this.viewX * this.processNameFraction);
    this.xD = this.xB + Math.min(75, Math.floor(this.viewX / 20));
    var scrollBarWidth = Math.min(50, Math.floor(this.viewX / 10));
    this.xS = this.viewX - scrollBarWidth;
    this.canvasY = this.viewY;
  },

  setupWidgets: function() {
    var searchResultsView = this;
    this.widgetManager = new htrace.WidgetManager({searchResultsView: this});

    var partitionWidgetWidth = Math.max(5, Math.floor(this.viewX / 300));

    // Create a SpanWidget for each span we know about
    var spanWidgetHeight = Math.min(25, Math.floor(this.viewY / 32));
    var numResults = this.searchResults.size();
    var groupY = 0;
    for (var i = 0; i < numResults; i++) {
      var widget = new htrace.SpanGroupWidget({
        manager: this.widgetManager,
        ctx: this.ctx,
        span: this.searchResults.at(i),
        x0: 0,
        xB: this.xB + partitionWidgetWidth,
        xD: this.xD,
        xF: this.xS,
        y0: groupY,
        begin: this.begin,
        end: this.end,
        spanWidgetHeight: spanWidgetHeight
      });
      groupY = widget.yF;
    }
    if (this.canvasY < groupY) {
      this.canvasY = groupY;
    }

    // Create the draggable horizontal parition between process names and span
    // names.
    new htrace.PartitionWidget({
      el: '#resultsCanvas',
      manager: this.widgetManager,
      ctx: this.ctx,
      x0: this.xB,
      xF: this.xB + partitionWidgetWidth,
      xMin: Math.floor(this.viewX * 0.10),
      xMax: Math.floor(this.viewX * 0.90),
      y0: 0, 
      yF: groupY,
      releaseHandler: function(x) {
        searchResultsView.processNameFraction = (x / searchResultsView.viewX);
        console.log("htrace#PartitionWidget setting processNameFraction to " +
              searchResultsView.processNameFraction);
        searchResultsView.render();
      }
    });

    // Create the time cursor widget.
    var selectedTime = this.begin;
    if (this.timeCursor != null) {
      selectedTime = this.timeCursor.selectedTime;
    }
    this.timeCursor = new htrace.TimeCursor({
      manager: this.widgetManager,
      selectedTime: selectedTime,
      el: "#selectedTime"
    });
    this.timeCursor.ctx = this.ctx;
    this.timeCursor.x0 = this.xD;
    this.timeCursor.xF = this.xS;
    this.timeCursor.y0 = 0;
    this.timeCursor.yF = this.canvasY;
    this.timeCursor.begin = this.begin;
    this.timeCursor.end = this.end;
  },

  draw: function() {
    if (this.checkCanvasTooSmall()) {
      return;
    }

    // Set the background to white.
    this.ctx.save();
    this.ctx.fillStyle="#ffffff";
    this.ctx.strokeStyle="#000000";
    this.ctx.fillRect(0, 0, this.viewX, this.canvasY);
    this.ctx.restore();

    // Draw all the widgets.
    this.widgetManager.handle({type: "draw"});
  },

  checkCanvasTooSmall: function() {
    if ((this.viewX < 200) || (this.viewY < 200)) {
      this.ctx.fillStyle="#cccccc";
      this.ctx.strokeStyle="#000000";
      this.ctx.fillRect(0, 0, this.viewX, this.viewY);
      this.ctx.font = "24px serif";
      this.ctx.fillStyle="#000000";
      this.ctx.fillText("Canvas too small!", 0, 24);
      return true;
    }
    return false;
  },

  attachEvents: function() {
    // Use jquery to capture mouse events on the canvas.
    // For some reason using backbone doesn't work for getting these events.
    var view = this;
    $("#resultsCanvas").off("mousedown");
    $("#resultsCanvas").on("mousedown", function(e) {
      $("#resultsCanvas").focus();
      view.handleMouseDown(e);
    });
    $("#resultsCanvas").off("mouseup");
    $("#resultsCanvas").on("mouseup", function(e) {
      view.handleMouseUp(e);
    });
    $("#resultsCanvas").off("mouseout");
    $("#resultsCanvas").on("mouseout", function(e) {
      view.handleMouseOut(e);
    });
    $("#resultsCanvas").off("mousemove");
    $("#resultsCanvas").on("mousemove", function(e) {
      view.handleMouseMove(e);
    });
    $("#resultsCanvas").off("dblclick");
    $("#resultsCanvas").on("dblclick", function(e) {
      view.handleDblclick(e);
    });
    // Keyboard events.  These events only fire if the canvas has focus.  So if
    // you press delete when entering a time in the time dialog box, this will
    // not fire.  Etc.
    $("#resultsCanvas").off("keyup");
    $("#resultsCanvas").on("keyup", function(e) {
      if (e.keyCode == 46) { // delete key
        view.clearHandler(false);
        return false;
      } else if (e.keyCode == 90) { // z key
        view.zoomHandler();
        return false;
      } else {
        return true;
      }
    });
    $("#resultsCanvas").off("contextmenu");
    $("#resultsCanvas").on("contextmenu", function(e) {
      return false;
    });
  },

  remove: function() {
    $(window).off("resize");
    $("#resultsCanvas").off("mousedown");
    $("#resultsCanvas").off("mouseup");
    $("#resultsCanvas").off("mouseout");
    $("#resultsCanvas").off("mousemove");
    $("#resultsCanvas").off("dblclick");
    $("#resultsCanvas").off("keyup");
    $("#resultsCanvas").off("contextmenu");
    Backbone.View.prototype.remove.apply(this, arguments);
  },

  handleBeginOrEndChange: function(e, type) {
    e.preventDefault();
    var text = $(e.target).val().trim();
    var d = null;
    try {
      d = htrace.parseDate(text);
    } catch(err) {
      $("#begin").val(htrace.dateToString(this.begin));
      $("#end").val(htrace.dateToString(this.end));
      htrace.showModalWarning("Timeline " + type + " Format Error",
        "Please enter a valid time in the timeline " + type + " field.<p/>" +
        err);
      return null;
    }
    if (type === "begin") {
      this.setTimes({begin: d.valueOf()});
    } else if (type === "end") {
      this.setTimes({end: d.valueOf()});
    } else {
      throw "invalid type for handleBeginOrEndChange: expected begin or end.";
    }
    this.render();
  },

  setTimes: function(params) {
    if (params["begin"]) {
      this.begin = params["begin"];
    }
    if (params["end"]) {
      this.end = params["end"];
    }
    if (this.end < this.begin) {
      var b = this.begin;
      this.begin = this.end;
      this.end = b;
    }
    var delta = this.end - this.begin;
    if (delta < this.MINIMUM_TIME_SPAN) {
      var needed = this.MINIMUM_TIME_SPAN - delta;
      this.begin -= (needed / 2);
      this.end += (needed / 2);
    }
    $("#begin").val(htrace.dateToString(this.begin));
    $("#end").val(htrace.dateToString(this.end));
    // caller should invoke render()
  },

  clearHandler: function(clearAllIfNoneSelected) {
    console.log("invoking clearHandler.");
    var toDelete = []
    var noneSelected = true;
    for (var i = 0; i < this.searchResults.length; i++) {
      var resultSelected = false;
      var model = this.searchResults.at(i);
      htrace.treeTraverseDepthFirstPre(model,
        htrace.getReifiedChildren, 0,
          function(node, depth) {
            if (noneSelected) {
              if (node.get("selected")) {
                resultSelected = true;
              }
            }
          });
      htrace.treeTraverseDepthFirstPre(model,
        htrace.getReifiedParents, 0,
          function(node, depth) {
            if (node.get("selected")) {
              resultSelected = true;
            }
          });
      if (resultSelected) {
        if (noneSelected) {
          toDelete = [];
          noneSelected = false;
        }
        toDelete.push(model);
      } else if (noneSelected) {
        toDelete.push(model);
      }
    }
    if (noneSelected && (!clearAllIfNoneSelected)) {
      return;
    }
    ids = [];
    for (var i = 0; i < toDelete.length; i++) {
      ids.push(toDelete[i].get("spanId"));
    }
    console.log("clearHandler: removing " + JSON.stringify(ids));
    this.searchResults.remove(toDelete);
    this.render();
  },

  getSelectedSpansOrAllSpans: function() {
    // Get the list of selected spans.
    // If there are no spans selected, we return all spans.
    var ret = [];
    var noneSelected = true;
    this.applyToAllSpans(function(span) {
        if (span.get("selected")) {
          if (noneSelected) {
            ret = [];
            noneSelected = false;
          }
          ret.push(span);
        } else if (noneSelected) {
          ret.push(span);
        }
      });
    return ret;
  },

  zoomHandler: function() {
    var zoomSpans = this.getSelectedSpansOrAllSpans();
    var numResults = zoomSpans.length;
    if (numResults == 0) {
      this.setTimes({begin:0, end:this.MINIMUM_TIME_SPAN});
      this.render();
      return;
    }
    var minStart = 4503599627370496;
    var maxEnd = 0;
    for (var i = 0; i < numResults; i++) {
      var begin = zoomSpans[i].getEarliestBegin();
      if (begin < minStart) {
        minStart = begin;
      }
      var end = zoomSpans[i].getLatestEnd();
      if (end > maxEnd) {
        maxEnd = end;
      }
    }
    this.setTimes({begin: minStart, end: maxEnd});
    this.render();
  },

  // Apply a function to all spans
  applyToAllSpans: function(cb) {
    for (var i = 0; i < this.searchResults.length; i++) {
      htrace.treeTraverseDepthFirstPre(this.searchResults.at(i),
        htrace.getReifiedChildren, 0,
          function(node, depth) {
            cb(node);
          });
      htrace.treeTraverseDepthFirstPre(this.searchResults.at(i),
        htrace.getReifiedParents, 0,
          function(node, depth) {
            if (depth > 0) {
              cb(node);
            }
          });
    }
  }
});
