// PurplePart recv message and create log
// Copyright 2011 Google Inc. 
// see Purple/license.txt for BSD license
// johnjbarton@google.com

define(['log/consoleEntryRep','../resources/objRep','lib/reps', 'lib/Assembly', 'lib/part' ], 
function(ConsoleEntryRep, ObjRep, reps, Assembly, PurplePart) {
  
  'use strict';
  //------------------------------------------------------------------------------------
  // Implement PurplePart
  
  var EventLogViewport =  new PurplePart('EventLogViewport');  // 
  
  Assembly.addPartContainer(EventLogViewport);
  
  EventLogViewport.initialize = function() {
    this.scrollLock = false; // false means the viewport tracks the bottom of the log
    this.onPoll = this.poll.bind(this);
    this.pollInterval = 100;
    
    this.viewport = {
      rendered: { // these values are controlled by RenderedLines
        first: 0,
        last: 0
      },
      visible: {  // these values are controled by VisibleLines
        first: 0,
        last: 0
      }
    };
    reps.rehash();
  };
    
  EventLogViewport.connect = function(log) {
    log.registerPart(this); // for appendData notification that drive input to output (for now)
      this.initializeUI();
      if (this.optionPolling) {
        this.beginPolling();
      } else {
        this.endPolling();
      }
      this.update();
  };

  EventLogViewport.disconnect = function() {
      this.endPolling();
  };
  
  // -----------------------------------------------------------------------------------
  EventLogViewport.computeLineHeight = function() {
    return 14;
  };
  
  var renderedLines = {
    first: 0,
    total: 0,
    connect: function(elt) {
      this.container = elt;
    },
    isRendered: function(p_id) {
      return (p_id >= this.first && p_id < this.first + this.total); 
    },
    append: function(data, p_id) {
      var dataView = this.renderToHTML(p_id, data);
      if (dataView) {
        // debug
        var p_id_div = this.container.ownerDocument.createElement('span');
        p_id_div.classList.add('p_id');
        p_id_div.innerHTML = p_id;
        dataView.insertBefore(p_id_div, dataView.firstChild);
        this.container.appendChild(dataView);
      } 
    },
    renderToHTML: function(p_id, object) {
      var div = this.container.ownerDocument.createElement('div');

      try {
        var rep;
        if (object && object.rep) {
          rep = object.rep;
        } else {
          rep = reps.getRepByObject(object);
        }
        // The rep tags are 'controllers/views', $object is their model
        // tag.subject is set by domplate() to the tag, use the default here
        var tag = rep.shortTag || rep.tag;
        tag.replace({object: object}, div);
      } catch (exc) {
          consoleEntryRep.InternalExceptionTag.tag.replace({object: exc}, div, consoleEntryRep.InternalExceptionTag);
      }
      return div;
    },
    renderToString: function(object) {
      var str = "";
      if(object.toString() === '[object MessageEvent]') {
        str = object.type +" event " + this.summary(object.data);
      } else {
        str = 'Not a MessageEvent,' + this.summary(object);
      }
      return str;
    },
    summary: function(obj) {
      if (!obj) {
        return 'falsy';
      } 
      var objType = typeof obj;
      if (objType === 'string') {
        return obj;
      }
      if (objType !== 'object') {
        return objType;
      }
      var keys = Object.keys(obj);
      var str = '{' + keys.join(',')+'}';
      if (str.length < 100) {
        var sub = [];
        keys.forEach(function (key) {
          sub.push( key+':'+renderedLines.summary(obj[key]) );
        });
        str = '{' + sub.join(',') +'}';
      }
      return str;
    }
  };
  
  EventLogViewport.initializeUI = function () {
    var logElement = document.getElementById('log');
    renderedLines.connect(logElement);
  };

  //-------------------------------------------------------
  // Query the indexes for entries from event p_id that match the constraints.
  EventLogViewport.pullEntry = function(p_id) {
    var constraint = {  // TODO from findAnything
      matches: function(entry) {
        return true;
      }
    };
    // We want to visit each index so they all can contribute items from p_id.
    // p_id is a proxy for 'time': 
    //   every log entry that can ever appear in the viewport must have a p_id
    //   p_id increase monotonically
    //   an index may or may not have an entry for a p_id
    this.forEachPart(function filterAndAppendMatches(index) {
      var indexEntry = index.get(p_id);
      if (indexEntry) {
        if(constraint.matches(indexEntry)) {
            renderedLines.append(indexEntry, p_id);
        }
      }
    });
  };

  EventLogViewport.update = function() {
    if (!this.scrollLock) {
      var max = window.purple.p_id; // TODO via initialize
      var last = this.viewport.visible.last; 
      // work bottom up and stop once we fill the viewport
      for (var ndx = last; ndx <= max; ndx++) {
        this.pullEntry(ndx);
      }
      this.viewport.visible.last = max;
    }
    delete this.queueUpdate;
  };
  
  EventLogViewport.boundUpdate = EventLogViewport.update.bind(EventLogViewport);
  
  EventLogViewport.appendData = function (data, p_id) {
    if (!this.queueUpdate) {
      this.queueUpdate = EventLogViewport.boundUpdate;
      window.setTimeout(this.queueUpdate);
    }
  };
  
  EventLogViewport.poll = function(event) {
    console.log("EventLogViewport poll", event);
    this.update();
  };
  
  EventLogViewport.beginPolling = function() {
    this.pollingId = window.setInterval(this.onPoll, this.pollInterval);
  };
  
  EventLogViewport.endPolling = function() {
    if (this.pollingId) {
      window.clearInterval(this.pollId);
    }
  };
  
  // ---------------------------------------------------------------------------------
  
  
  return EventLogViewport;
  
});
@@ -1206,24 +1206,28 @@
 r now)%0D%0A    
+%0D%0A  
   this.initi
@@ -1234,26 +1234,24 @@
 alizeUI();%0D%0A
-  
     if (this
@@ -1265,26 +1265,24 @@
 Polling) %7B%0D%0A
-  
       this.b
@@ -1293,34 +1293,32 @@
 Polling();%0D%0A    
-  
 %7D else %7B%0D%0A      
@@ -1307,26 +1307,24 @@
   %7D else %7B%0D%0A
-  
       this.e
@@ -1333,39 +1333,35 @@
 Polling();%0D%0A    
-  
 %7D%0D%0A
-  
     this.update(

correct formatting