#
############################################################################
# File   : relationships.pl                                                #
# Author : Supun Ruwanpura                                                 #
# Date   : 19-10-2000                                                      #
############################################################################
use strict;

use Tk::Dialog;
use Tk::Balloon;

############################################################################
# Modular level variable
my $lst_tables;        # list of table names
my $lst_columns1;      # list of column names for the first table
my $lst_columns2;      # list of column names for the second table
my $lbl_columns1;      # label displaying the table name for the columns list 1
my $lbl_columns2;      # label displaying the table name for the columns list 2
my $win_join_tables;   # this window where table relationships are defined
my $cmd_add;           # button to add the current relationship to the relationships list
my $join_str;          # table relationship two tables
my $table1;            # selected table name 1
my $table2;            # selected table name 2
my $column1;           # selected column name 1
my $column2;           # selected column name 2
my %table_joins;       # hash of all the table relationships
my $lbl_current_joins; # all the table relationships


############################################################################
# Create and display the table relationships window
sub show_table_joins
############################################################################
{
    ### create the table relationships window ###
    $win_join_tables = $win_sq_hal->Toplevel();

    $win_join_tables->title("Table Relationships - SQ-HAL");

    ### Center the window in the screen ###
    my $h = 350;    ### window height ###
    my $w = 600;    ### window width  ###
    my $x =  int(($win_join_tables->screenwidth()-$w)/2);        ### x position ###
    my $y =  int(($win_join_tables->screenheight()-100-$h)/2);   ### y position ###
    $win_join_tables->geometry("${w}x${h}+${x}+${y}");

    ### Set the minimu and maximum sizes to be the same ###
    ### so that the user can not resize the window      ###
    $win_join_tables->minsize( $w, $h );
    $win_join_tables->maxsize( $w, $h );

    ########################################################################
    ### define and plce window controls ###

    my $tooltip = $win_db->Balloon;

    my $fra_lists = $win_join_tables->Frame->pack( -side => 'top',
                                           -fill => "x",
                                           -expand => 0);

    my $fra_list1 = $fra_lists->Frame->pack( -side => 'left',
                                           -fill => "x",
                                           -expand => 1);
    my $fra_list2 = $fra_lists->Frame->pack( -side => 'left',
                                           -fill => "x",
                                           -expand => 1);
    my $fra_list3 = $fra_lists->Frame->pack( -side => 'right',
                                           -fill => "x",
                                           -expand => 1);

    $fra_list1->Label( -text => "Select the two tables\nto be joined form the following list:")
                ->pack( -side => "top",
                        -padx => 5,
                        -fill => "x",
                        -anchor => "nw",
                        -expand => 0);

    $lbl_columns1 = $fra_list2->Label( -text => "Select the joining column\nfor the table '':")
                ->pack( -side => "top",
                        -padx => 5,
                        -fill => "x",
                        -expand => 0,
                        -anchor => "nw");

     $lbl_columns2 = $fra_list3->Label( -text => "Select the joining column\nfor the table '':")
                ->pack( -side => "top",
                        -padx => 5,
                        -fill => "x",
                        -expand => 0,
                        -anchor => "nw");

    ### list of all the table names ----------------------------------------
    $lst_tables = $fra_list1->Scrolled( 'Listbox', -scrollbars => "oe",
                                              -selectmode => "multiple",
                                              -border => 3,
                                              -height => 7)
                                      ->pack( -side => "left",
                                              -padx => 5,
                                              -fill => "both",
                                              -expand => 1);
    $tooltip->attach($lst_tables,
                     -msg => "Select the two table names which involves in the relationsip.");

    ### populate the list with table names ###
    $lst_tables->insert("end", &get_table_names());

    ### update the column names lists when table names are selected ###
    $lst_tables->bind("", \&update_column_names_3);

    ### column names list for the first table ------------------------------
    $lst_columns1 = $fra_list2->Scrolled( 'Listbox', -scrollbars => "oe",
                                              -selectmode => "single",
                                              -border => 3,
                                              -height => 7)
                                      ->pack( -side => "left",
                                              -padx => 5,
                                              -fill => "both",
                                              -expand => 1);

    ### update the relationship string when the user select the column name ###
    $lst_columns1->bind("",
                         sub
                         {
                             $column1 = $lst_columns1->get($lst_columns1->curselection);
                             create_join_str();
                         }
                        );

    $tooltip->attach($lst_columns1,
                     -msg => "Select the column name that involves in the relationship.");


    ### column names list for the second table -----------------------------
    $lst_columns2 = $fra_list3->Scrolled( 'Listbox', -scrollbars => "oe",
                                              -selectmode => "single",
                                              -border => 3,
                                              -height => 7)
                                      ->pack( -side => "right",
                                              -padx => 5,
                                              -fill => "both",
                                              -expand => 1);

    ### update the relationship string when the user select the column name ###
    $lst_columns2->bind("",
                         sub
                         {
                             $column2 = $lst_columns2->get($lst_columns2->curselection);
                             create_join_str();
                         }
                        );

    $tooltip->attach($lst_columns2,
                     -msg => "Select the column name that involves in the relationship.");

    my $fra_join_str = $win_join_tables->Frame->pack( -side => "top", -fill => "x");

    ### label to display the current relationship --------------------------
    my $lbl_join_str = $fra_join_str->Label( -textvariable => \$join_str)
                                     ->pack( -side => "left",
                                             -fill => "x");

    $tooltip->attach($lbl_join_str,
                     -msg => "the current table relationship.");

    ### button to add the current relationship to the list of --------------
    ### all the relationsihips
    $cmd_add = $fra_join_str->Button( -text => "Add",
                           -state => "disabled",
                           -command =>
                           sub
                           {
                               ### add the current relationship to the list ###

                               ### if the table relationship is already defined ###
                               if ($table_joins{"$table1, $table2"})
                               {
                                   ### confirm that the user wants to overwrite the existing relationship ###
                                   my $response = $win_join_tables->Dialog( -text => "Do you want to overwrite the existing relationship?\n",
                                                             -title => "Overwrite?",
                                                             -buttons => ["Yes", "No"])->Show;

                                   if ($response eq "Yes")
                                   {
                                       ### overwrite the existing relationship ###
                                       $table_joins{"$table1, $table2"} = "$table1.$column1 = $table2.$column2";

                                       ### update the relationship display on the window ###
                                       update_joins();
                                   }
                               }
                               else    ### table relationship does not exist ###
                               {
                                   ### add the new relationship for the hash ###
                                   $table_joins{"$table1, $table2"} = "$table1.$column1 = $table2.$column2";

                                   ### update the relationship display on the window ###
                                   update_joins();
                               }
                            }
                         )
                   ->pack( -side => "right",
                           -ipadx => 20);

    $tooltip->attach($cmd_add,
                     -msg => "add the current relationship to the list of all the relationships.");

    ### label to display all the table relationships defined ---------------
    $lbl_current_joins = $win_join_tables->Label( -text => "Current table joins:\n",
                                                  -anchor => "nw")
                                          ->pack( -side => "top",
                                                  -fill => "both",
                                                  -expand => 1);

    $tooltip->attach($lbl_current_joins,
                     -msg => "all the table relationships.");

    my $fra_buttons = $win_join_tables->Frame->pack( -side => "bottom" );

    ### button to accept changes to the table relationships ----------------
    my $cmd_accept_all = $fra_buttons->Button( -text => "Accept all",
                                          -command => \&ok_pressed_for_join )
                                  ->pack( -side => "left",
                                          -padx => 10,
                                          -ipadx => 15,
                                          -pady => 10 );

    $tooltip->attach($cmd_accept_all,
                     -msg => "accept all the changes to the table relationships and close this window.");

    ### button to close this window ----------------------------------------
    my $cmd_close = $fra_buttons->Button( -text => "Cancel",
                                     -command =>
                                     sub
                                     {
                                         $win_join_tables->destroy();
                                     } )
                             ->pack( -side => "right",
                                     -padx => 10,
                                     -ipadx => 15,
                                     -pady => 10 );

    $tooltip->attach($cmd_close,
                     -msg => "ignore all the changes to the table relationships and close this window.");

    ### copy existing table joins to a hash variable ###
    %table_joins = ();
    foreach my $table (keys(%table_relationships))
    {
        foreach (keys(%{$table_relationships{$table}}))
        {
            $table_joins{"$table, $_"} = $table_relationships{$table}{$_};
        }
    }

    ### make the database structure window visible when this window get closed ###
    $win_join_tables->bind('', sub{ $win_db->MapWindow; $win_db->deiconify; } );

    ### update table joins display area ###
    update_joins();

    $win_join_tables->update();

    ### display this window ###
    $win_join_tables->raise();

    ### hide the database structure window ###
    $win_db->UnmapWindow;
}

############################################################################
# updata the two column names list with the column names for the
# two selected tables
sub update_column_names_3
############################################################################
{
    eval
    {
        ### get the indexes of the selected table names
        my @tables = $lst_tables->curselection;
        my @table_names;

        ### get the selected table names ###
        foreach ( @tables )
        {
            $table_names[++$#table_names] = $lst_tables->get($_);
        }

        ### only the first two table names are used in the table relationship ###
        ### the other table names are ignored                                 ###
        $table1 = $table_names[0];

        if ( $table_names[1] ) {
            $table2 = $table_names[1];
        }
        else {
            $table2 =  "";
        }



        ### update the labels above column names lists to display ###
        ### the coresponding table name for each list             ###
        $lbl_columns1->configure( -text => "Select the joining column\nfor the table '$table1':");
        $lbl_columns2->configure( -text => "Select the joining column\nfor the table '$table2':");

        $column1 = "";
        $column2 = "";

        ### clear column names lists ###
        $lst_columns1->delete(0, "end");
        $lst_columns2->delete(0, "end");

        ### if the first table name is defined,     ###
        ### then update the first column names list ###
        if ($table1)
        {
            eval { $lst_columns1->insert("end", &get_column_names($table1)); };
        }

        ### if the second table name is defined,     ###
        ### then update the second column names list ###
        if ($table2)
        {
            eval { $lst_columns2->insert("end", &get_column_names($table2)); };
        }

        ### create the current table relationship ###
        create_join_str();
    };
}


############################################################################
# create the current tables relationship using the select table names
# and column names
sub create_join_str
############################################################################
{
    ### define the current table relationship and display on the window ###
    $join_str = "Join tables  [ $table1, $table2 ]  on  [ $table1.$column1 = $table2.$column2 ]";

    ### all the table names and column names are defined ###
    if ($table1 && $table2 && $column1 && $column2)
    {
        ### enable the 'Add' button ###
        $cmd_add->configure( -state => "normal" );
    }
    else ### not all the table names and column names are defined ###
    {
        $cmd_add->configure( -state => "disabled" );

    }

    ### update window controls with new values ###
    $win_join_tables->update;
}

############################################################################
# update the label which display all the defined relationships
sub update_joins
############################################################################
{
    my $str = "Current table joins:\n";

    ### create a string which contains formatted table relationships
    foreach (keys(%table_joins))
    {
        $str .= "Join tables [ $_ ] on [ ${table_joins{$_}} ]\n";
    }

    ### display the table relationships sting ###
    $lbl_current_joins->configure( -text => $str );
}

############################################################################
# save the relationships and close this window
sub ok_pressed_for_join
############################################################################
{
    ### empth the table relationships hash ###
    %table_relationships = ();

    ### copy existing relationships to table relationships ###
    ### i.e. save changes to the table relationships
    foreach my $tables (keys(%table_joins))
    {
        my ($tb1, $tb2) = split(", ", $tables);

        $table_relationships{$tb1}{$tb2} = $table_joins{$tables};
    }

    ### save database structure to a file ###
    save_db_info();

    ### close this window ###
    $win_join_tables->destroy();
 }

1;    ### so the 'do' command succeeds ###