/*  $Id: locator.js 11436 2009-10-14 20:21:10Z rallj $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
 *               National Center for Biotechnology Information
 *
 *  This software/database is a "United States Government Work" under the
 *  terms of the United States Copyright Act.  It was written as part of
 *  the author's official duties as a United States Government employee and
 *  thus cannot be copyrighted.  This software/database is freely available
 *  to the public for use. The National Library of Medicine and the U.S.
 *  Government have not placed any restriction on its use or reproduction.
 *
 *  Although all reasonable efforts have been taken to ensure the accuracy
 *  and reliability of the software and data, the NLM and the U.S.
 *  Government do not and cannot warrant the performance or results that
 *  may be obtained by using this software or data. The NLM and the U.S.
 *  Government disclaim all warranties, express or implied, including
 *  warranties of performance, merchantability or fitness for any particular
 *  purpose.
 *
 *  Please cite the author in any work or product based on this material.
 *
 * ===========================================================================
 *
 * Authors:  Vlad Lebedev
 *
 * File Description: Locator for the overview panel & alignment panel
 *
 */
 
 
/* locator */
function Locator(idx, color, resizable) {
   this.idx = idx; // view index
   tmpl_string = '<div id="seq_g{idx}" style="position:absolute;top:0px;left:0px;width:1px;">';
   tmpl_string += '<div id="pan_scroller_{idx}" class="pan-bar" style="background-color:#{color};"></div><div class="locator_rect"></div>';
   if (resizable) {
      tmpl_string += '<div id="left_resizer_{idx}" class="left-resizer"></div><div id="right_resizer_{idx}" class="right-resizer"></div>';
   }
   tmpl_string += '</div>';
      
   var tpl = new Ext.Template(tmpl_string);

   this.element = tpl.insertFirst(Ext.get('panorama_id'), {idx:this.idx, qtip:'View #', color:color, adjheight: m_PanoramaHeight-19}, true);
   this.element.setHeight( m_PanoramaHeight-2 );
}
Locator.prototype.getElement = function() { return this.element; }
Locator.prototype.setColor = function(color) { Ext.get('pan_scroller_'+this.idx).setStyle('background-color', '#'+color); }
Locator.prototype.setHeight = function(h) { this.element.setHeight( h );  Ext.util.CSS.updateRule(".locator_rect","height",(h - 17) + "px");}






/* 
 *
 * File Description: Multiple alignment view panel
 *
 */
var m_AlignViewPageSize = 500;

SeqApp.createAlignment = function(new_config) {
   idx = m_GViewCounter;
   the_id = 'alignment_id' + idx;
   
   spacer = m_SeqApp.add({border:false, height:m_SpacerHeight}); // spacer
   
   var cp = new Ext.ColorPalette();
   cur_color = cp.colors[Math.round( Math.random() * cp.colors.length)];

   if (!new_config['color']) new_config['color'] = cur_color; // view color (from url or at random)
   else cur_color = new_config['color'];
   
   tbar = [
      {text:SeqApp.colorBarTPL.apply({idx:idx, color:cur_color}), tooltip:'View Color', menu:new Ext.menu.ColorMenu({idx:idx, listeners: {'select': function(cm, color) {
            Ext.get('view_color_'+this.idx).setStyle('background-color', '#'+color);
            m_GViews[this.idx]['locator'].setColor(color);
            m_GViews[this.idx]['color'] = color;
            Reflection.reCreateReflections();
      }}})}, '-',
      {iconCls:'zoom_plus', tooltip:'Zoom In', idx:idx, handler:function() {SeqApp.zoomInAlign(this.idx);} }, 
      {iconCls:'zoom_minus', tooltip:'Zoom Out', idx:idx, handler:function() {SeqApp.zoomOutAlign(this.idx);} }, 
      {iconCls:'zoom_seq', tooltip:'Zoom To Sequence', idx:idx, handler:function() {SeqApp.zoomSeqAlign(this.idx);} },
      '-',
      {iconCls:'prev', tooltip:'Prev Page', idx:idx, handler:function() { SeqApp.gotoAlignmentPrev(this.idx); }},'-',
      {iconCls:'next', tooltip:'Next Page', idx:idx, handler:function() { SeqApp.gotoAlignmentNext(this.idx); }},'->',
      {iconCls:'x-tbar-loading', id:'seq-view-loading-'+idx, tooltip:'Reload View', idx:idx, handler:SeqApp.reloadAlignmentImage }
   ];
   
   tools = [
      {id:'close', qtip:'Close View', handler:function(e, target, panel) { 
         idx = panel.idx;
         config = m_GViews[idx];
         config['locator'].getElement().remove(); // remove locator form panoram

         panel.ownerCt.remove(config['spacer'], true);
         panel.ownerCt.remove(panel, true);
         m_GViews[idx] = null;
         Reflection.reCreateReflections();
      } }
   ];
   
   view = m_SeqApp.add( {collapsible:true, title:'Loading...',
      titleCollapse:true, tools:tools, idx:idx, tbar:tbar, html:'<div class="alignment_div" id="'+the_id+'"/>'}// + map_ctrl} 
   );
   m_SeqApp.doLayout();
   
   Ext.get(the_id).on({
        //'mousedown' : SeqApp.onGViewMouseDown,//onPanoramaMouseDown,
        //'mouseup' : SeqApp.onGViewMouseUp, //onPanoramaMouseUp,
        'dblclick': SeqApp.onAlnViewDblClick,
        'mousemove' : SeqApp.onAlnViewMouseMove,
        'contextmenu':SeqApp.onAlnViewContextMenu,
        scope: this
   });
   
   // Init view data      
   new_config['idx']    = idx,
   new_config['view']   = view;
   new_config['type']   = 'alignment';
   new_config['spacer'] = spacer;
   new_config['the_id'] = the_id;
   new_config['scroll_pix'] = 0;
   new_config['top_offset'] = 0;
   new_config['flip'] = false;
   new_config['expand'] = '';
   
   m_GViews[idx] = new_config;
   m_GViews[idx]['locator'] = new Locator(idx, cur_color, true);
   m_GViewCounter++;
   SeqApp.loadAlignmentImage(new_config, new_config['from_seq'], new_config['len_seq']);
}


SeqApp.reloadAlignmentImage = function() {
   cfg = SeqApp.getAlignment();
   if (cfg) SeqApp.loadAlignmentImage(cfg, cfg['vis_from_seq'], cfg['vis_len_seq']);
}


SeqApp.loadAlignmentImage = function(config, from, len) {
   width = panorama['view'].getInnerWidth() - 2;
   url = theAlignmentCGI + '&view=aln&client=assmviewer&width='+width+'&from='+from+'&len='+len;
   if (config['expand'].length>0) url += '&expand=' + config['expand'];
   
   Ext.getCmp('seq-view-loading-'+config['idx']).disable();
   Ext.Ajax.request({url:url, success:function(res) { 
      from_cgi = Ext.decode(res.responseText);
      Ext.getCmp('seq-view-loading-'+config['idx']).enable();
      
      the_div = Ext.get( config['the_id'] );
      
      config['from_cgi'] = from_cgi;
      config['vis_from_seq'] = from_cgi['from'];
      config['vis_to_seq'] = from_cgi['to'];
      config['vis_len_seq'] = from_cgi['to'] - from_cgi['from'];
      config['seq_length'] = from_cgi['seq_length'];
      m_AlignViewPageSize = config['vis_len_seq'];// / 3;
      
      the_div.setStyle('background-image', 'url(' + from_cgi['img_url'] + ')'); 
      the_div.setStyle('height', from_cgi['img_height']+'px' );

      SeqApp.updateTitle(config);
      //SeqApp.doExtensionPoint('alignment_image_loaded', config);
   }}); // Ext.Ajax
}



SeqApp.zoomInAlign = function(idx) {
   config = m_GViews[idx];
   new_len  = config['vis_len_seq'] / 2;
   new_from = config['vis_from_seq'] + new_len / 2;
   
   SeqApp.loadAlignmentImage(config, new_from, new_len);
}

SeqApp.zoomSeqAlign = function(idx) {
   config = m_GViews[idx];
   new_len  = 100;//config['vis_len_seq'] / 2000;
   new_from = config['vis_from_seq'] + new_len / 2;

   SeqApp.loadAlignmentImage(config, new_from, new_len);
}


SeqApp.zoomOutAlign = function(idx) {
   config = m_GViews[idx];
   new_len  = config['vis_len_seq'] * 2;
   new_from = config['vis_from_seq'] - config['vis_len_seq'] / 2;
   
   new_from = Math.max(0, new_from); // not to exteed the sequence range
   if (new_from + new_len > config['seq_length']) new_len = config['seq_length'] - new_from;

   SeqApp.loadAlignmentImage(config, new_from, new_len);
}

SeqApp.gotoAlignmentPrev = function(idx) {
   config = m_GViews[idx];
   
   new_from = Math.max(0, config['vis_from_seq'] - m_AlignViewPageSize);
   //new_to   = Math.min(config['vis_from_seq'] + m_AlignViewPageSize, config['vis_len_seq']);
   //new_len  = new_to - new_from;
   
   SeqApp.loadAlignmentImage(config, new_from, config['vis_len_seq']);
}

SeqApp.gotoAlignmentNext = function(idx) {
   config = m_GViews[idx];

   new_from = Math.min(config['vis_from_seq']  + m_AlignViewPageSize - 1, config['seq_length'] - m_AlignViewPageSize);
   new_from = Math.max(0, new_from);
   //new_to   = Math.min(new_from+m_AlignViewPageSize, config['seq_length']);
   //new_len  = new_to - new_from;

   SeqApp.loadAlignmentImage(config, new_from, config['vis_len_seq']);
}

SeqApp.getAlignment = function() {
   for (v in m_GViews) {
      config = m_GViews[v];
      if (config && config['type'] == 'alignment') return config;//['view'];
   }
   return null;
}

SeqApp.onAlnViewMouseMove = function (e) { 
      elem = e.getTarget().id;
      if (elem.indexOf('alignment_id') == 0) { // GView
         idx = elem.substr(elem.length-1, 1);

         config = m_GViews[idx];
         area = SeqApp.hitTestAlign(idx, e.getXY());

         cur_target = Ext.get( config['the_id'] );

         if (area && !config['selection']) {
            cur_target.setStyle('cursor', 'pointer');
            config['selection'] = new AlignSelection(idx, area);
         } else if (config['selection']) {
            cur_target.setStyle('cursor', 'default');
            if (config['selection'].qtip) {
               config['selection'].qtip.destroy()
            }
            config['selection'].getElement().remove();
            config['selection'] = null;
         }
            //
            //
      }
}


SeqApp.hitTestAlign = function(idx, page_xy) {
   config = m_GViews[idx];

   elem_xy = Ext.get( config['the_id'] ).getXY();
   xx = page_xy[0] - elem_xy[0];// - config['scroll_pix'];
   yy = page_xy[1] - elem_xy[1];// - config['top_offset'];
   for (a in config['from_cgi']['checkboxes']) {
      area = config['from_cgi']['checkboxes'][a];
      the_x = area['x'];
      the_y = area['y'];
      the_w = area['w'];
      the_h = area['h'];
      if (xx >= the_x-1 && xx <= the_x+the_w && yy >= the_y-1 && yy <= the_y+the_h) return area; // add extra pixel
   }
   return null;
}


SeqApp.onAlignViewClick = function(e)
{
   elem = e.getTarget().id;
   idx = elem.substr(elem.length-1, 1);
   area = SeqApp.hitTestAlign(idx, e.getXY());
   if (area) { // open alignment
      cur_name = area['name'];
      cur_expand = m_GViews[idx]['expand'];
      e_array = cur_expand.length > 0 ? cur_expand.split(',') : [];
      expanded = false;

      for (i = 0;  i != e_array.length;  i++) {
         if (e_array[i]==cur_name) {
            expanded = true;
            delete e_array[i];
            break;
         }
      }
      
      if (!expanded) e_array.push(cur_name);
      m_GViews[idx]['expand'] = e_array.join(',');      
      
      SeqApp.reloadAlignmentImage();
   }
}


SeqApp.onAlnViewContextMenu = function(e) {
   e.preventDefault();  // this prevents the default contextmenu to open in Firefox (linux)
   e.stopPropagation();
   elem = e.getTarget().id;
   
   menu = new Ext.menu.Menu();
   if (elem.length>0) {
         idx = elem.substr(elem.length-1, 1);
         
         menu.add({iconCls:'zoom_plus', text:'Zoom In', idx:idx, handler:function() {SeqApp.zoomInAlign(this.idx);} });
         menu.add({iconCls:'zoom_minus', text:'Zoom Out', idx:idx, handler:function() {SeqApp.zoomOutAlign(this.idx);} });
         menu.add('-');
         menu.add({iconCls:'zoom_seq', text:'Zoom To Sequence', idx:idx, handler:function() {SeqApp.zoomSeqAlign(this.idx);} });
         menu.add('-');
         menu.add({iconCls:'expand_all', text:'Expand All', idx:idx, handler:function() {SeqApp.expandAllAlign(this.idx);} });
         menu.add({iconCls:'collapse_all', text:'Collapse All', idx:idx, handler:function() {SeqApp.collapseAllAlign(this.idx);} });
         menu.add('-');
         menu.add({iconCls:'prev', text:'Prev Page', idx:idx, handler:function() {SeqApp.gotoAlignmentPrev(this.idx);} });
         menu.add({iconCls:'next', text:'Next Page', idx:idx, handler:function() {SeqApp.gotoAlignmentNext(this.idx);} });
   }
   if (menu.items.length>0) menu.showAt(e.getXY());
}


SeqApp.onSyncAlignView = function(seq_idx) {
   cfg = SeqApp.getAlignment();
   seq_cfg = m_GViews[idx];
   if (cfg) SeqApp.loadAlignmentImage(cfg, seq_cfg['vis_from_seq'], seq_cfg['vis_len_seq']);
}

SeqApp.onAlnViewDblClick = function() {
   elem = e.getTarget().id;
   idx = elem.substr(elem.length-1, 1);
   config = m_GViews[idx];
}


SeqApp.expandAllAlign = function(idx) {
   config = m_GViews[idx];
   e_array = [];
   
   for (a in config['from_cgi']['checkboxes']) 
         e_array.push( config['from_cgi']['checkboxes'][a]['name'] );
   
   m_GViews[idx]['expand'] = e_array.join(',');   
   SeqApp.reloadAlignmentImage();
}

SeqApp.collapseAllAlign = function(idx) {
   config = m_GViews[idx];
   m_GViews[idx]['expand'] = '';
   SeqApp.reloadAlignmentImage();
}


