/**************************************************************
 * Structured Markov Chains Solver       [  SMCSolver  ]      *
 * Dario Bini, Beatrice Meini, Sergio Steffe'                 *
 * bini@dm.unipi.it, meini@dm.unipi.it, steffe@dm.unipi.it    *
 * Dipartimento di Matematica "Leonida Tonelli"               *
 * Largo Pontecorvo 5                                         *
 * 56127 Pisa                                                 *
 * Italy                                                      *
 * Version 1.1 - Oct 2006                                     *
 **************************************************************
 *
 *  padwrite.c -  writing asyncronously on the NotePad of the Main Window and keep situation bar up to date .
 *
 */

#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <libgen.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <time.h>

#include "structures.h"
#include "padwrite.h"

pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;  /* this macro must be called just once */
 
/* append some text in a FIFO buffer */
void append_fifo_(char *text)
{
struct timespec small_wait;
small_wait.tv_sec=0;
small_wait.tv_nsec=1000000; /* 1000000 nano sec = 1+1msec */
/* pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; global */
/* int fifosi=0, fifoin=0, fifoout=0, fifomax=50; global      */
/* fifomax aumentato a 200 righe */
pthread_mutex_lock( &my_mutex ); 
strncpy(fifostr[fifoin],text,119);
fifoin++;
if (fifoin==fifomax) fifoin=0;
fifosi=1;
/* this 1 msec delay is an empirical cure for a race condition ! */
/* may be nanosleep can be used instead */
/* system("/bin/sleep 0.001\n"); */
pthread_mutex_unlock( &my_mutex );
nanosleep(&small_wait,NULL);
pthread_testcancel();  /* cancellation point for fortran programs */
nanosleep(&small_wait,NULL);
}
/*********************************/

/* write text from FIFO buffer on textview in Main Window */
gint fifo_inwin(void)
{
/* pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; global */
/* int fifosi=0, fifoin=0, fifoout=0, fifomax=50; global      */
/* char fifostr[50][120]; global */
/* int is_completed;     global */
/* GtkWidget *textview; global */
GtkTextBuffer *buffer;
GtkTextIter  enditerm, startiterm;
GtkTextMark *endmarkm;
/* GtkWidget *statusb global */

gdk_threads_enter ();
pthread_mutex_lock( &my_mutex );
if(is_completed ==1) {
/* pthread_mutex_lock( &my_mutex );*/
is_completed=0;
 clean_statusb();
/* pthread_mutex_unlock( &my_mutex ); */
}
if (fifosi==1) {
/*   pthread_mutex_lock( &my_mutex );*/
   buffer = (GtkTextBuffer *) gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
   /* follow circularly fifoin, until you reach it and set fifosi=0 */
   gtk_text_buffer_get_end_iter(buffer,&enditerm);
   gtk_text_buffer_insert(buffer,&enditerm,fifostr[fifoout],-1); 
   fifoout++;
   if (fifoout == fifomax) fifoout=0;
   if (fifoout == fifoin) fifosi=0; 
 
   gtk_text_buffer_get_end_iter(buffer,&startiterm);
   gtk_text_buffer_get_end_iter(buffer,&enditerm);
   endmarkm=gtk_text_buffer_create_mark (buffer,"endmark",&enditerm,FALSE);
   gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW(textview),endmarkm, 0,0,0,0);
/*   pthread_mutex_unlock( &my_mutex);*/
  }
 pthread_mutex_unlock( &my_mutex);
gdk_threads_leave ();
/* return 1 to let it run always in idle time loop until run is finished and fifo is void */
if ((is_running==0)&&(is_completed==0)&&(fifosi==0)) return(0); else return(1);
}
/*********************************/

/* update situation bar in main window  - one shot routine  */
gint
selection_uptodaten(void)
{
/* GtkWidget *handlebox_s; global */
/* GtkWidget *label_s1, *label_s2, *label_s3, *label_s4; globals */
/* algorithms_choice; global */
/* "PROBLEM                DATA                       ALGORITHM                       GOAL" */
int k;
char tmp[256];
 k=0;
 if (committed.allocated ==1) {
   switch (committed.type){
        case 1: gtk_label_set_text (GTK_LABEL(label_s1),"QBD"); k=1; break;
        case 2: gtk_label_set_text (GTK_LABEL(label_s1),"M/G/1"); k=2; break;
        case 3: gtk_label_set_text (GTK_LABEL(label_s1),"GI/M/1"); k=3; break;
        default:gtk_label_set_text (GTK_LABEL(label_s1),"Unknown");
        }
   if (committed.example !=0) {sprintf(tmp,"Example %d",committed.example);gtk_label_set_text (GTK_LABEL(label_s2),tmp); }
        else {sprintf(tmp,"Read from File"); gtk_label_set_text (GTK_LABEL(label_s2),tmp); }
   } else {
        switch (selected.type){
           case 1: gtk_label_set_text (GTK_LABEL(label_s1),"QBD"); gtk_label_set_text (GTK_LABEL(label_s2),"Still to Read");k=1; break;
           case 2: gtk_label_set_text (GTK_LABEL(label_s1),"M/G/1"); gtk_label_set_text (GTK_LABEL(label_s2),"Still to Read");k=2; break;
           case 3: gtk_label_set_text (GTK_LABEL(label_s1),"M/G/1"); gtk_label_set_text (GTK_LABEL(label_s2),"Still to Read"); k=3; break;
           default: gtk_label_set_text (GTK_LABEL(label_s1),"Unknown");gtk_label_set_text (GTK_LABEL(label_s2),"Still to Read");
           }
   }

 switch (algorithms_choice.type){
        case 1: if( algorithms_choice.cr_base==1) gtk_label_set_text (GTK_LABEL(label_s3),"Cyclic Reduction(basic)");
                if( algorithms_choice.cr_shift==1) gtk_label_set_text (GTK_LABEL(label_s3),"Cyclic Reduction(shift)");
                if( algorithms_choice.cr_diag==1) gtk_label_set_text (GTK_LABEL(label_s3),"Cyclic Reduction(diag.adj.)");
                break;
        case 2: if( algorithms_choice.lr_base==1) gtk_label_set_text (GTK_LABEL(label_s3),"Logarithmic Reduction(basic)");
                if( algorithms_choice.lr_shift==1) gtk_label_set_text (GTK_LABEL(label_s3),"Logarithmic Reduction(shift)");
                if( algorithms_choice.lr_gth==1) gtk_label_set_text (GTK_LABEL(label_s3),"Logarithmic Reduction(diag.adj.)");
                break;
        case 3: if((algorithms_choice.fi_base0==1)&&(algorithms_choice.fi_natural==1))gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(natural,basic,x(0)=0)");
                if((algorithms_choice.fi_base0==1)&&(algorithms_choice.fi_traditional==1))gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(traditional,basic,x(0)=0)");
                if((algorithms_choice.fi_base0==1)&&(algorithms_choice.fi_Ubased==1))gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(U-based,basic,x(0)=0)");
                if((algorithms_choice.fi_base1==1)&&(algorithms_choice.fi_natural==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(natural,basic,x(0)=I)");
                if((algorithms_choice.fi_base1==1)&&(algorithms_choice.fi_traditional==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(traditional,basic,x(0)=I)");
                if((algorithms_choice.fi_base1==1)&&(algorithms_choice.fi_Ubased==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(U-based,basic,x(0)=I)");



                if((algorithms_choice.fi_base_u==1)&&(algorithms_choice.fi_natural==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(natural,basic,x user)");
                if((algorithms_choice.fi_base_u==1)&&(algorithms_choice.fi_traditional==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(traditional,basic,x user)");
                if((algorithms_choice.fi_base_u==1)&&(algorithms_choice.fi_Ubased==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(U-based,basic,x user)");



                if((algorithms_choice.fi_shift==1)&&(algorithms_choice.fi_natural==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(natural,shift)");
                if((algorithms_choice.fi_shift==1)&&(algorithms_choice.fi_traditional==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(traditional,shift)");
                if((algorithms_choice.fi_shift==1)&&(algorithms_choice.fi_Ubased==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(U-based,shift)");

                if((algorithms_choice.fi_shift_u==1)&&(algorithms_choice.fi_natural==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(natural,shift, x user)");
                if((algorithms_choice.fi_shift_u==1)&&(algorithms_choice.fi_traditional==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(traditional,shift, x user)");
                if((algorithms_choice.fi_shift_u==1)&&(algorithms_choice.fi_Ubased==1)) gtk_label_set_text (GTK_LABEL(label_s3),"Functional Iteration(U-based,shift, x user)");



                break;
        case 4: if( algorithms_choice.is_base==1) gtk_label_set_text (GTK_LABEL(label_s3),"Invariant Subspace(basic)");
                if( algorithms_choice.is_balzer==1) gtk_label_set_text (GTK_LABEL(label_s3),"Invariant Subspace(Balzer)");
                if( algorithms_choice.is_schur==1) gtk_label_set_text (GTK_LABEL(label_s3),"Invariant Subspace(Schur)");
                break;
        default: gtk_label_set_text (GTK_LABEL(label_s3),"Unknown");
        }
 switch(k){
        case 1:
                if(goals_choice.qbd_g==1) {gtk_label_set_text (GTK_LABEL(label_s4),"G only"); break;}
                if(goals_choice.qbd_gr==1) {gtk_label_set_text (GTK_LABEL(label_s4)," G and R"); break;}
                if(goals_choice.qbd_gru==1) {gtk_label_set_text (GTK_LABEL(label_s4),"G, R and U"); break;}
                if(goals_choice.qbd_grupi==1) {gtk_label_set_text (GTK_LABEL(label_s4),"Gr, R, U, Pi"); break;}
        case 2:
                if(goals_choice.mg1_g==1) {gtk_label_set_text (GTK_LABEL(label_s4),"G only"); break;}
                if(goals_choice.mg1_gpi==1) {gtk_label_set_text (GTK_LABEL(label_s4),"G and Pi"); break;}
        case 3:
                if(goals_choice.gim1_r==1) {gtk_label_set_text (GTK_LABEL(label_s4),"R only"); break;}
                if(goals_choice.gim1_rpi==1) {gtk_label_set_text (GTK_LABEL(label_s4),"R and Pi"); break;}
        default: gtk_label_set_text (GTK_LABEL(label_s4)," ");

        }
return(0); /* one shot */
}
/*******************************/

/*  delayed close of parameters modal window */
gint
delayed_close(void)
{
/* ok button corrects a out of bound parameter, and uses a delayed close to give 2 sec of time to see the correction done */
if(is_parameters==1) {
     is_parameters=0;
     sleep(2);
     gtk_widget_destroy(window_parameters);
     }
return(0); /* one shot */
}
/*******************************/

/*  delayed close of pi parameters modal window */
gint
pi_delayed_close(void)
{
/* ok button corrects a out of bound parameter, and uses a delayed close to give 2 sec of time to see the correction done */
if(is_pi_parameters==1) {
     is_pi_parameters=0;
     is_pi_parameters_open=0;
     sleep(2);
     gtk_widget_destroy(window_pi_parameters);
     }
return(0); /* one shot */
}
/*******************************/


/*  delayed close of example ok  window */
gint
delayed_examples_close(void)
{
/* ok button corrects a out of bound float, and uses a delayed close to give 2 sec of time to see the correction done */
if(is_examples_open ==1) {
     sleep(2);
     is_examples_open=0;
     gtk_widget_destroy(window_examples);
     }
return(0); /* one shot */
}
/*******************************/

