/** File template.c
 *
 */
#include <stdlib.h>
#include <string.h>

#include "template.h"

#include "files.h"
#include "globals.h"
#include "utils.h"
#include "noxprotos.h"
#include "ng_objects.h"
#include "nn_cmd.h"
#include "nn_tree.h"

#define WT(w) if (force || tp->w != (w) ) 

extern void nn_cmd_prefix     (char *pref);
extern void nn_cmd_obj_prefix (QDobject *new ,char *prefix);
extern void nn_cmd_axis	      (int gno ,int axisno
			       ,tickmarks *old ,world *w_old ,QDobject *oobj 
			       ,int all ,int undo_on);
extern void nn_cmd_prt 	      (char *buf);


Template *template_new (void)
{
  Template *tp;
  tp = malloc (sizeof (Template));
  tp->fonts   	  = NULL;
  tp->cmap    	  = NULL;
  tp->sformat 	  = NULL;
  tp->timestamp.s = NULL;
  return tp;
}

Template *template_set (Template *tp)
{
  int i;
  Qtype typ;
  CMap_entry *cmap;
  tickmarks *ptm;
  if (tp == NULL) tp = template_new ();
  tp->version = bi_version_id();
  get_device_page_dimensions (tdevice ,&(tp->wpp)  ,&(tp->hpp));

  tp->scrollper 		= scrollper;
  tp->shexper   		= shexper;
  tp->scrolling_islinked = scrolling_islinked;

  /* Fonts mapping  */
  tp->nfonts = number_of_fonts ();
  tp->fonts = xmalloc (tp->nfonts * sizeof(FontDB));
  for (i = 0; i < tp->nfonts; i++) {
    tp->fonts[i].mapped_id = get_font_mapped_id (i);
    tp->fonts[i].alias     = copy_string (NULL ,get_fontalias (i));
    tp->fonts[i].fallback  = copy_string (NULL ,get_fontfallback (i));
  }

  /* Color map */
  tp->ncolors = number_of_colors();
  tp->cmap = xmalloc (tp->ncolors * sizeof(CMap_entry));
  for (i = 0; i < tp->ncolors; i++) {
    cmap = get_cmap_entry(i);
    if (cmap != NULL && cmap->ctype == COLOR_MAIN) {
      tp->cmap[i].rgb.red   = cmap->rgb.red;
      tp->cmap[i].rgb.green = cmap->rgb.green;
      tp->cmap[i].rgb.blue  = cmap->rgb.blue;
      tp->cmap[i].tstamp    = cmap->tstamp;
      tp->cmap[i].cname     = copy_string (NULL ,cmap->cname);
    }
  }

  /* Date */
  tp->ref_date  	    = get_ref_date ();
  tp->two_digits_years_flag = two_digits_years_allowed ();
  tp->wrap_year             = get_wrap_year ();

  /* Regions */
  tp->rg = rg[0];

  /* Graph  */
  tp->grdefaults  = grdefaults;
  tp->gr          = copy_graph_params (get_cg ());
  tp->sformat     = copy_string (NULL ,sformat);
  tp->bgcolor 	  = getbgcolor();
  tp->bgfill      = getbgfill ();
  tp->timestamp   = objs[iTS];

  /* Axis */
  ptm             = get_graph_tickmarks (/* gno= */ 0 ,/* axisno = */ 0); 
  tp->tmarks      = copy_graph_tickmarks (ptm);

  /* Objects defaults */
  for (typ = 0; typ < Q_Last; typ++) {
    obj_get_template (typ ,&(tp->objs[typ]));
  }

  /* 22 This use intrinsic defaults */

  tp->xscale = tp->yscale = SCALE_NORMAL;
  /* Sets */
  set_default_plotarr (&(tp->p));
  /* Legend */
  //  get_graph_legend (/* gno= */ 0  ,&(tp->l) ,&(tp->objs[Q_LegendBox]));
  set_default_legend (&(tp->l));

  return tp;
}

static FILE *ppa = NULL;

static void print_compound (int i ,int depth)
{
  int child;
  if (objs[i].typ == Q_Compound) {
    child  = objs[i].child;
    if (objs[i].s != NULL) {
      fprintf (ppa ,"@ New Compound %d \"%s\" %s %d\n" ,objs[i].id ,objs[i].s ,Qtype_name[objs[child].typ] ,objs[child].id);
    } else {
      fprintf (ppa ,"@ New Compound %d %s %d\n"        ,objs[i].id 	      ,Qtype_name[objs[child].typ] ,objs[child].id);
    }
    while (objs[child].brother >= 0) {
      child = objs[child].brother;
      fprintf (ppa ,"@   Compound %d %s %d\n" ,objs[i].id 
	       ,Qtype_name[objs[child].typ]
	       ,objs[child].id);
    }
    fprintf (ppa, "@   Compound  %d hidden %s\n"            ,objs[i].id ,true_or_false (objs[i].hidden));
    fprintf (ppa ,"@   Compound  %d loctype %s\n"           ,objs[i].id ,w_or_v (objs[i].loctyp));
    fprintf (ppa ,"@   Compound  %d : %f , %f , %f , %f\n"  ,objs[i].id ,objs[i].x1 ,objs[i].y1 ,objs[i].x2 ,objs[i].y2);
  }
}




void params_diff (FILE *pp ,Template *tp ,int force)
{
  int i ,gno ,setno ,axisno ,num;
  QDobject o ,*template_obj ,*template_colorbar;
  char *nmt = NULL;
  int subarc = 0;
  int wpp, hpp;
  CMap_entry *cmap;
  char prefix[64];
  region old_rg;
  tickmarks *tm_old;
  world w_old;
  plotarr p ,*template_plotarr;

  ppa = pp;
  if (pp == NULL) return;

  nn_cmd_set_filep (pp);
 
  fprintf(pp, "# -*- sh -*-\n");          /* to set emacs mode */
  fprintf(pp, "# Grace diff project file\n");
  fprintf(pp, "#\n");
 
  fprintf(pp, "@ Version %ld\n", bi_version_id());
 
  /* Page size is always copied */
  get_device_page_dimensions (tdevice, &wpp, &hpp);
  fprintf(pp, "@page size %d, %d\n" ,wpp, hpp);
  WT(scrollper)   	   fprintf(pp ,"@page scroll %d%%\n" ,(int) rint(scrollper * 100));
  WT(shexper)   	   fprintf(pp ,"@page inout %d%%\n"  ,(int) rint(shexper * 100));
  WT(scrolling_islinked)   fprintf(pp, "@link page %s\n"     ,scrolling_islinked ? "on" : "off");
     
  /* Fonts mapping  */
  int nfonts = number_of_fonts ();
  for (i = 0; i < nfonts; i++) {
    if (force ||tp->fonts[i].mapped_id != get_font_mapped_id (i) ||
    	compare_strings (tp->fonts[i].alias    ,get_fontalias (i))    == FALSE ||
    	compare_strings (tp->fonts[i].fallback ,get_fontfallback (i)) == FALSE) {
      if (get_font_mapped_id (i) != BAD_FONT_ID) {
    	fprintf(pp, "@map font %d to \"%s\", \"%s\"\n"
    		,get_font_mapped_id(i)
    		,get_fontalias(i)
    		,get_fontfallback(i));
      }
    }
  }
    
  /* Color map */
  int ncolors = number_of_colors();
  for (i = 0; i < ncolors; i++) {
    cmap = get_cmap_entry(i);
    if (cmap != NULL && cmap->ctype == COLOR_MAIN) {
      if (force ||
    	  tp->cmap[i].rgb.red   != cmap->rgb.red   ||
    	  tp->cmap[i].rgb.green != cmap->rgb.green ||
    	  tp->cmap[i].rgb.blue  != cmap->rgb.blue  ||
    	  compare_strings (tp->cmap[i].cname ,cmap->cname) == FALSE
    	  )     fprintf(pp, "@map color %d to (%d, %d, %d), \"%s\"\n"
    			,i ,cmap->rgb.red ,cmap->rgb.green ,cmap->rgb.blue,
    			PSTRING(cmap->cname));
    }
  }
    
  if (force || tp->ref_date  != get_ref_date ())    fprintf(pp ,"@reference date %.12g\n" ,get_ref_date ());
  if (force || tp->two_digits_years_flag != two_digits_years_allowed ())
    fprintf(pp, "@date wrap %s\n" 	 ,on_or_off(two_digits_years_allowed ()));
  if (force || tp->wrap_year != get_wrap_year ())   fprintf(pp ,"@date wrap year %d\n"    ,get_wrap_year ());
  WT(grdefaults.linew)    fprintf(pp ,"@default linewidth %.1f\n" ,grdefaults.linew);
  WT(grdefaults.lines)    fprintf(pp ,"@default linestyle %d\n"   ,grdefaults.lines);
  WT(grdefaults.color)    fprintf(pp ,"@default color %d\n"       ,grdefaults.color);
  WT(grdefaults.pattern)  fprintf(pp ,"@default pattern %d\n"     ,grdefaults.pattern);
  if (force || tp->grdefaults.font != get_font_mapped_id(grdefaults.font)) 
    fprintf(pp, "@default font %d\n" ,get_font_mapped_id (grdefaults.font));
  WT(grdefaults.charsize) fprintf(pp, "@default char size %f\n"   ,grdefaults.charsize);
  WT(grdefaults.symsize)  fprintf(pp, "@default symbol size %f\n" ,grdefaults.symsize);
  fprintf(pp, "@default sformat \"%s\"\n"   ,PSTRING(sformat));
  fprintf(pp, "@background color %d\n"     ,getbgcolor());
  fprintf(pp, "@page background fill %s\n" ,on_or_off(getbgfill()));
    
  /* Timestamp  (inclure dans la boucle ? ) */
  nn_cmd_obj_prefix (&objs[iTS] ,prefix);
  nn_cmd_prefix     (prefix);
  nn_cmd_obj        (&(tp->timestamp) ,&objs[iTS] ,force ,FALSE);
 
  /* Geometric objects */
  for (i = iTS+1; i < objs_max(); i++) {
    o = objs[i];
    switch (o.typ) {
    case Q_Line:
    case Q_Polyline:
    case Q_Arc:
    case Q_String:
    case Q_Box:
      if (obj_is_active (i) && o.id >= 0) {  // Q_LegendBox a inclure ?
	if (o.father_id > -2) { 
	  nmt = Qtype_name[o.typ];
	  switch (o.typ) {        /* for Grace-5 compatibility */
	  case Q_Arc:
	    subarc = arc_subtyp (o.pmask);
	    if (subarc == 1) nmt =  "Ellipse";
	    break;
	  case Q_Polyline:
	    if (o.nxy == 2) nmt = "Line";
	    break;
	  default:
	    break;
	  }
 	  fprintf (pp ,"@ WITH %s %d\n" ,nmt ,o.id);
 	  nn_cmd_obj_prefix (&o ,prefix);
 	  nn_cmd_prefix     (prefix);
 	  nn_cmd_obj        (&(tp->objs[o.typ]) ,&o ,force ,FALSE);
	}
	break;
      default:
	/* other types are printed elsewhere */
	break;
      }
    }
  }
 
  /* Compounds are always written and
   * we must start with the compounds the further from the root */
  nn_traverse_child_first (0 ,NULL ,print_compound);
 
  /* Regions */
  for (i = 0; i < MAXREGION; i++) {
    old_rg = tp->rg;
    sprintf 	    	 (prefix ,"@r%d" ,i);
    nn_cmd_prefix 	 (prefix);
    nn_cmd_on_off 	 (&(old_rg.active) ,rg[i].active ,"%s %s\n");
    sprintf 	    	 (prefix ,"@link r%d" ,i);
    nn_cmd_prefix 	 (prefix);
    nn_cmd_i      	 (&(old_rg.linkto) ,rg[i].linkto ,"%s to g%d\n");
    sprintf 	    	 (prefix ,"@r%d" ,i);
    nn_cmd_prefix 	 (prefix);
    nn_cmd_region_type (&(old_rg.type)  ,rg[i].type   ,"%s type %s\n");
    nn_cmd_i           (&(old_rg.lines) ,rg[i].lines  ,"%s linestyle %d\n");
    nn_cmd_d           (&(old_rg.linew) ,rg[i].linew  ,"%s linewidth %.1f\n");
    nn_cmd_i           (&(old_rg.color) ,rg[i].color  ,"%s color %d\n");
    nn_cmd_region_line (&(old_rg)       ,i            ,"%s line %.12g, %.12g, %.12g, %.12g\n");
 
  }

  /* Graphs */
  for (gno = 0; gno < number_of_graphs (); gno++) {
    fprintf (pp ,"@ WITH G%d\n" ,gno);
    nn_cmd_graph (gno ,tp->gr ,force ,FALSE ,FALSE);
    tm_old = tp->tmarks;
    w_old  = tp->gr->w;
    num    = obj_tid_get_num (Q_Axis ,0 ,Q_Graph ,gno);
    /* Axes */
    nn_cmd_graph_scale (&(tp->xscale)  ,gno ,X_AXIS 	      ,"%s xaxes scale %s\n");
    nn_cmd_graph_scale (&(tp->yscale)  ,gno ,Y_AXIS 	      ,"%s yaxes scale %s\n");
    nn_cmd_on_off      (&(tp->xinvert) ,is_graph_xinvert(gno) ,"%s xaxes invert %s\n");
    nn_cmd_on_off      (&(tp->yinvert) ,is_graph_yinvert(gno) ,"%s yaxes invert %s\n");
    for (axisno = 0; axisno < MAXAXES; axisno++) {
      nn_cmd_axis (gno ,axisno ,tm_old ,&w_old ,&objs[num] ,force ,FALSE);
    }
    /* Legend box */
    nn_cmd_legendbox (gno ,&(tp->l) ,&(tp->objs[Q_LegendBox]) ,force ,FALSE);
    /* Sets */
    for (setno = 0; setno < number_of_sets(gno); setno++) {
      get_graph_plotarr         (gno, setno, &p);
      num = obj_tid_get_set_num (gno ,setno);
      template_plotarr 	= &(tp->p);
      template_obj     	= &(tp->objs[Q_Set]);
      template_colorbar = &(tp->objs[Q_Colorbar]);
      nn_cmd_set (gno ,setno ,template_plotarr ,template_obj ,template_colorbar
		  ,p ,objs[num] ,force ,FALSE);
    }
    
  }
  /* Assume file is closed after the call */
  nn_cmd_set_filep (NULL);
}
