/*
 * ModuleTabLayoutPanel.java
 *
 * Copyright (C) 2009-12 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.core.client.theme;

import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.*;

import org.rstudio.core.client.events.*;
import org.rstudio.core.client.layout.WindowState;
import org.rstudio.core.client.theme.res.ThemeResources;
import org.rstudio.core.client.theme.res.ThemeStyles;
import org.rstudio.core.client.widget.DoubleClickState;
import org.rstudio.core.client.widget.model.ProvidesBusy;
import org.rstudio.studio.client.workbench.events.BusyEvent;
import org.rstudio.studio.client.workbench.events.BusyHandler;

public class ModuleTabLayoutPanel extends TabLayoutPanel
{
   public static class ModuleTab extends Composite implements BusyHandler
   {
      public ModuleTab(String title, ThemeStyles styles, boolean canClose)
      {
         layoutPanel_ = new HorizontalPanel();
         layoutPanel_.setStylePrimaryName(styles.tabLayout());

         HTML left = new HTML();
         left.setStylePrimaryName(styles.tabLayoutLeft());
         layoutPanel_.add(left);

         HorizontalPanel center = new HorizontalPanel();
         center.setStylePrimaryName(styles.tabLayoutCenter());
         Label label = new Label(title, false);
         center.add(label);
         if (canClose)
         {
            closeButton_ = new Image(ThemeResources.INSTANCE.closeTab());
            closeButton_.setStylePrimaryName(styles.closeTabButton());
            closeButton_.addStyleName(ThemeStyles.INSTANCE.handCursor());
            center.add(closeButton_);
         }
         layoutPanel_.add(center);

         HTML right = new HTML();
         right.setStylePrimaryName(styles.tabLayoutRight());
         layoutPanel_.add(right);

         addDomHandler(new MouseDownHandler()
         {
            public void onMouseDown(MouseDownEvent event)
            {
               // Stop double-click of tab from selecting the tab title text
               event.preventDefault();
            }
         }, MouseDownEvent.getType());

         initWidget(layoutPanel_);
      }

      public Widget getWidget()
      {
         return super.getWidget();
      }

      public HandlerRegistration addClickHandler(ClickHandler handler)
      {
         return addDomHandler(handler, ClickEvent.getType());
      }

      public HandlerRegistration addCloseButtonClickHandler(ClickHandler handler)
      {
         return closeButton_.addClickHandler(handler);
      }

      @Override
      public void onBusy(BusyEvent event)
      {
         setBusy(event.isBusy());
      }
      
      private void setBusy(boolean isBusy)
      {
         if (isBusy)
         {
            if (busyImage_ == null)
            {
               busyImage_ = new Image(ThemeResources.INSTANCE.busyTab());
               busyImage_.setHeight("9px");
               busyImage_.setWidth("9px");
               busyImage_.getElement().getStyle().setMarginLeft(4, Unit.PX);
               busyImage_.getElement().getStyle().setMarginTop(6, Unit.PX);
               HorizontalPanel center = (HorizontalPanel)closeButton_.getParent();
               if (center != null)
                  center.add(busyImage_);
            }
            closeButton_.setVisible(false);
            busyImage_.setVisible(true);
         }
         else
         {
            if (busyImage_ != null)
              busyImage_.setVisible(false);
            closeButton_.setVisible(true);
         }
      }

      private HorizontalPanel layoutPanel_;
      private Image closeButton_;
      private Image busyImage_;
   }

   public ModuleTabLayoutPanel(final WindowFrame owner)
   {
      super(BAR_HEIGHT, Style.Unit.PX);
      owner_ = owner;
      styles_ = ThemeResources.INSTANCE.themeStyles();
      addStyleName(styles_.moduleTabPanel());
      addDomHandler(new MouseDownHandler() {
         public void onMouseDown(MouseDownEvent event)
         {
            if (!isWithinTopBand(event.getNativeEvent()))
               return;
            // Stop click-drag selection from working in top band
            event.preventDefault();
         }
      }, MouseDownEvent.getType());
      addDomHandler(new ClickHandler() {
         public void onClick(ClickEvent event)
         {
            if (!isWithinTopBand(event.getNativeEvent()))
               return;

            event.preventDefault();
            event.stopPropagation();
            if (doubleClickState_.checkForDoubleClick(event.getNativeEvent()))
            {
               owner.fireEvent(new WindowStateChangeEvent(WindowState.MAXIMIZE));
            }
         }
      }, ClickEvent.getType());
   }

   private boolean isWithinTopBand(NativeEvent event)
   {
      int absTop = getAbsoluteTop();
      return absTop + BAR_HEIGHT > event.getClientY();
   }

   @Override
   public void add(Widget child, String text)
   {
      add(child, text, false);
   }

   @Override
   public void add(Widget child, String text, boolean asHtml)
   {
      add(child, text, asHtml, null);
   }

   public void add(Widget child, String text, boolean asHtml, 
                   ClickHandler closeHandler)
   {
      add(child, text, asHtml, closeHandler, null);
   }

   public void add(final Widget child, String text, boolean asHtml,
                   ClickHandler closeHandler, ProvidesBusy providesBusy)
   {
      if (asHtml)
         throw new UnsupportedOperationException("HTML tab names not supported");

      ModuleTab tab = new ModuleTab(text, styles_, closeHandler != null);
      super.add(child, tab);

      if (closeHandler != null)
         tab.addCloseButtonClickHandler(closeHandler);
      
      if (providesBusy != null)
         providesBusy.addBusyHandler(tab);
   }

   @Override
   public void selectTab(int index)
   {
      super.selectTab(Math.max(0, Math.min(index, getWidgetCount() - 1)));
      if (index == 0)
         owner_.addStyleName(styles_.firstTabSelected());
      else
         owner_.removeStyleName(styles_.firstTabSelected());
   }

   @Override
   public void add(Widget child, Widget tab)
   {
      throw new UnsupportedOperationException();
   }

   private final ThemeStyles styles_;

   private final DoubleClickState doubleClickState_ = new DoubleClickState();
   public static final int BAR_HEIGHT = 23;
   private final WindowFrame owner_;
}
