/*  Gnometab -- a guitar tablature editor for GNOME
    Copyright (C) 2001  William L. Guelker

    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <math.h>
#include <gnome.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include "tab_canvas.h"
#include "interface.h"
#include "chord_builder.h"
#include "dialogs.h"
#include "tab_doc.h"

static void
popup_destroyed (GtkObject *obj,  void **popup_pointer)
{
    if (popup_pointer != NULL)
    {
        g_free (*popup_pointer);
        *popup_pointer = NULL;
    }
}

static void
on_cut_popup_activate                  (GtkMenuItem     *menuitem,
                                        GtabDoc         *doc)
{
    doc->parent->clipboard_doc = xmlNewDoc("1.0");
    doc->parent->clipboard_doc->xmlRootNode = xmlNewDocNode(doc->parent->clipboard_doc, NULL, 
                                        "clipped_objects", NULL);
    
    g_list_foreach(doc->parent->clipboard_objs, destroy_tab_object_and_node_with_cut, doc);
    
    g_list_free(doc->parent->clipboard_objs);
    doc->parent->clipboard_objs = NULL;
    
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "cut_popup")), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "copy_popup")), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "paste_popup")), TRUE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "clear_popup")), FALSE);
    doc->changed = TRUE;
                            
}


static void
on_copy_popup_activate                 (GtkMenuItem     *menuitem,
                                        GtabDoc         *doc)
{
    xmlNodePtr tmp_node, obj_node;
    GList* tmp = doc->parent->clipboard_objs;
    
    doc->parent->clipboard_doc = xmlNewDoc("1.0");
    doc->parent->clipboard_doc->xmlRootNode = xmlNewDocNode(doc->parent->clipboard_doc, NULL, 
                                        "clipped_objects", NULL);
    doc->parent->clipboard_objs = g_list_first(doc->parent->clipboard_objs);
    while (doc->parent->clipboard_objs != NULL)    {
        if (GNOME_IS_CANVAS_ITEM(doc->parent->clipboard_objs->data))    {
            
            obj_node = (xmlNodePtr ) g_object_get_data
                                    (G_OBJECT(doc->parent->clipboard_objs->data), "node");
            tmp_node = xmlCopyNode(obj_node, TRUE);
            tmp_node = xmlAddChild(doc->parent->clipboard_doc->xmlRootNode, tmp_node);
            tmp = doc->parent->clipboard_objs;
            doc->parent->clipboard_objs = g_list_next(doc->parent->clipboard_objs);
            tmp = g_list_remove(tmp, tmp->data);
        }
    }    
    
    g_list_free(doc->parent->clipboard_objs);
    doc->parent->clipboard_objs = NULL;
    
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "cut_popup")), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "copy_popup")), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "paste_popup")), TRUE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "clear_popup")), FALSE);
        
}


static void
on_paste_popup_activate                (GtkMenuItem     *menuitem,
                                        GtabDoc         *doc)
{
    xmlNodePtr tmp_node;
    double tmp_x, tmp_y;
    gchar *char_x, *char_y;
    
    find_staff(doc->popup->y);
    for (tmp_node = doc->parent->clipboard_doc->xmlRootNode->children; tmp_node != NULL; 
                                            tmp_node = tmp_node->next)    {
                                                
        if (g_ascii_strcasecmp(tmp_node->name, "tab_chord") == 0)    {
            doc->popup->y = (floor(doc->popup->y/140))*140 - 4;
        }
        
        if (doc->parent->clipboard_multi == TRUE)    {
            /* do magic coordinate translations */
            char_x = get_prop(tmp_node, "x_create");
            char_y = get_prop(tmp_node, "y_create");
            tmp_x = atof(char_x);
            tmp_x = tmp_x - doc->parent->clipboard_multi_start_x;
            xmlSetProp(tmp_node, "x_create", 
                        float_to_char(doc->popup->x + tmp_x));
            
            tmp_y = atof(char_y) - doc->parent->clipboard_multi_start_y;
            xmlSetProp(tmp_node, "y_create", 
                        float_to_char(clipboard_multi_find_y_offset
                                            (current_staff) + tmp_y));
            g_free(char_x);
            g_free(char_y);
            
            
        }
        else    {
            doc->popup->x = (floor((doc->popup->x)/17.0))*17.0;
            xmlSetProp(tmp_node, "x_create", float_to_char(doc->popup->x));
            xmlSetProp(tmp_node, "y_create", float_to_char(doc->popup->y));
        }
        
    }
    render_objects(doc, doc->parent->clipboard_doc->xmlRootNode);
    
    xmlFreeDoc(doc->parent->clipboard_doc);
    doc->parent->clipboard_multi = FALSE;
    doc->parent->clipboard_multi_start_x = 0.0;
    doc->parent->clipboard_multi_start_y = 0.0;
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "cut_popup")), TRUE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "copy_popup")), TRUE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "paste_popup")), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(
                g_object_get_data(G_OBJECT(doc->popup->menu), "clear_popup")), TRUE);
    
    doc->changed = TRUE;
}

static void
on_clear_popup_activate                (GtkMenuItem     *menuitem,
                                        GtabDoc         *doc)
{
    g_list_foreach(doc->parent->clipboard_objs, destroy_tab_object_and_node, doc);
    
    g_list_free(doc->parent->clipboard_objs);
    doc->parent->clipboard_objs = NULL;
    doc->changed = TRUE;
}

static void
on_right_click_popup_deactivate        (GtkMenuShell    *menushell,
                                        GtabDoc         *doc)
{
    if (doc->highlights)
    {
        gtk_object_destroy(GTK_OBJECT(doc->highlights));
        doc->highlights = NULL;
    }
    
}

static GnomeUIInfo right_click_popup_uiinfo[] =
{
    GNOMEUIINFO_MENU_CUT_ITEM (on_cut_popup_activate, NULL),
    GNOMEUIINFO_MENU_COPY_ITEM (on_copy_popup_activate, NULL),
    GNOMEUIINFO_MENU_PASTE_ITEM (on_paste_popup_activate, NULL),
    {
        GNOME_APP_UI_ITEM, N_("_Delete"),
        NULL,
        (gpointer) on_clear_popup_activate, NULL, NULL,
        GNOME_APP_PIXMAP_NONE, NULL,
        0, (GdkModifierType) 0, NULL
    },
    GNOMEUIINFO_END
};


static GtabDocPopup*
create_right_click_popup (GtabDoc *doc)
{
    GtabDocPopup *popup;

    popup = g_new0(GtabDocPopup, 1);
    
    popup->menu = gtk_menu_new ();
    
    gtk_container_set_border_width (GTK_CONTAINER (popup->menu), 2);
    gnome_app_fill_menu_with_data (GTK_MENU_SHELL (popup->menu), right_click_popup_uiinfo,
                           NULL, FALSE, 0, doc);
    
    g_object_set_data(G_OBJECT(popup->menu), "cut_popup", right_click_popup_uiinfo[0].widget);
    g_object_set_data(G_OBJECT(popup->menu), "copy_popup", right_click_popup_uiinfo[1].widget);
    g_object_set_data(G_OBJECT(popup->menu), "paste_popup", right_click_popup_uiinfo[2].widget);
    g_object_set_data(G_OBJECT(popup->menu), "clear_popup", right_click_popup_uiinfo[3].widget);
    
    g_signal_connect (GTK_OBJECT (popup->menu), "deactivate",
                          GTK_SIGNAL_FUNC (on_right_click_popup_deactivate),
                          doc);
    g_signal_connect(G_OBJECT(popup->menu), "destroy",
                          G_CALLBACK(popup_destroyed), &popup);
    
    popup->x = 0;
    popup->y = 0;
    
    return popup;
}

GtabDoc*
new_tab_doc(GtabApp *parent)
{
    GtabDoc     *doc;
    xmlNodePtr page_ptr;
    xmlNodePtr tmp_node;
    
    doc = g_new0(GtabDoc, 1);
    
    doc->current_doc = xmlNewDoc("1.0");
    doc->current_doc->xmlRootNode = xmlNewDocNode(doc->current_doc, 
                                            NULL, "staff_objects", NULL);
    
    xmlSetProp(doc->current_doc->xmlRootNode, "page", "1");
        
    doc->staff_nodes[0] = xmlNewChild(doc->current_doc->xmlRootNode, NULL, "STAFF1", NULL);
    doc->staff_nodes[1] = xmlNewChild(doc->current_doc->xmlRootNode, NULL, "STAFF2", NULL);
    doc->staff_nodes[2] = xmlNewChild(doc->current_doc->xmlRootNode, NULL, "STAFF3", NULL);
    doc->staff_nodes[3] = xmlNewChild(doc->current_doc->xmlRootNode, NULL, "STAFF4", NULL);
    doc->staff_nodes[4] = xmlNewChild(doc->current_doc->xmlRootNode, NULL, "STAFF5", NULL);
    doc->staff_nodes[5] = xmlNewChild(doc->current_doc->xmlRootNode, NULL, "STAFF6", NULL);
    
    doc->loaded_doc = xmlNewDoc("1.0");
    doc->loaded_doc->xmlRootNode = xmlNewDocNode(doc->loaded_doc, NULL, "tab_doc", NULL);
    page_ptr = xmlCopyNode(doc->current_doc->xmlRootNode, TRUE);
    
    tmp_node = xmlAddChild(doc->loaded_doc->xmlRootNode, page_ptr);
    doc->doc_props = xmlNewChild(doc->loaded_doc->xmlRootNode, NULL, "PROPS", NULL);
    
    doc->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (doc->scrolledwindow);
    
    /* MDI work here! */
    gtk_paned_pack1(GTK_PANED(parent->paned_window), 
                    doc->scrolledwindow, TRUE, FALSE);
  
    gtk_widget_push_colormap(gdk_rgb_get_colormap());
    doc->tab_canvas = GNOME_CANVAS(gnome_canvas_new());
    gtk_widget_pop_colormap();
  
    gtk_widget_show(GTK_WIDGET(doc->tab_canvas));
    gtk_container_add (GTK_CONTAINER (doc->scrolledwindow), GTK_WIDGET(doc->tab_canvas));
    gnome_canvas_set_scroll_region (GNOME_CANVAS (doc->tab_canvas), 0, 0, 800, 1002);    
    
    doc->canvas_group = gnome_canvas_root(GNOME_CANVAS(doc->tab_canvas));
    
    doc->parent = parent;
    doc->popup = create_right_click_popup(doc);
    doc->changed = FALSE;
    doc->block_title_updates = FALSE;
    
    return doc;
}

void
free_tab_doc(GtabDoc *doc)
{
    xmlFreeDoc(doc->current_doc);
    xmlFreeDoc(doc->loaded_doc);
    
    if (GTK_IS_WIDGET(doc->scrolledwindow)) {
        gtk_widget_destroy(doc->scrolledwindow);
    }
    
    g_free(doc);
}

gboolean
doc_save_check(GtabDoc *doc, gboolean can_cancel)
{
    GtkWidget *dialog;
    GtkWidget *button;
    GtkWidget *image;
    GtkWidget *label;
    GtkWidget *hbox;
    GtkWidget *align;
    GtkWidget *save_as;
    gchar     *filename;
    gint dlg_return, i;
    gboolean success = FALSE;
    
    if (doc->changed == FALSE) {
        return TRUE;
    }
    
    if (doc->filename == NULL) {
        dialog = gtk_message_dialog_new(GTK_WINDOW(doc->parent->gnometab),
                                    GTK_DIALOG_MODAL,
                                    GTK_MESSAGE_WARNING,
                                    GTK_BUTTONS_NONE,
                                    _("Do you want to save the changes you made to this document? \n\n"
                                      "Your changes will be lost if you don't save them."),
                                    NULL);
    }
    else {
        dialog = gtk_message_dialog_new(GTK_WINDOW(doc->parent->gnometab),
                                        GTK_DIALOG_MODAL,
                                        GTK_MESSAGE_WARNING,
                                        GTK_BUTTONS_NONE,
                                        _("Do you want to save the changes you made to the document \n \"%s\"? \n\n"
                                          "Your changes will be lost if you don't save them."),
                                        doc->filename);
    }
    
    
    
    button = gtk_button_new();
    label = gtk_label_new_with_mnemonic("Do_n't Save");
    gtk_label_set_mnemonic_widget(GTK_LABEL(label), button);
    image = gtk_image_new_from_stock(GTK_STOCK_NO, GTK_ICON_SIZE_BUTTON);\
    hbox = gtk_hbox_new(FALSE, 2);
    align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
    gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
    gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
    
    gtk_container_add(GTK_CONTAINER(button), align);
    gtk_container_add(GTK_CONTAINER(align), hbox);
    gtk_widget_show_all(align);
    
    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
    gtk_widget_show(button);
    
    gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button, GTK_RESPONSE_NO);
    
    if (can_cancel) {
        gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
    }
    
    // gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_NO, GTK_RESPONSE_NO);
    gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, GTK_RESPONSE_YES);
        
    gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
    
    dlg_return = gtk_dialog_run(GTK_DIALOG(dialog));
    
    gtk_widget_destroy(dialog);
    
    switch (dlg_return) {
        case GTK_RESPONSE_CANCEL:
            return FALSE;
            break;
        case GTK_RESPONSE_NO:
            return TRUE;
            break;
        default:
            if (doc->filename == NULL) {
                while (!success) {
                    save_as = gtk_file_selection_new(_("Save As"));
                    //gtk_widget_show(save_as);
                    i = gtk_dialog_run(GTK_DIALOG(save_as));
                    
                    switch (i) {
                        case GTK_RESPONSE_OK:
                            filename = g_strdup(gtk_file_selection_get_filename
                                                (GTK_FILE_SELECTION
                                                (save_as)));
                            success = save_new_tab_file(doc, filename);
                            g_free(filename);
                            break;
                        default:
                            success = TRUE;
                            break;
                    
                    }
                    gtk_widget_destroy(save_as);
                }
                return TRUE;
            }
            else {
                i = save_tab_file(doc);
                return TRUE;
            }
            
            break;
    }
    
}

gboolean 
save_new_tab_file(GtabDoc *tab_doc, gchar *filename)
{
    gboolean file_exists, file_is_dir, i;
    
    file_exists = g_file_test(filename, G_FILE_TEST_EXISTS && G_FILE_TEST_IS_REGULAR);
        
    if (file_exists) {
        gtab_warn(tab_doc->parent, "File already exists!");
        return FALSE;
    }
        
    file_is_dir = g_file_test(filename,    G_FILE_TEST_IS_DIR);
      
    if (file_is_dir) {
        gtab_warn(tab_doc->parent, "Filename not valid!");
        return FALSE;
    }
        
    if (tab_doc->filename != NULL)
    {
        g_free(tab_doc->filename);
    }
            
    tab_doc->filename = g_strdup(filename);
            
    i = save_tab_file(tab_doc);
    
    if (i) {
        add_to_history(tab_doc->parent, tab_doc->filename);
        
        return TRUE;
    }
    else {
        return FALSE;
    }
}
