/** Reloads color info. */
  @Override
  public void loadSkin() {
    super.loadSkin();

    TAB_HIGHLIGHT_FOREGROUND_COLOR =
        new Color(DesktopUtilActivator.getResources().getColor("service.gui.TAB_TITLE_HIGHLIGHT"));

    TAB_SELECTED_FOREGROUND_COLOR =
        new Color(DesktopUtilActivator.getResources().getColor("service.gui.TAB_TITLE_SELECTED"));
  }
/**
 * This UI displays a different interface, which is independent from the look and feel.
 *
 * @author David Bismut, [email protected]
 * @author Yana Stamcheva
 * @author Adam Netocny
 */
public class SIPCommTabbedPaneEnhancedUI extends SIPCommTabbedPaneUI implements Skinnable {
  private static Color TAB_HIGHLIGHT_FOREGROUND_COLOR =
      new Color(DesktopUtilActivator.getResources().getColor("service.gui.TAB_TITLE_HIGHLIGHT"));

  private static Color TAB_SELECTED_FOREGROUND_COLOR =
      new Color(DesktopUtilActivator.getResources().getColor("service.gui.TAB_TITLE_SELECTED"));

  private static final int TAB_OVERLAP =
      Integer.parseInt(
          DesktopUtilActivator.getResources().getSettingsString("impl.gui.TAB_OVERLAP"));

  private static final int PREFERRED_WIDTH = 150;

  /**
   * The image used in the <tt>SIPCommLookAndFeel</tt> to paint the background of a selected tab.
   */
  private static final String SELECTED_TAB_LEFT_BG = "service.gui.lookandfeel.SELECTED_TAB_LEFT_BG";

  /**
   * The image used in the <tt>SIPCommLookAndFeel</tt> to paint the background of a selected tab.
   */
  private static final String SELECTED_TAB_MIDDLE_BG =
      "service.gui.lookandfeel.SELECTED_TAB_MIDDLE_BG";

  /**
   * The image used in the <tt>SIPCommLookAndFeel</tt> to paint the background of a selected tab.
   */
  private static final String SELECTED_TAB_RIGHT_BG =
      "service.gui.lookandfeel.SELECTED_TAB_RIGHT_BG";

  /** The image used in the <tt>SIPCommLookAndFeel</tt> to paint the background of a tab. */
  private static final String TAB_LEFT_BG = "service.gui.lookandfeel.TAB_LEFT_BG";

  /** The image used in the <tt>SIPCommLookAndFeel</tt> to paint the background of a tab. */
  private static final String TAB_MIDDLE_BG = "service.gui.lookandfeel.TAB_MIDDLE_BG";

  /** The image used in the <tt>SIPCommLookAndFeel</tt> to paint the background of a tab. */
  private static final String TAB_RIGHT_BG = "service.gui.lookandfeel.TAB_RIGHT_BG";

  protected final java.util.List<Integer> highlightedTabs = new Vector<Integer>();

  public static ComponentUI createUI(JComponent c) {
    return new SIPCommTabbedPaneEnhancedUI();
  }

  @Override
  protected void paintFocusIndicator(
      Graphics g,
      int tabPlacement,
      Rectangle[] rects,
      int tabIndex,
      Rectangle iconRect,
      Rectangle textRect,
      boolean isSelected) {}

  /** Overriden to paint nothing. */
  @Override
  protected void paintTabBorder(
      Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {}

  @Override
  protected void paintContentBorderTopEdge(
      Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
    if (tabPane.getTabCount() < 1) return;

    g.setColor(shadow);
    g.drawLine(x, y, x + w - 2, y);
  }

  @Override
  protected void paintContentBorderLeftEdge(
      Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
    if (tabPane.getTabCount() < 1) return;

    g.setColor(shadow);

    g.drawLine(x, y, x, y + h - 3);
  }

  @Override
  protected void paintContentBorderBottomEdge(
      Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
    if (tabPane.getTabCount() < 1) return;

    g.setColor(shadow);
    g.drawLine(x + 1, y + h - 3, x + w - 2, y + h - 3);
    g.drawLine(x + 1, y + h - 2, x + w - 2, y + h - 2);
    g.setColor(shadow.brighter());
    g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
  }

  @Override
  protected void paintContentBorderRightEdge(
      Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
    if (tabPane.getTabCount() < 1) return;

    g.setColor(shadow);

    g.drawLine(x + w - 3, y + 1, x + w - 3, y + h - 3);
    g.drawLine(x + w - 2, y + 1, x + w - 2, y + h - 3);
    g.setColor(shadow.brighter());
    g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 2);
  }

  @Override
  protected void paintTabBackground(
      Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
    g = g.create();
    try {
      internalPaintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
    } finally {
      g.dispose();
    }
  }

  private void internalPaintTabBackground(
      Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
    BufferedImage leftImg = null;
    BufferedImage middleImg = null;
    BufferedImage rightImg = null;

    Graphics2D g2 = (Graphics2D) g;

    AntialiasingManager.activateAntialiasing(g2);

    int tabOverlap = 0;

    if (isSelected) {
      if (tabPane.isEnabledAt(tabIndex)) {
        leftImg = DesktopUtilActivator.getImage(SELECTED_TAB_LEFT_BG);
        middleImg = DesktopUtilActivator.getImage(SELECTED_TAB_MIDDLE_BG);
        rightImg = DesktopUtilActivator.getImage(SELECTED_TAB_RIGHT_BG);

        tabOverlap = TAB_OVERLAP;
      } else {
        leftImg = DesktopUtilActivator.getImage(TAB_LEFT_BG);
        middleImg = DesktopUtilActivator.getImage(TAB_MIDDLE_BG);
        rightImg = DesktopUtilActivator.getImage(TAB_RIGHT_BG);
      }
    } else {
      leftImg = DesktopUtilActivator.getImage(TAB_LEFT_BG);
      middleImg = DesktopUtilActivator.getImage(TAB_MIDDLE_BG);
      rightImg = DesktopUtilActivator.getImage(TAB_RIGHT_BG);
    }

    // Remove the existing gap between the tabs and the panel, which is due
    // to the removal of the tabbed pane border.
    y++;
    // If the current tab is not the selected tab we paint it 2 more pixels
    // to the bottom in order to create the disabled look.
    if (!isSelected) y += 2;

    g2.drawImage(leftImg, x, y, null);
    g2.drawImage(
        middleImg,
        x + leftImg.getWidth(),
        y,
        w - leftImg.getWidth() - rightImg.getWidth() + tabOverlap,
        leftImg.getHeight(),
        null);
    g2.drawImage(rightImg, x + w - rightImg.getWidth() + tabOverlap, y, null);
  }

  @Override
  protected void paintText(
      Graphics g,
      int tabPlacement,
      Font font,
      FontMetrics metrics,
      int tabIndex,
      String title,
      Rectangle textRect,
      boolean isSelected) {
    g.setFont(font);

    int titleWidth = SwingUtilities.computeStringWidth(metrics, title);

    int preferredWidth = 0;
    if (isOneActionButtonEnabled()) {
      preferredWidth = calculateTabWidth(tabPlacement, tabIndex, metrics) - WIDTHDELTA - 15;

      if (isCloseEnabled()) preferredWidth -= BUTTONSIZE;

      if (isMaxEnabled()) preferredWidth -= BUTTONSIZE;
    } else {
      preferredWidth = titleWidth;
    }

    while (titleWidth > preferredWidth) {
      if (title.endsWith("...")) title = title.substring(0, title.indexOf("...") - 1).concat("...");
      else title = title.substring(0, title.length() - 4).concat("...");

      titleWidth = SwingUtilities.computeStringWidth(metrics, title);
    }

    textRect.width = titleWidth;

    View v = getTextViewForTab(tabIndex);
    if (v != null) {
      // html
      v.paint(g, textRect);
    } else {
      // plain text
      int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);

      if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
        if (isSelected) g.setColor(TAB_SELECTED_FOREGROUND_COLOR);
        else {
          if (this.isTabHighlighted(tabIndex)) {
            g.setColor(TAB_HIGHLIGHT_FOREGROUND_COLOR);
          } else g.setColor(tabPane.getForegroundAt(tabIndex));
        }

        BasicGraphicsUtils.drawString(
            g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
      } else { // tab disabled
        g.setColor(tabPane.getBackgroundAt(tabIndex).brighter());
        BasicGraphicsUtils.drawStringUnderlineCharAt(
            g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());

        g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
        BasicGraphicsUtils.drawStringUnderlineCharAt(
            g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1);
      }
    }
  }

  protected class ScrollableTabButton extends SIPCommTabbedPaneUI.ScrollableTabButton {
    /** Serial version UID. */
    private static final long serialVersionUID = 0L;

    public ScrollableTabButton(int direction) {
      super(direction);
      setRolloverEnabled(true);
    }

    @Override
    public Dimension getPreferredSize() {
      return new Dimension(16, calculateMaxTabHeight(0));
    }

    @Override
    public void paint(Graphics g) {
      Color origColor;
      boolean isPressed, isRollOver, isEnabled;
      int w, h, size;

      w = getWidth();
      h = getHeight();
      origColor = g.getColor();
      isPressed = getModel().isPressed();
      isRollOver = getModel().isRollover();
      isEnabled = isEnabled();

      g.setColor(getBackground());
      g.fillRect(0, 0, w, h);

      g.setColor(shadow);
      // Using the background color set above
      if (direction == WEST) {
        g.drawLine(0, 0, 0, h - 1); // left
        g.drawLine(w - 1, 0, w - 1, 0); // right
      } else g.drawLine(w - 2, h - 1, w - 2, 0); // right

      g.drawLine(0, 0, w - 2, 0); // top

      if (isRollOver) {
        // do highlights or shadows
        Color color1;
        Color color2;

        if (isPressed) {
          color2 = Color.WHITE;
          color1 = shadow;
        } else {
          color1 = Color.WHITE;
          color2 = shadow;
        }

        g.setColor(color1);

        if (direction == WEST) {
          g.drawLine(1, 1, 1, h - 1); // left
          g.drawLine(1, 1, w - 2, 1); // top
          g.setColor(color2);
          g.drawLine(w - 1, h - 1, w - 1, 1); // right
        } else {
          g.drawLine(0, 1, 0, h - 1);
          g.drawLine(0, 1, w - 3, 1); // top
          g.setColor(color2);
          g.drawLine(w - 3, h - 1, w - 3, 1); // right
        }
      }

      // g.drawLine(0, h - 1, w - 1, h - 1); //bottom

      // If there's no room to draw arrow, bail
      if (h < 5 || w < 5) {
        g.setColor(origColor);
        return;
      }

      if (isPressed) {
        g.translate(1, 1);
      }

      // Draw the arrow
      size = Math.min((h - 4) / 3, (w - 4) / 3);
      size = Math.max(size, 2);

      boolean highlight = false;

      if (!highlightedTabs.isEmpty()
          && ((direction == WEST && tabScroller.scrollBackwardButton.isEnabled())
              || (direction == EAST && tabScroller.scrollForwardButton.isEnabled()))) {
        Rectangle viewRect = tabScroller.viewport.getViewRect();

        if (direction == WEST) {
          int leadingTabIndex = getClosestTab(viewRect.x, viewRect.y);

          for (int i = 0; i < leadingTabIndex; i++) {
            if (highlightedTabs.contains(i) && !isScrollTabVisible(i)) {
              highlight = true;
              break;
            }
          }
        } else {
          int leadingTabIndex = getClosestTab(viewRect.x + viewRect.y, viewRect.y);

          for (int i = leadingTabIndex; i < tabPane.getTabCount(); i++) {
            if (highlightedTabs.contains(i) && !isScrollTabVisible(i)) {
              highlight = true;
              break;
            }
          }
        }

        if (highlight) {
          Image img =
              DesktopUtilActivator.getImage(
                  direction == WEST
                      ? "service.gui.icons.TAB_UNREAD_BACKWARD_ICON"
                      : "service.gui.icons.TAB_UNREAD_FORWARD_ICON");

          int wi = img.getWidth(null);

          g.drawImage(img, (w - wi) / 2, (h - size) / 2 - 2 /* 2 borders 1px width*/, null);
        }
      }

      if (!highlight) paintTriangle(g, (w - size) / 2, (h - size) / 2, size, direction, isEnabled);

      // Reset the Graphics back to it's original settings
      if (isPressed) {
        g.translate(-1, -1);
      }
      g.setColor(origColor);
    }
  }

  /**
   * Checks whether the <tt>tabIndex</tt> is visible in the scrollable tabs list.
   *
   * @param tabIndex the tab index to check.
   * @return whether <tt>tabIndex</tt> is visible in the list of scrollable tabs.
   */
  private boolean isScrollTabVisible(int tabIndex) {
    Rectangle tabRect = rects[tabIndex];
    Rectangle viewRect = tabScroller.viewport.getViewRect();
    if ((tabRect.x + tabRect.width - BUTTONSIZE < viewRect.x)
        || (tabRect.x + BUTTONSIZE > viewRect.x + viewRect.width)) {
      return false;
    } else {
      return true;
    }
  }

  @Override
  protected SIPCommTabbedPaneUI.ScrollableTabButton createScrollableTabButton(int direction) {
    return new ScrollableTabButton(direction);
  }

  @Override
  protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
    int width = super.calculateTabWidth(tabPlacement, tabIndex, metrics);

    if (isOneActionButtonEnabled()) {
      if (width > PREFERRED_WIDTH) width = PREFERRED_WIDTH;
    }

    return width + WIDTHDELTA;
  }

  public void tabAddHightlight(int tabIndex) {
    this.highlightedTabs.add(tabIndex);
  }

  public void tabRemoveHighlight(int tabIndex) {
    Iterator<Integer> highlightedIter = highlightedTabs.iterator();

    while (highlightedIter.hasNext()) {
      if (highlightedIter.next().intValue() == tabIndex) {
        highlightedIter.remove();
        break;
      }
    }
  }

  public boolean isTabHighlighted(int tabIndex) {
    return highlightedTabs.contains(tabIndex);
  }

  /** Reloads color info. */
  @Override
  public void loadSkin() {
    super.loadSkin();

    TAB_HIGHLIGHT_FOREGROUND_COLOR =
        new Color(DesktopUtilActivator.getResources().getColor("service.gui.TAB_TITLE_HIGHLIGHT"));

    TAB_SELECTED_FOREGROUND_COLOR =
        new Color(DesktopUtilActivator.getResources().getColor("service.gui.TAB_TITLE_SELECTED"));
  }
}