<!--
  This in an HTML Import-able file that contains the definition
  of the following elements:

    <commits-table-d3-sk>

  This uses d3 to draw the commit table.  Unlike previous versions which used a table and basically
  drew the table row by row, this implementation draws it column by column.  Because filtering
  happens on a task spec (column) basis, drawing it column by column results in simpler code.

  D3 is much much faster than Polymer for this type of data visualization, although this element
  still offers a Polymer interface.  If any of the inputs change, the table will be redrawn.

  To use this file import it:

    <link href="/res/imp/commits-table-d3-sk" rel="import" />

  Usage:

    <commits-table-d3-sk></commits-table-d3-sk>

  Properties:
    // inputs
    task_details: Object, a map of commit hash to an object that has the task results by task spec.
    task_specs: Object, a map of the task spec names to an object that has, among other things, category,
        subcategory, and comments.
    tasks: Object, a map of the task spec names to an object that maps task IDs to task results.
    categories: Object, a map of the task spec categories to an object that has the subcategories and
        the colspan (total number of included task specs).
    category_list: Array<String>, an array of the task spec category names.
    commits: Array<Object>, the commit objects, in chronological detail.
    commits_map: Object, a map of commit hash to commit objects.
    logged_in: Boolean, if the links should be for internal or external pages.
    relanded_map: Object, a map of an issue number that was relanded to the commit that relands it.
    repo: String, the current repo.  Used to direct comments to the right place.
    repo_base: The base URL for commits. Commit hashes will be appended to this.
    reverted_map: Object, a map of an issue number that was reverted to the commit that reverts it.
    swarming_url: String, the URL of the Swarming server.
    task_scheduler_url: String, the URL of the Task Scheduler.

  Methods:
    None.

  Events:
    None.
-->
<script src="/res/imp/bower_components/d3/d3.min.js"></script>

<link rel="import" href="/res/imp/bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="/res/imp/bower_components/iron-icons/iron-icons.html">
<link rel="import" href="/res/imp/bower_components/iron-icons/communication-icons.html">
<link rel="import" href="/res/imp/bower_components/iron-icons/image-icons.html">
<link rel="import" href="/res/imp/bower_components/paper-dialog/paper-dialog.html">

<link rel="import" href="/res/common/imp/styles-sk.html">

<link rel="import" href="task-popup-sk.html">
<link rel="import" href="taskspec-popup-sk.html">
<link rel="import" href="commit-popup-sk.html">

<link rel="stylesheet" href="commits-table-d3.css">
<dom-module id="commits-table-d3-sk">
  <template>
    <style include="iron-flex styles-sk">
      #commits {
        min-height: 780px;
        min-width: 50px;
      }
      #tasks {
        border: 1px solid blue;
        min-height: 400px;
      }
      #legend {
        border-right: 1px solid black;
        font-size: 10px;
        height: 68px;
      }
      #table {
        /* 80 pixels of header and 35 * 20px of commits.
        It is important to preallocate this size, otherwise the flexbox layout
        behaves strangely (i.e. wrong) when the data is first added. */
        min-height: 780px;
      }
      iframe {
        border: 0;
      }
    </style>

    <div id="container" class="horizontal layout">
      <div id="commits">
        <div id="legend">
          <iron-icon class="tiny" icon="communication:chat"></iron-icon> comment<br/>
          <iron-icon class="tiny" icon="image:texture"></iron-icon> flaky<br/>
          <iron-icon class="tiny" icon="icons:block"></iron-icon> ignore failure<br/>
          <iron-icon class="tiny fg-failure" icon="icons:undo"></iron-icon> reverted<br/>
          <iron-icon class="tiny fg-success" icon="icons:redo"></iron-icon> relanded<br/>
        </div>
      </div>
      <div id="table" class="flex horizontal layout"></div>
    </div>

    <div id="infoDialog"></div>

  </template>
  <script>
  (function(){
    var TASK_HEIGHT = 20;
    Polymer({
      is: 'commits-table-d3-sk',
      properties: {
        // inputs from data source to render.
        task_specs: {
          type: Object,
        },
        task_details: {
          type: Object,
        },
        tasks: {
          type: Object,
        },
        categories: {
          type: Object,
        },
        category_list: {
          type: Array,
        },
        commit_label: {
          type: String,
        },
        commits: {
          type: Array,
        },
        commits_map: {
          type: Object,
        },
        logged_in: {
          type: Boolean,
        },
        relanded_map: {
          type: Object,
        },
        repo: {
          type: String,
        },
        repo_base: {
          type: String,
        },
        reverted_map: {
          type: Object,
        },
        swarming_url: {
          type: String,
        },
        time_points: {
          type: Object,
        },
        task_scheduler_url: {
          type: String,
        },

        // outputs
        drawing: {
          type: Boolean,
          notify: true,
          value: false,
        }
      },
      observers: [
        "redraw(task_specs, task_details, categories, category_list, commit_label, commits, commits_map, relanded_map, repo, reverted_map, time_points)",
      ],

      ready: function() {
        // We redraw, so as to try to better fit the screen size.
        d3.select(window).on('resize', this.redraw.bind(this));
        this.scopeSubtree(this.$.container, true);
      },

      redraw:function() {
        // This gets called any time one of the values changes.  Since the values are
        // updated simultaneously, we don't want to try to draw the table many times at the
        // same time, so we debounce it.  No timeout on the debounce because all the this.set
        // calls will happen before a paint call, so this just basically collates all the requests.
        this.debounce("redraw-commits-table", function(){
          this._redraw();
        }.bind(this));
      },

      _redraw:function() {
        this.set("drawing", true);
        console.time("d3 rendering");

        // Display pictures instead of tasks if there aren't any to display.
        var iframe = null;
        for (var i = 0; i < this.$.table.childNodes.length; i++) {
          var child = this.$.table.childNodes[i];
          if (child.tagName == "IFRAME") {
            iframe = child;
            break;
          }
        }
        if (this.category_list.length === 0) {
          if (!iframe) {
            iframe = document.createElement("iframe");
            iframe.src = "https://clients3.google.com/cast/chromecast/home?slideshow-period=300";
            this.$.table.appendChild(iframe);
          }
          // Images are 1920x1080. Scale to fit the size of the div.
          srcWidth = 1920;
          srcHeight = 1080;
          var scale = Math.min(this.$.table.clientWidth / srcWidth, this.$.table.clientHeight / srcHeight);
          iframe.style.width = (srcWidth * scale) + "px";
          iframe.style.height = (srcHeight * scale) + "px";
        } else {
          if (iframe) {
            this.$.table.removeChild(iframe);
          }
        }

        this._drawCommitMessages(this.commits, this.relanded_map, this.reverted_map, this.time_points);
        this._drawCategories(this.category_list, this.categories);
        this._drawSubCategories(this.categories);
        this._drawTaskSpecColumns(this.categories, this.task_specs, this.commits.length);
        this._drawTasks(this.commits, this.task_details);
        console.timeEnd("d3 rendering");
        this.set("drawing", false);
      },

      // Draw all of the commit divs that are on the left.
      _drawCommitMessages: function(commits, relanded_map, reverted_map, time_points){
        var openCommitDialog = this._openCommitDialog.bind(this);
        var commitLabel = this.commit_label;
        // It's easiest to delete all .commits and redraw them.  Normally, we would only update
        // the ones we want, but since we have a composed element and there aren't very many
        // commits, starting from scratch is simplest.
        d3.select(this.$.commits).selectAll(".commit").remove();
        var data = d3.select(this.$.commits).selectAll(".commit")
          .data(commits, function(commit, i){
            commit.index = i;
            return commit.hash;
          });
        // Create a commit div for each commit with id "patch_storage + codereview_number".
        // Eg: "gerrit12345" for Gerrit.
        // For posterity: Element selectors choke if an id starts with a number, thus the
        // patch_storage prefix helps with that.
        var newCommits = data
          .enter()
          .append("div")
          .classed("commit",true)
          .attr("id", function(commit){
            return commit.patchStorage + commit.issue;
          })
          .on("tap", function(commit) {
            // Stop the propogation so we don't immediately hide the popup we show.
            d3.event.stopPropagation();
            openCommitDialog(commit);
          });
        // Sort the commits to be in the order we are presented with them.
        data.order();
        // Set the mouseover to be the opposite of what the label says.
        newCommits
          .attr("title", function(commit) {
            if (commitLabel == "author") {
              return commit.shortSubject;
            }
            return commit.author;
          });

        // Add a spacer to every commit where the time bubble could be.  This allows all
        // the bubbles and non-bubble commits to line up vertically.
        var spacers = newCommits
          .insert("div")
          .classed("time-spacer",true);

        spacers.each(function(commit) {
          var point = time_points[commit.hash];
          if (point) {
          d3.select(this)
            .append("span")
            .classed("time-underline", true);
          d3.select(this)
            .insert("span")
            .classed("time", true)
            .attr("title", point.label)
            .text(point.label);
          }
        });

        // Insert a span with the commit label.
        newCommits
          .insert("span")
          .classed("author", function(){
            return commitLabel == "author";
          })
          .classed("subject", function(){
            return commitLabel == "subject";
          })
          .text(function(commit) {
            if (commitLabel == "author") {
              return commit.shortAuthor || "[no author]";
            }
            return commit.shortSubject || "[no subject]";
        });

        newCommits
          .insert("div")
          .classed("flex", true);
        newCommits
          .insert("span")
          .classed("commit-comment", true);
        newCommits
          .insert("span")
          .classed("commit-ignore", true);
        newCommits
          .insert("span")
          .classed("commit-revert", true);
        newCommits
          .insert("span")
          .classed("commit-reland", true);

        // On the other side, conditionally draw iron icons for comments, relands, reverts.
        this._addIronIcon(newCommits.select(".commit-comment"), "communication:chat", "tiny", function(commit){
          return commit.comments && commit.comments.length > 0;
        });
        this._addIronIcon(newCommits.select(".commit-ignore"), "icons:block", "tiny", function(commit){
            return commit.ignoreFailure;
        });
        var reverts = this._addIronIcon(newCommits.select(".commit-revert"), "icons:undo", "tiny fg-failure", function(commit){
          var reverterCommit = reverted_map[commit.issue];
          return (reverterCommit !== undefined && reverterCommit.timestamp > commit.timestamp);
        });
        reverts.on("mouseover", function(commit){
          var reverterIssue = reverted_map[commit.issue].issue;
          d3.select("#"+commit.patchStorage+reverterIssue).classed("bg-failure", true);
        })
        reverts.on("mouseleave", function(commit){
          d3.selectAll(".commit.bg-failure").classed("bg-failure", false);
        })
        var relands = this._addIronIcon(newCommits.select(".commit-reland"), "icons:redo", "tiny fg-success", function(commit){
          var relanderCommit = relanded_map[commit.issue];
          return (relanderCommit !== undefined && relanderCommit.timestamp > commit.timestamp);
        });
        relands.on("mouseover", function(commit){
          var relanderIssue = relanded_map[commit.issue].issue;
          d3.select("#"+commit.patchStorage+relanderIssue).classed("bg-success", true);
        });
        relands.on("mouseleave", function(commit){
          d3.selectAll(".commit.bg-success").classed("bg-success", false);
        });
      },

      // Adds iron icons to everything in the selection if shouldAddIcon returns truthy.  It
      // returns all icons that were added.
      _addIronIcon: function(selection, icon, classes, shouldAddIcon) {
        return selection
          .html(function(commit){
            // The Polymer templates will pick this up and make it a real iron-icon element.
            // However, if you try to do .insert("iron-icon")... that does not work.
            if (shouldAddIcon === undefined || shouldAddIcon(commit)) {
              return "<iron-icon class=\""+classes+"\" icon=\"" + icon + "\"></iron-icon>";
            }
          });
      },

      // Draw all of the divs for the categories, including the header.
      _drawCategories: function(category_list, categories){
        var data = d3.select(this.$.table).selectAll(".category")
          .data(category_list, function(category){
            return category;
          });
        data.exit().remove();
        var newCategories = data
          .enter()
          .append("div")
          .classed("category",true);
        data.order();
        data
          .style("flex-grow", function(category){
            // This keeps the rows about as evenly sized as possible.
            // colspan is the total number of task specs in this category.
            return categories[category].colspan;
          });

        newCategories
          .insert("div")
          .classed("category-title", true)
          .text(function(category){
            return category;
          })
        // .subcategories will hold all of the .subcategory elements.
        newCategories
          .insert("div")
          .classed("subcategories", true);
      },

      // Draw all of the divs for the subcategories, including the header
      _drawSubCategories: function(categories) {
        d3.select(this.$.table).selectAll(".subcategories").each(function(category){
          if (!categories[category]) {
            return;
          }
          var list = categories[category].subcategoryList.map(function(subcat){
            return {
              "category": category,
              "subcategory": subcat,
            };
          });

          var data = d3.select(this)
            .selectAll(".subcategory")
            .data(list, function(d) {
              return d.category + d.subcategory;
            });
          data.exit().remove();
          var subcategories = data
            .enter()
            .insert("div")
            .classed("subcategory", true);
          data.order();
          data
            .style("flex-grow", function(d){
              // This keeps the rows about as evenly sized as possible.
              return categories[d.category].subcategories[d.subcategory].task_specs.length;
            });
          subcategories
            .insert("div")
            .classed("subcategory-title", true)
            .text(function(d){
              return d.subcategory;
            });
          // .task-specs will hold all of the .task-spec elements.
          subcategories
            .insert("div")
            .classed("task-specs", true);
        });
      },

      // draw all of the task spec columns, including the header box with the flaky, ignore_failure,
      // and comment icons
      _drawTaskSpecColumns: function(categories, taskSpecs, num_commits) {
        var addIronIcon = this._addIronIcon.bind(this);
        var openTaskSpecDialog = this._openTaskSpecDialog.bind(this);
        d3.select(this.$.table).selectAll(".task-specs").each(function(d){
          if (!categories[d.category].subcategories[d.subcategory]) {
            return;
          }
          var list = categories[d.category].subcategories[d.subcategory].task_specs.map(function(taskSpec){
            return {
              "category": d.category,
              "subcategory": d.subcategory,
              "taskSpec": taskSpec,
            };
          });

          var data = d3.select(this)
            .selectAll(".task-spec")
            .data(list, function(d) {
              return d.category + d.subcategory + d.taskSpec;
            });
          data.exit().remove();
          var newTaskSpecs = data
            .enter()
            .insert("div")
            .classed("task-spec", true);
          data.order();
          var titles = newTaskSpecs
            .insert("div")
            .classed("task-spec-title", true)
            .attr("title", function(d){
              return d.taskSpec;
            })
            .on("tap", function(d){
              // Stop the propogation so we don't immediately hide the popup we show.
              d3.event.stopPropagation();
              openTaskSpecDialog(d.taskSpec);
            });
          titles
            .insert("span")
            .classed("taskspec-comment", true);
          titles
            .insert("span")
            .classed("taskspec-ignore", true);
          titles
            .insert("span")
            .classed("taskspec-flaky", true);

          addIronIcon(data.selectAll(".taskspec-ignore"), "icons:block", "tiny", function(d){
            return taskSpecs[d.taskSpec].ignoreFailure;
          });
          addIronIcon(data.selectAll(".taskspec-flaky"), "image:texture", "tiny", function(d){
            return taskSpecs[d.taskSpec].flaky;
          });
          addIronIcon(data.selectAll(".taskspec-comment"), "communication:chat", "tiny", function(d){
            return taskSpecs[d.taskSpec].comments && taskSpecs[d.taskSpec].comments.length > 0;
          });

          newTaskSpecs
            .insert("div")
            .classed("task-spec-spacer", true);

          // Set the height so that flexing doesn't throw off the multi column alignment.
          newTaskSpecs
            .insert("div")
            .classed("tasks", true)
            .style("max-height", function(){
              return (TASK_HEIGHT * num_commits) + "px";
            });
            // .style("min-height", function(){
            //   return (TASK_HEIGHT * num_commits) + "px";
            // });
        });
      },

      // Draws the task divs.  We forego flexbox helping us align these.  First, we create a task
      // div (which is a fixed height) in side of it create a div with the various task classes to
      // set the heights/widths/margins etc.  This is easier to line up with the adjacent columns
      // and allows for more consistent zooming behavior.
      _drawTasks: function(commits, task_details) {
        var openTaskDialog = this._openTaskDialog.bind(this);
        var addIronIcon = this._addIronIcon.bind(this);

        d3.select(this.$.table).selectAll(".tasks").each(function(d){
          var list = commits.map(function(commit) {
            return {
              "category": d.category,
              "subcategory": d.subcategory,
              "taskSpec": d.taskSpec,
              "commit": commit,
              "displayClass": commit.displayClass[d.taskSpec] || [],
            };
          });
          var data = d3.select(this)
            .selectAll(".task")
            .data(list, function(d) {
              return d.category + d.subcategory + d.taskSpec + d.commit.hash;
            });
          data.exit().remove();
          var newTasks = data
            .enter()
            .insert("div")
            .classed("task",true)
            .insert("div")
            .on("tap", function(d){
              // Stop the propogation so we don't immediately hide the popup we show.
              d3.event.stopPropagation();
              openTaskDialog(d);
            });
          newTasks
            .insert("span")
            .classed("task-comment", true);
          data.order();
          // Style the inside div.
          data.each(function(d){
            var task = this.children[0];
            // Remove any previously-set classes.
            var removeClasses = [];
            for (var i = 0; i < task.classList.length; i++) {
              var c = task.classList.item(i);
              if (c.indexOf("bg-") === 0 || c.indexOf("task_") === 0) {
                removeClasses.push(c);
              }
            }
            removeClasses.forEach(function(c) {
              task.classList.remove(c);
            });

            // Add task display class.
            for (var i = 0; i < d.displayClass.length; i++) {
              task.classList.add(d.displayClass[i]);
            }

            task.title = d.taskSpec + " @ " + d.commit.shortHash;

            var details = task_details[d.commit.hash] && task_details[d.commit.hash][d.taskSpec];
            if (details) {
              // Add the new class.
              task.classList.add(task_details[d.commit.hash][d.taskSpec].colorClass);
              addIronIcon(d3.select(task).select(".task-comment"), "communication:chat", "tiny", function(){
                return details.comments && details.comments.length > 0 &&
                    (task.classList.contains(CLASS_TASK_SINGLE)
                  || task.classList.contains(CLASS_TASK_TOP));
              });
            } else {
              task.style["background-color"] = "";
              task.title = "";
            }
          });
        });
      },

      _openTaskDialog: function(task) {
        if (this._infoPopupOpen()) {
          return;
        }
        var details = this.task_details[task.commit.hash][task.taskSpec];
        if (details) {
          var taskInfo = document.createElement("task-popup-sk");
          taskInfo.task = details;
          taskInfo.repo = this.repo;
          taskInfo.repo_base = this.repo_base;
          taskInfo.commit_details = this.commits_map;
          taskInfo.parent = this;
          taskInfo.swarming_url = this.swarming_url;
          taskInfo.task_scheduler_url = this.task_scheduler_url;
          this._openDialog(taskInfo);
        }
      },

      _openTaskSpecDialog: function(taskSpec) {
        if (this._infoPopupOpen()) {
          return;
        }
        if (taskSpec) {
          var taskSpecInfo = document.createElement("taskspec-popup-sk");
          taskSpecInfo.task_spec = this.task_specs[taskSpec];
          taskSpecInfo.repo = this.repo;
          taskSpecInfo.swarming_url = this.swarming_url;
          this._openDialog(taskSpecInfo);
        }
      },

      _openCommitDialog: function(commit) {
        if (this._infoPopupOpen()) {
          return;
        }
        var commitInfo = document.createElement("commit-popup-sk");
        commitInfo.commit = commit;
        commitInfo.repo = this.repo;
        commitInfo.repo_base = this.repo_base;
        this._openDialog(commitInfo);
      },

      // Is the info popup open?
      _infoPopupOpen: function() {
        return this.$.infoDialog.opened;
      },

      // Set the dialog content and open the dialog.
      _openDialog: function(child) {
        this.$.infoDialog.innerHTML = '';
        this.$.infoDialog.appendChild(child);
        child.show();
      },
    });
  })()
  </script>
</dom-module>
