/*
 * ObjectBrowser.java
 *
 * Copyright (C) 2009-17 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

package org.rstudio.studio.client.workbench.views.connections.ui;

import java.util.HashSet;
import java.util.Set;

import org.rstudio.core.client.widget.ProgressPanel;
import org.rstudio.core.client.widget.SimplePanelWithProgress;
import org.rstudio.studio.client.workbench.views.connections.model.Connection;
import org.rstudio.studio.client.workbench.views.connections.model.DatabaseObject;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.BorderStyle;
import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.cellview.client.CellTree.CellTreeMessages;
import com.google.gwt.user.cellview.client.TreeNode;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class ObjectBrowser extends Composite implements RequiresResize
{
   public ObjectBrowser()
   {
      hostPanel_ = new SimplePanelWithProgress();
      scrollPanel_ = new ScrollPanel();
      scrollPanel_.setSize("100%", "100%");
      hostPanel_.setWidget(scrollPanel_);
      connection_ = null;
       
      // init widget
      initWidget(hostPanel_);
   }
  
   public void clear()
   {
      if (objectsModel_ != null)
         objectsModel_.clear();
      connection_ = null;
      objectsModel_ = null;
   }
   
   public void update(Connection connection, String hint)
   { 
      final Set<DatabaseObject> expandedNodes = new HashSet<DatabaseObject>();
      
      // if this update is for the currently visible connection in the model,
      // cache the set of expanded nodes for replay
      if (objects_ != null && connection == connection_)
      {
         TreeNode rootNode = objects_.getRootTreeNode();
         if (!objects_.getRootTreeNode().isDestroyed())
         {
            for (int i = 0; i < rootNode.getChildCount(); i++)
            {
               if (rootNode.isChildOpen(i))
               {
                  DatabaseObject node = (DatabaseObject)rootNode.getChildValue(i);
                  expandedNodes.add(node);
               }
            }
         }
      }
      
      // create tables model and widget
      objectsModel_ = new ObjectBrowserModel();
      
      // capture scroll position
      final int scrollPosition = scrollPanel_.getVerticalScrollPosition();

      // show progress while updating the connection
      hostPanel_.showProgress(50, "Loading objects");
            
      // update the table then restore expanded nodes
      objectsModel_.update(
         connection,      // connection 
         expandedNodes,
         new Command() {   // table update completed, expand nodes
            @Override
            public void execute()
            {
               // clear progress and show the object tree again
               hostPanel_.setWidget(scrollPanel_);
               
               // restore expanded nodes
               TreeNode rootNode = objects_.getRootTreeNode();
               if (!rootNode.isDestroyed())
               {
                  for (int i = 0; i < rootNode.getChildCount(); i++)
                  {
                     final DatabaseObject nodeVal = 
                           (DatabaseObject)(rootNode.getChildValue(i));
                     for (DatabaseObject expanded: expandedNodes)
                     {
                        if (expanded.isEqualTo(nodeVal))
                           rootNode.setChildOpen(i, true, false);
                     }
                  }
               }
            }
         },
         new Command() {   // node expansion completed, restore scroll position
            @Override
            public void execute()
            {
               // delay 100ms to allow expand animation to complete
               new Timer() {

                  @Override
                  public void run()
                  {
                     scrollPanel_.setVerticalScrollPosition(scrollPosition); 
                  }
                  
               }.schedule(100);
              
            }
         });

      // create new widget
      objects_ = new CellTree(objectsModel_, null, RES, MESSAGES);
      
      // create the top level list of objects
      objects_.setDefaultNodeSize(Integer.MAX_VALUE);
      objects_.getElement().getStyle().setBorderStyle(BorderStyle.NONE);
      objects_.setWidth("100%");
      
      // wrap in vertical panel to get correct scrollbar behavior
      objectsWrapper_ = new VerticalPanel();
      objectsWrapper_.setWidth("100%");
      objectsWrapper_.add(objects_);
      
      scrollPanel_.setWidget(objectsWrapper_);
      
      // cache connection
      connection_ = connection;
   }
   
   @Override
   public void onResize()
   {
   }
   
   public interface Resources extends CellTree.Resources {
      
      @Source("zoomDataset_2x.png")
      ImageResource zoomDataset2x();
      
      @ImageOptions(flipRtl = true)
      @Source("ExpandIcon_2x.png")
      ImageResource cellTreeClosedItem();

      /**
       * An image indicating that a node is loading.
       */
      @ImageOptions(flipRtl = true)
      @Source("ExpandingIcon_2x.png")
      ImageResource cellTreeLoading();
    
      @ImageOptions(flipRtl = true)
      @Source("CollapseIcon_2x.png")
      ImageResource cellTreeOpenItem();
      
      @Source({CellTree.Style.DEFAULT_CSS, "ObjectBrowser.css"})
      public Style cellTreeStyle();   
      
      public interface Style extends CellTree.Style
      {
         String fieldName();
         String fieldType();
         String tableViewDataset();
         String containerIcon();
      }
   }
   
   static final Resources RES = GWT.create(Resources.class);
   
   static {
      RES.cellTreeStyle().ensureInjected();
   }
   
   @DefaultLocale("en_US")
   public interface TableBrowserMessages extends CellTreeMessages {
     @DefaultMessage("Show more")
     String showMore();
     @DefaultMessage("(No tables)")
     String emptyTree();
   }
   
   private static final TableBrowserMessages MESSAGES 
                              = GWT.create(TableBrowserMessages.class);
   
   private final SimplePanelWithProgress hostPanel_;
   private final ScrollPanel scrollPanel_;
   private CellTree objects_;
   private VerticalPanel objectsWrapper_;
   private ObjectBrowserModel objectsModel_;
   private Connection connection_;
}

@@ -698,61 +698,8 @@
 t;%0A%0A
-import org.rstudio.core.client.widget.ProgressPanel;%0A
 impo
@@ -1941,24 +1941,66 @@
 ollPanel_);%0A
+      hostPanel_.setSize(%22100%25%22, %22100%25%22);%0A
       connec

fix eclipse warning + scroll issue with connections browser