/*
Copyright © 2011-2012 Clint Bellanger

This file is part of FLARE.

FLARE is free software: you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

FLARE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
FLARE.  If not, see http://www.gnu.org/licenses/
*/

#include "WidgetTabControl.h"
#include "WidgetLabel.h"

using namespace std;

/**
 * Class constructor.
 *
 * @param amount  Amount of tabs the control will have.
 */
WidgetTabControl::WidgetTabControl(int amount) {

  // Based on given amount:
  tabsAmount = amount;
  titles = new std::string[tabsAmount];
  tabs = new SDL_Rect[tabsAmount];

  // Predefined:
  activeTab = 0;
  tabPadding.x = 6;
  tabPadding.y = 4;

  // Load needed graphics.
  loadGraphics();

}
/**
 * Class destructor.
 */
WidgetTabControl::~WidgetTabControl() {
  SDL_FreeSurface(activeTabSurface);
  SDL_FreeSurface(inactiveTabSurface);
  delete[] titles;
  delete[] tabs;
}

/**
 * Sets the title of a tab.
 *
 * @param number        Tab index. For example, 0 for the first tab.
 * @param title         Tab title.
 * @param updateHeader  Whether or not the header should be updated.
 */
void WidgetTabControl::setTabTitle(int number, const std::string& title) {
  titles[number] = title;
}

/**
 * Returns the index of the open tab.
 *
 * For example, if the first tab is open, it will return 0.
 */
int WidgetTabControl::getActiveTab() {
  return activeTab;
}

/**
 * Define the position and size of the tab control.
 *
 * @param x       X coordinate of the top-left corner of the widget.
 * @param y       Y coordinate of the top-left corner of the widget.
 * @param width   Width of the widget.
 * @param height  Height of the widget.
 */
void WidgetTabControl::setMainArea(int x, int y, int width, int height)
{
  // Set tabs area.
  tabsArea.x = x;
  tabsArea.y = y;
  tabsArea.w = width;
  tabsArea.h = 20;

  // Set content area.
  contentArea.x = x + 8;
  contentArea.y = y + 26;
  contentArea.w = width - 16;
  contentArea.h = height - 20;
}

/**
 * Updates the areas or the tabs.
 *
 * Use it right after you set the area and tab titles of the tab control.
 */
void WidgetTabControl::updateHeader()
{
  for (int i=0; i<tabsAmount; i++) {
    tabs[i].y = tabsArea.y;
    tabs[i].h = tabsArea.h;

    if (i==0) tabs[i].x = tabsArea.x;
    else tabs[i].x = tabs[i-1].x + tabs[i-1].w;

    tabs[i].w = tabPadding.x + font->calc_width(titles[i]) + tabPadding.x;

  }
}

/**
 * Load the graphics for the control.
 */
void WidgetTabControl::loadGraphics()
{
  activeTabSurface = IMG_Load(mods->locate("images/menus/tab_active.png").c_str());
  inactiveTabSurface = IMG_Load(mods->locate("images/menus/tab_inactive.png").c_str());

  if(!activeTabSurface || !inactiveTabSurface) {
    fprintf(stderr, "Could not load image: %s\n", IMG_GetError());
    SDL_Quit();
  }

  SDL_Surface *cleanup;

  cleanup = activeTabSurface;
  activeTabSurface = SDL_DisplayFormatAlpha(activeTabSurface);
  SDL_FreeSurface(cleanup);

  cleanup = inactiveTabSurface;
  inactiveTabSurface = SDL_DisplayFormatAlpha(inactiveTabSurface);
  SDL_FreeSurface(cleanup);
}

void WidgetTabControl::logic()
{
  logic(inpt->mouse.x,inpt->mouse.y);
}

/**
 * Performs one frame of logic.
 *
 * It basically checks if it was clicked on the header, and if so changes the active tab.
 */
void WidgetTabControl::logic(int x, int y)
{
  Point mouse = {x,y};
  // If the click was in the tabs area;
  if(isWithin(tabsArea, mouse) && inpt->pressing[MAIN1]) {
    // Mark the clicked tab as activeTab.
    for (int i=0; i<tabsAmount; i++) {
      if(isWithin(tabs[i], mouse)) {
        activeTab = i;
        return;
      }
    }
  }
}

/**
 * Renders the widget.
 *
 * Remember to render then on top of it the actual content of the {@link getActiveTab() active tab}.
 */
void WidgetTabControl::render(SDL_Surface *target)
{
  if (target == NULL) {
    target = screen;
  }
  for (int i=0; i<tabsAmount; i++) {
    renderTab(i,target);
  }
}

/**
 * Renders the given tab on the widget header.
 */
void WidgetTabControl::renderTab(int number, SDL_Surface *target)
{
  int i = number;
  SDL_Rect src;
  SDL_Rect dest;

  // Draw tab’s background.
  src.x = src.y = 0;
  dest.x = tabs[i].x;
  dest.y = tabs[i].y;
  src.w = tabs[i].w;
  src.h = tabs[i].h;

  if (i == activeTab)
    SDL_BlitSurface(activeTabSurface, &src, target, &dest);
  else
    SDL_BlitSurface(inactiveTabSurface, &src, target, &dest);

  // Draw tab’s right edge.
  src.x = 128 - tabPadding.x;
  src.w = tabPadding.x;
  dest.x = tabs[i].x + tabs[i].w - tabPadding.x;

  if (i == activeTab)
    SDL_BlitSurface(activeTabSurface, &src, target, &dest);
  else
    SDL_BlitSurface(inactiveTabSurface, &src, target, &dest);

  // Set tab’s label font color.
  int fontColor;
  if (i == activeTab) fontColor = FONT_WHITE;
  else fontColor = FONT_GREY;

  // Draw tab’s label.
  WidgetLabel label;
  label.set(tabs[i].x + tabPadding.x, tabs[i].y + tabPadding.y, JUSTIFY_LEFT, VALIGN_TOP, titles[i], fontColor);
  label.render(target);
}

/**
 * Returns the height in pixels of the widget.
 */
SDL_Rect WidgetTabControl::getContentArea()
{
  return contentArea;
}
