﻿/**
 * A panel on the list pages.
 *
 * @param id	The id of the panel
 * @param title	The title to display on the panel
 * @param styleId	A style genrenated for the panel - Optional
 */
function RecordListPanel(id, title, styleId)
{
  this.id = id;
  this.title = title;
  this.className = null;
  if (styleId)
    this.styleId = styleId;
  this.parent = null;
  this.headerContent = new Array();
  this.childContent = null;
  this.width = null;
  this.spacerSize = 10;
  this.siblingLeft = null;
  this.bottomPanel = false;
  this.siblingBelow = null;
  this.collapseDirection = RecordListPanel.statics.collapseDirection.vertical;
  
  this.onResize = new REvent();
  this.onScroll = new REvent();
  this.onExpandCollapse = new REvent();
  this.onPanelClick = new REvent();
  
  this.onExpandCollapse.addEventListener(new REventListener(this.expandCollapse, this));
  this.onPanelClick.addEventListener(new REventListener(this.horizontalExpand, this));
  
  RegisterControl.statics.getInstance().add(this);
}

RecordListPanel.statics = new Object();
RecordListPanel.statics.collapseDirection = new Object();
RecordListPanel.statics.collapseDirection.vertical = 0;
RecordListPanel.statics.collapseDirection.horizontal = 1;

/**
 * Sets the title of the panel
 *
 * @param title	The title to display on the panel
 */
RecordListPanel.prototype.setTitle = function(title)
{
  this.title = title;
}

/**
 * Sets the desired width of the panel.  If null it will take all the width.
 *
 * @param title	The desired width of the panel
 */
RecordListPanel.prototype.setWidth = function(w)
{
  this.width = w;
}

/**
 * Sets the panel that this panel should be below.
 * Right now there can only be one panel stacked vertically, the layout code will have to be updated to support more
 *
 * @param panel	The panel that the panel shoudl be under
 */
RecordListPanel.prototype.setBelowPanel = function(panel)
{
  this.bottomPanel = true;
  panel.siblingBelow = this;
}

/**
 * Sets the panel that is to the left of this panel
 *
 * @param panel	The panel that the panel shoud be on the left of this panel
 */
RecordListPanel.prototype.setLeftPanel = function(panel)
{
  this.siblingLeft = panel;
}

/**
 * Sets the direction that the panel collapses
 *
 * @param collapseDirection	The direction that the panel should collapse.  One of RecordListPanel.statics.collapseDirection
 */
RecordListPanel.prototype.setCollapseDirection = function(collapseDirection)
{
  this.collapseDirection = collapseDirection;
}

/**
 * Gets the direction that the panel collapses
 *
 * @returns The direction the panel collapses
 */
RecordListPanel.prototype.GetCollapseDirection = function()
{
  return this.collapseDirection;
}

/**
 * Adds content to display in the header
 * the content must implement the IRecordListPanelHeaderContent interface
 *
 * @param content	The content to add to the panel header
 */
RecordListPanel.prototype.addHeaderContent = function(content)
{
  this.headerContent.push(content);
  if(this.parent)
    content.init(this);
}

/**
 * Sets the content to be displayed in the panel
 * the content must implement the IRecordListPanelChildContent interface
 *
 * @param content	The content that the panel will display
 */
RecordListPanel.prototype.setChildContent = function(content)
{
  this.childContent = content;
  if(this.parent)
    content.init(this);
}

/**
 * Attaches the panel to a DOM node.
 *
 * @param node	The the DOM node to put the panel in
 */
RecordListPanel.prototype.attach = function(node)
{
  var panel = document.createElement("div");
  panel.id = RegisterControl.statics.encodeId(this);
  panel.className = "panel";
  if (this.styleId)
    panel.className += " " + this.styleId;
  node.appendChild(panel);
  
  var cap = document.createElement("div");
  cap.className = 'cap0';
  panel.appendChild(cap);
  cap = document.createElement("div");
  cap.className = 'cap1';
  panel.appendChild(cap);
  cap = document.createElement("div");
  cap.className = 'cap2';
  panel.appendChild(cap);
  
  var header = document.createElement("h2");
  header.id = RegisterControl.statics.encodeId(this, "header");
  
  if(RecordListPanel.statics.collapseDirection.horizontal == this.collapseDirection && this.childContent && this.childContent.isCollapsible())
  {
    var img = document.createElement("img");
    img.id = RegisterControl.statics.encodeId(this, "expandCollapse");
    if(this.childContent.getCollapsed())
    {
      img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9k68FKJz6zutNU7X5BgMr0NUqEXSKnYHm22JmoQce3oPQ2&t=633294381740000000';
    }
    else
      img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9nvsoZWMG9Lu5afX-jGvqd9mQ8PSMdIubg7fd6urpGzog2&t=633294381740000000';
    img.onclick = RecordListPanel.statics.onExpandCollapse;
    img.className = 'headerContent';
    header.appendChild(img);
  }
  else if(this.bottomPanel && this.childContent && this.childContent.isCollapsible())
  {
    var img = document.createElement("img");
    img.id = RegisterControl.statics.encodeId(this, "expandCollapse");
    if(this.childContent.getCollapsed())
      img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9mij_PGvTEMB58AqN5noBsQ0&t=633294381740000000';
    else
      img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9mMGVRGFUjKMyLR9xsSEdYrwq2k2LFrkCijPwAzdSRLYQ2&t=633294381740000000';
    img.onclick = RecordListPanel.statics.onExpandCollapse;
    img.className = 'headerContent';
    header.appendChild(img);
  }
  
  for (var i in this.headerContent)
  {
    var div = document.createElement("div");
    div.className = 'headerContent';
    header.appendChild(div);
    this.headerContent[i].attach(div);
  }

  var titleSpan = document.createElement("span");
  titleSpan.appendChild(document.createTextNode(this.title));
  header.appendChild(titleSpan);
  panel.appendChild(header);

  var content = document.createElement("div");
  content.id = RegisterControl.statics.encodeId(this, "content");
  content.onscroll = RecordListPanel.statics.onScroll;
  content.className = "content";
  panel.appendChild(content);

  if(this.childContent)
  {
    if(this.childContent.handlesScrolling())
      content.style.overflow = 'hidden';
    this.childContent.attach(content);
  }
}

/**
 * Inititializes the panel and calls init on any children it has
 *
 * @param parent	The parent object of thie panel
 */
RecordListPanel.prototype.init = function(parent)
{
  this.parent = parent;
  
  for (var i in this.headerContent)
  {
    this.headerContent[i].init(this);
  }  
  
  if(this.childContent)
    this.childContent.init(this);
}

/**
 * Sizes and positions the panel inside of its parent
 */
RecordListPanel.prototype.resize = function()
{
  var panel = document.getElementById(RegisterControl.statics.encodeId(this));
  panel.style.top = this.getTop(panel.parentNode) + "px";
  panel.style.left = this.getLeft(panel.parentNode) + "px";
  panel.style.width = this.getWidth(panel.parentNode) + "px";
  panel.style.height = this.getHeight(panel.parentNode) + "px";
  
  var content = document.getElementById(RegisterControl.statics.encodeId(this, "content"));
  var contentOffsetTop = content.offsetTop;
  var remainingHeight = parseInt(content.parentNode.offsetHeight) - contentOffsetTop - 2;
  var remainingWidth = parseInt(content.parentNode.offsetWidth) - 2;
  content.style.height = ((0<remainingHeight)?remainingHeight:1) + "px";
  content.style.width = ((0<remainingWidth)?remainingWidth:1) + "px";

  this.onResize.trigger();
}

// fixme: functions to calculate the panel size do not take into account having more than two panels vertically

/**
 * Figures out where the top of the panel should be
 *
 * @param node	The parent node of the panel
 */
RecordListPanel.prototype.getTop = function(node)
{
  var parentPos = Coordinate.Statics.findPos(node);
  if(this.bottomPanel)
  {
    var top = parentPos.y + Math.ceil((node.offsetHeight + this.spacerSize) / 2);
    if(this.childContent)
    {
      var requiredSize = this.childContent.getDesiredHeight();
      if ((this.childContent.isCollapsible() && this.childContent.getCollapsed()) || 0<requiredSize)
      {
        var header = document.getElementById(RegisterControl.statics.encodeId(this, "header"));
        var top2 = node.offsetHeight - this.spacerSize - header.offsetHeight - requiredSize;
        top2 = (0<top2) ? (parentPos.y + top2) : (parentPos.y);
        if (0<requiredSize && !(this.childContent.getCollapsed()))
          return (top2<top) ? top : top2;
        return top2;
      }
      return top;
    }
    else
    {
      return top;
    }
  }
  else
  {
    return parentPos.y;
  }
}

/**
 * Figures out where the left of the panel should be
 *
 * @param node	The parent node of the panel
 */
RecordListPanel.prototype.getLeft = function(node)
{
  if (this.siblingLeft)
    return this.siblingLeft.getLeft(node) + this.siblingLeft.getWidth(node) + this.spacerSize;
  return Coordinate.Statics.findPos(node).x;
}

/**
 * Figures out what the width of the panel should be
 *
 * @param node	The parent node of the panel
 */
RecordListPanel.prototype.getWidth = function(node)
{
  if(RecordListPanel.statics.collapseDirection.horizontal == this.collapseDirection && this.childContent.getCollapsed())
    return 85;
  if(this.width)
    return this.width;
  var width = node.offsetWidth - this.getLeft(node) + Coordinate.Statics.findPos(node).x;
  if (0<width)
    return width;
  return 1;
}

/**
 * Figures out what the height of the panel should be
 *
 * @param node	The parent node of the panel
 */
RecordListPanel.prototype.getHeight = function(node)
{
  var parentPos = Coordinate.Statics.findPos(node);
  var height = 0;
  if (this.siblingBelow)
  {
    height = this.siblingBelow.getTop(node) - parentPos.y - this.spacerSize;
  }
  else if(this.bottomPanel)
  {
    height = parentPos.y + node.offsetHeight - this.getTop(node) - this.spacerSize;
  }
  else
  {
    height = node.offsetHeight - this.spacerSize;
  }
  
  if (0<height)
    return height;
  return 1;
}

/**
 * Gets the id of the panel
 *
 * @returns	The id of the panel
 */
RecordListPanel.prototype.getId = function()
{
  return this.id;
}

/**
 * Toggles the expanded / collapsed state of the panel
 */
RecordListPanel.prototype.expandCollapse = function()
{
  var img = document.getElementById(RegisterControl.statics.encodeId(this, "expandCollapse"));
  this.childContent.setCollapsed(!this.childContent.getCollapsed());
  if(RecordListPanel.statics.collapseDirection.vertical == this.collapseDirection)
  {
    if (img)
    {
      if(this.childContent.getCollapsed())
        img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9mij_PGvTEMB58AqN5noBsQ0&t=633294381740000000';
      else
        img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9mMGVRGFUjKMyLR9xsSEdYrwq2k2LFrkCijPwAzdSRLYQ2&t=633294381740000000';
    }
  }
  else
  {
    if(this.childContent.getCollapsed())
    {
      if (img)
        img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9k68FKJz6zutNU7X5BgMr0NUqEXSKnYHm22JmoQce3oPQ2&t=633294381740000000';
    }
    else
    {
      if (img)
        img.src = 'WebResource.axd?d=bjB1kThl5P8nlZxTJNmQFL5dRRCDIWLn7ZVo9sunYGDIb6f-edYidyloNxyeJDhISRfZ0Fq5qJI6Goz1K9zynDAzTKPmnwFdrkFlbyWHS9nvsoZWMG9Lu5afX-jGvqd9mQ8PSMdIubg7fd6urpGzog2&t=633294381740000000';
    }
  }
}

/**
 * Static functions to get called DOM events from the gui and trigger the appropriate REvent
 */
RecordListPanel.statics.eventDispatch = function(id, eventName, jsEvent)
{
  // try and normalize the js event a bit
  if(!jsEvent)
    jsEvent = window.event;
  if(jsEvent)
  {
    if (!jsEvent.target) 
      jsEvent.target = jsEvent.srcElement;
  }
  var params = new Array();
  var instance = RegisterControl.statics.decodeId(id, params);
  instance[eventName].trigger(jsEvent);
}
RecordListPanel.statics.onScroll         = function(event) { RecordListPanel.statics.eventDispatch(this.id, "onScroll", event); }
RecordListPanel.statics.onExpandCollapse = function(event) { RecordListPanel.statics.eventDispatch(this.id, "onExpandCollapse", event); }
RecordListPanel.statics.onPanelClick = function(event) { RecordListPanel.statics.eventDispatch(this.id, "onPanelClick", event); }



/**
 * An interface that panel content should implement
 */
function IRecordListPanelChildContent()
{
}
/**
 * Called during setup to allow the content to initialize itself.  Eg register events on the parent
 *
 * @param parent	The parent of the content, the panel it is added to
 */
IRecordListPanelChildContent.prototype.init = function(parent)
{
}
/**
 * Used to tell the panel if the panel should handle scrolling or if the content will do it itself
 *
 * @returns if the content handles its own scrolling
 */
IRecordListPanelChildContent.prototype.handlesScrolling = function()
{
  return false;
}
/**
 * Used to tell the panel if the panel if the content is collapsible
 *
 * @returns if the content is collapsible
 */
IRecordListPanelChildContent.prototype.isCollapsible = function()
{
  return false;
}
/**
 * Gets the present collapsed state of the content
 *
 * @returns if the content is in its collapsed state
 */
IRecordListPanelChildContent.prototype.getCollapsed = function()
{
  return false;
}
/**
 * Sets the collapsed state of the content
 *
 * @param collapsed	If the content should be collapsed or not
 */
IRecordListPanelChildContent.prototype.setCollapsed = function(collapsed)
{
}
/**
 * Gets the amount of vertical space the content would like.
 *
 * @returns The height it would like
 */
IRecordListPanelChildContent.prototype.getDesiredHeight = function()
{
  return 0;
}


/**
 * An interface that header content should implement
 */
function IRecordListPanelHeaderContent()
{
}
/**
 * Called during setup to allow the content to initialize itself.  Eg register events on the parent
 *
 * @param parent	The parent of the content, the panel it is added to
 */
IRecordListPanelHeaderContent.prototype.init = function(parent)
{
}
