/*
 * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
 * See README for License detail, AUTHORS for developers list.
 *
 * This program 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.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* gui-gtk-bar.c: bar functions for Gtk GUI */


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>

#include "../../core/weechat.h"
#include "../../core/wee-config.h"
#include "../../core/wee-log.h"
#include "../gui-bar.h"
#include "../gui-chat.h"
#include "../gui-color.h"
#include "../gui-window.h"
#include "gui-gtk.h"


/*
 * gui_bar_window_search_bar: search a reference to a bar in a window
 */

struct t_gui_bar_window *
gui_bar_window_search_bar (struct t_gui_window *window, struct t_gui_bar *bar)
{
    struct t_gui_bar_window *ptr_bar_win;

    for (ptr_bar_win = GUI_GTK(window)->bar_windows; ptr_bar_win;
         ptr_bar_win = ptr_bar_win->next_bar_window)
    {
        if (ptr_bar_win->bar == bar)
            return ptr_bar_win;
    }
    
    /* bar window not found for window */
    return NULL;
}

/*
 * gui_bar_window_get_current_size: get current size of bar window
 *                                  return width or height, depending on bar
 *                                  position
 */

int
gui_bar_window_get_current_size (struct t_gui_bar_window *bar_window)
{
    return bar_window->current_size;
}

/*
 * gui_bar_window_set_current_size: set current size of all bar windows for a bar
 */

void
gui_bar_window_set_current_size (struct t_gui_bar *bar, int size)
{
    struct t_gui_window *ptr_win;
    struct t_gui_bar_window *ptr_bar_win;
    
    if (CONFIG_INTEGER(bar->type) == GUI_BAR_TYPE_ROOT)
        bar->bar_window->current_size = (size == 0) ? 1 : size;
    else
    {
        for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
        {
            for (ptr_bar_win = GUI_GTK(ptr_win)->bar_windows;
                 ptr_bar_win; ptr_bar_win = ptr_bar_win->next_bar_window)
            {
                ptr_bar_win->current_size = (size == 0) ? 1 : size;
            }
        }
    }
}

/*
 * gui_bar_window_get_size: get total bar size (window bars) for a position
 *                          bar is optional, if not NULL, size is computed
 *                          from bar 1 to bar # - 1
 */

int
gui_bar_window_get_size (struct t_gui_bar *bar, struct t_gui_window *window,
                         enum t_gui_bar_position position)
{
    (void) bar;
    (void) window;
    (void) position;
    
    /* TODO: write this function for Gtk */
    return 0;
}

/*
 * gui_bar_get_min_width: return minimum width of a bar window displayed for
 *                        a bar
 *                        for example, if a bar is displayed in 3 windows,
 *                        this function return min width of these 3 bar windows
 */

int
gui_bar_get_min_width (struct t_gui_bar *bar)
{
    struct t_gui_window *ptr_win;
    struct t_gui_bar_window *ptr_bar_win;
    int min_width;
    
    if (CONFIG_INTEGER(bar->type) == GUI_BAR_TYPE_ROOT)
        return bar->bar_window->width;
    
    min_width = INT_MAX;
    for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
    {
        for (ptr_bar_win = GUI_GTK(ptr_win)->bar_windows;
             ptr_bar_win; ptr_bar_win = ptr_bar_win->next_bar_window)
        {
            if (ptr_bar_win->bar == bar)
            {
                if (ptr_bar_win->width < min_width)
                    min_width = ptr_bar_win->width;
            }
        }
    }
    
    if (min_width == INT_MAX)
        return 0;
    
    return min_width;
}

/*
 * gui_bar_get_min_height: return minimum height of a bar window displayed for
 *                         a bar
 *                         for example, if a bar is displayed in 3 windows,
 *                         this function return min width of these 3 bar windows
 */

int
gui_bar_get_min_height (struct t_gui_bar *bar)
{
    struct t_gui_window *ptr_win;
    struct t_gui_bar_window *ptr_bar_win;
    int min_height;
    
    if (CONFIG_INTEGER(bar->type) == GUI_BAR_TYPE_ROOT)
        return bar->bar_window->height;
    
    min_height = INT_MAX;
    for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
    {
        for (ptr_bar_win = GUI_GTK(ptr_win)->bar_windows;
             ptr_bar_win; ptr_bar_win = ptr_bar_win->next_bar_window)
        {
            if (ptr_bar_win->bar == bar)
            {
                if (ptr_bar_win->height < min_height)
                    min_height = ptr_bar_win->height;
            }
        }
    }
    
    if (min_height == INT_MAX)
        return 0;
    
    return min_height;
}

/*
 * gui_bar_check_size_add: check if "add_size" is ok for bar
 *                         return 1 if new size is ok
 *                                0 if new size is too big
 */

int
gui_bar_check_size_add (struct t_gui_bar *bar, int add_size)
{
    (void) bar;
    (void) add_size;
    
    /* TODO: write this function for Gtk */
    return 1;
}

/*
 * gui_bar_window_calculate_pos_size: calculate position and size of a bar
 */

void
gui_bar_window_calculate_pos_size (struct t_gui_bar_window *bar_window,
                                   struct t_gui_window *window)
{
    (void) bar_window;
    (void) window;
    
    /* TODO: write this function for Gtk */
}

/*
 * gui_bar_window_create_win: create curses window for bar
 */

void
gui_bar_window_create_win (struct t_gui_bar_window *bar_window)
{
    (void) bar_window;
    
    /* TODO: write this function for Gtk */
}

/*
 * gui_bar_window_find_pos: find position for bar window (keeping list sorted
 *                          by bar number)
 */

struct t_gui_bar_window *
gui_bar_window_find_pos (struct t_gui_bar *bar, struct t_gui_window *window)
{
    struct t_gui_bar_window *ptr_bar_window;
    
    for (ptr_bar_window = GUI_GTK(window)->bar_windows; ptr_bar_window;
         ptr_bar_window = ptr_bar_window->next_bar_window)
    {
        if (CONFIG_INTEGER(bar->priority) >= CONFIG_INTEGER(ptr_bar_window->bar->priority))
            return ptr_bar_window;
    }
    
    /* position not found, best position is at the end */
    return NULL;
}

/*
 * gui_bar_window_new: create a new "window bar" for a bar, in screen or a window
 *                     if window is not NULL, bar window will be in this window
 */

int
gui_bar_window_new (struct t_gui_bar *bar, struct t_gui_window *window)
{
    (void) bar;
    (void) window;
    
    /* TODO: write this function for Gtk */
    return 0;
}

/*
 * gui_bar_window_free: free a bar window
 */

void
gui_bar_window_free (struct t_gui_bar_window *bar_window,
                     struct t_gui_window *window)
{
    (void) bar_window;
    (void) window;
    
    /* TODO: write this function for Gtk */
}

/*
 * gui_bar_free_bar_windows: free bar windows for a bar
 */

void
gui_bar_free_bar_windows (struct t_gui_bar *bar)
{
    struct t_gui_window *ptr_win;
    struct t_gui_bar_window *ptr_bar_win, *next_bar_win;
    
    for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
    {
        ptr_bar_win = GUI_GTK(gui_windows)->bar_windows;
        while (ptr_bar_win)
        {
            next_bar_win = ptr_bar_win->next_bar_window;
            
            if (ptr_bar_win->bar == bar)
                gui_bar_window_free (ptr_bar_win, ptr_win);
            
            ptr_bar_win = next_bar_win;
        }
    }
}

/*
 * gui_bar_window_remove_unused_bars: remove unused bars for a window
 *                                    return 1 if at least one bar was removed
 *                                           0 if no bar was removed
 */

int
gui_bar_window_remove_unused_bars (struct t_gui_window *window)
{
    int rc;
    struct t_gui_bar_window *ptr_bar_win, *next_bar_win;
    
    rc = 0;

    ptr_bar_win = GUI_GTK(window)->bar_windows;
    while (ptr_bar_win)
    {
        next_bar_win = ptr_bar_win->next_bar_window;

        if ((CONFIG_INTEGER(ptr_bar_win->bar->type) == GUI_BAR_TYPE_WINDOW)
            && (!gui_bar_check_conditions_for_window (ptr_bar_win->bar, window)))
        {
            gui_bar_window_free (ptr_bar_win, window);
            rc = 1;
        }
        
        ptr_bar_win = next_bar_win;
    }
    
    return rc;
}

/*
 * gui_bar_window_add_missing_bars: add missing bars for a window
 *                                  return 1 if at least one bar was created
 *                                         0 if no bar was created
 */

int
gui_bar_window_add_missing_bars (struct t_gui_window *window)
{
    int rc;
    struct t_gui_bar *ptr_bar;
    
    rc = 0;
    
    for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
    {
        if ((CONFIG_INTEGER(ptr_bar->type) == GUI_BAR_TYPE_WINDOW)
            && gui_bar_check_conditions_for_window (ptr_bar, window))
        {
            if (!gui_bar_window_search_bar (window, ptr_bar))
            {
                gui_bar_window_new (ptr_bar, window);
                rc = 1;
            }
        }
    }
    
    return rc;
}

/*
 * gui_bar_window_print_string: print a string text on a bar window
 *                              return number of chars displayed on screen
 */

int
gui_bar_window_print_string (struct t_gui_bar_window *bar_window,
                             const char *string, int max_chars)
{
    (void) bar_window;
    (void) string;
    (void) max_chars;
    
    /* TODO: write this function for Gtk */
    return 0;
}

/*
 * gui_bar_window_draw: draw a bar for a window
 */

void
gui_bar_window_draw (struct t_gui_bar_window *bar_window,
                     struct t_gui_window *window)
{
    (void) bar_window;
    (void) window;
    
    /* TODO: write this function for Gtk */
}

/*
 * gui_bar_draw: draw a bar
 */

void
gui_bar_draw (struct t_gui_bar *bar)
{
    (void) bar;

    /* TODO: write this function for Gtk */
}

/*
 * gui_bar_scroll: scroll a bar for a buffer
 *                 return 1 if scroll is ok, 0 if error
 */

int
gui_bar_scroll (struct t_gui_bar *bar, struct t_gui_buffer *buffer,
                const char *scroll)
{
    (void) bar;
    (void) buffer;
    (void) scroll;
    
    /* TODO: write this function for Gtk */
    return 0;
}

/*
 * gui_bar_window_print_log: print bar window infos in log (usually for crash dump)
 */

void
gui_bar_window_print_log (struct t_gui_bar_window *bar_window)
{
    log_printf ("");
    log_printf ("  [window bar (addr:0x%lx)]",   bar_window);
    log_printf ("    bar . . . . . . . : 0x%lx", bar_window->bar);
    log_printf ("    x . . . . . . . . : %d",    bar_window->x);
    log_printf ("    y . . . . . . . . : %d",    bar_window->y);
    log_printf ("    width . . . . . . : %d",    bar_window->width);
    log_printf ("    height. . . . . . : %d",    bar_window->height);
    log_printf ("    scroll_x. . . . . : %d",    bar_window->scroll_x);
    log_printf ("    scroll_y. . . . . : %d",    bar_window->scroll_y);
    log_printf ("    prev_bar_window . : 0x%lx", bar_window->prev_bar_window);
    log_printf ("    next_bar_window . : 0x%lx", bar_window->next_bar_window);
}
