/* Copyright (C) 1999 E. H. Haley

   accepts signals

   SIGUSR1: finish current matches() call, save current
   best matches to date and exit.

   can't deal with SIGUSR2: write to file but keep going, next write
   overwrites it.

   ../../snatches ../../pic.traga flatter.trex pic.dir.sneeter

   like matches(), but it doesn't write whole trees, just a
   contender[tarf.nnodes]

   doesn't even write contender[0], just [1]==best.  Could, though, later.

   companion programs--  matches:triage :: snatches:treeage
   
   Against a 1024^2 image, 10k tiles:
   before: Sun May 16 04:43:29 EDT 1999
   after: Mon May 17 02:42:14 EDT 1999

   a few hours on a 512^2 image, 10k-#uglies tiles

   sneetch: same thing but takes off appending where it left off.

*/

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "lib/tile.h"

void match(res *ti40s,tfile *tilf, res *tree,tfile *tarf, tile **contender)
{
  //for this tilefile, try each size on different nodes of the tree.

  int i,j, ta,ti, ea,ei, score,exp,rat, diff;

  for(ta=0; ta<tarf->nnodes; ta++)
    {
      diff = (int)(ti40s->avgy - tree[ta].avgy > 0 ?
	ti40s->avgy - tree[ta].avgy : tree[ta].avgy - ti40s->avgy);

      //      if (diff>128) continue; //won't match 
      //careful-- means there isn't always a contender.
      
      score = diff<128 ? 0 : -40;
      for(ea=0; ea<40; ea++)
	for(ei=0; ei<40; ei++)
	  {
	    if (ti40s->entry[ei].index[0]<tree[ta].side
		&& ti40s->entry[ei].index[1]<tree[ta].side)
	      //i.e. only compare low-freq-enough coeffs
	      {   
		if (tree[ta].entry[ea].index[0]
		    ==ti40s->entry[ei].index[0]
		    && tree[ta].entry[ea].index[1]
		    ==ti40s->entry[ei].index[1]
		    && tree[ta].entry[ea].index[2]
		    ==ti40s->entry[ei].index[2])
		  score+= tree[ta].entry[ea].val
		    * ti40s->entry[ei].val >0
		    ?1:0;  //i.e. if same sign
	      }
	  }

      score += 15*(256-diff)/256; //5??

      if (score > contender[0][ta].score 
	|| contender[0][ta].fname[0]=='\0') // get rid of these?
	{
	  if (score > contender[1][ta].score 
	    || contender[1][ta].fname[0]=='\0') //..?
	    {
	      //beats c0&c1: move c1->c0, new->c1
	      strcpy(contender[0][ta].fname,
		     contender[1][ta].fname);
	      strcpy(contender[1][ta].fname,
		     tilf->fname);
	      contender[0][ta].score
		=contender[1][ta].score;
	      contender[1][ta].score
		=score;
	      contender[0][ta].exp
		=contender[1][ta].exp;

	      exp=0;
	      if (tree[ta].side > ti40s->side)
		{
		  rat = tree[ta].side;
		  while (rat > ti40s->side) {rat>>=1;exp++;}
		}
	      else
		{
		  rat = ti40s->side;
		  while (rat > tree[ta].side) {rat>>=1;exp--;}
		}
		contender[1][ta].exp=exp;
	    }
	  else //beats c0 but not c1: move new->c0
	    {
	      strcpy(contender[0][ta].fname,
		     tilf->fname);
	      contender[0][ta].score
		=score;

	      exp=0;
	      if (tree[ta].side > ti40s->side)
		{
		  rat = tree[ta].side;
		  while (rat > ti40s->side) {rat>>=1;exp++;}
		}
	      else
		{
		  rat = ti40s->side;
		  while (rat > tree[ta].side) {rat>>=1;exp--;}
		}
	      contender[0][ta].exp=exp;
	    }		
	}
    }
}


int main(int aardc, char **aardv)
{
  int i,j,k,l,p, check, index, outdex, leftoffat=0, counter=0, append=0;
  FILE *tilefile, *targetfile, *outfile;
  res ti40s, *tree;
  tfile tarf, tilf;
  tile *contender[2];
  sigset_t mask, pending;
  char *outfname;

  if (aardc<4) exit(0);
  if ((targetfile=fopen(*++aardv,"r"))==NULL)
    { fprintf(stderr, "1. can't open %s\n",*aardv); exit(1); }
  if ((tilefile=fopen(*++aardv,"r"))==NULL)
    { fprintf(stderr, "2. can't open %s\n",*aardv); exit(1); }
  outfname=*++aardv;
  if (aardc>4) { leftoffat = atoi(*++aardv); append=1; }

  sigemptyset(&mask);
  sigaddset(&mask,SIGUSR1);
  sigaddset(&mask,SIGUSR2);
  sigprocmask(SIG_BLOCK,&mask,NULL);

  check=fread(&tarf, sizeof(tfile),1,targetfile);
  tree=(res *)malloc(tarf.nnodes*sizeof(res));
  check=fread(tree, tarf.nnodes*sizeof(res),1,targetfile);
  fclose(targetfile);

  contender[0]=(tile *)calloc(tarf.nnodes,sizeof(tile));
  contender[1]=(tile *)calloc(tarf.nnodes,sizeof(tile));

  while (counter++<leftoffat
	 && fread(&tilf, sizeof(tfile),1,tilefile)==1
	 && fread(&ti40s, tilf.nnodes*sizeof(res),1,tilefile))
    { printf("-"); fflush(stdout); }
    
  while (fread(&tilf, sizeof(tfile),1,tilefile)==1)
    {
      leftoffat++;
      check=fread(&ti40s, tilf.nnodes*sizeof(res),1,tilefile);
      for(i=0; i<tilf.nnodes; i++) //one, lately.
	match(&ti40s,&tilf, tree,&tarf, contender);
      sigpending(&pending);
      if(sigismember(&pending,SIGUSR1))
	{
	  outfile=fopen(outfname, append==1?"a":"w");
	  fwrite(&tarf, sizeof(tfile),1,outfile);
	  fwrite(contender[1], tarf.nnodes*sizeof(tile), 1, outfile);
	  fclose(outfile);

	  printf("\n%d\n",tarf.nnodes);
	  for(i=0; i<tarf.nnodes; i++)
	    printf("%d %s score=%d exp=%d\n",
		   tree[i].side,
		   contender[1][i].fname,
		   contender[1][i].score,
		   contender[1][i].exp);
	  fclose(tilefile);
	  fprintf(stderr,"left off at %d\n",leftoffat);
	  exit(0);
	}
      /*
      if(sigismember(&pending,SIGUSR2)) //uh-oh, it stays pending.
	{
	  fprintf(stderr,"paused for write at %d\n",leftoffat);
	  outfile=fopen(outfname, append==1?"a":"w");
	  fwrite(&tarf, sizeof(tfile),1,outfile);
	  fwrite(contender[1], tarf.nnodes*sizeof(tile), 1, outfile);
	  fclose(outfile);
	  //	  sigdelset(&pending,SIGUSR2);
	  sigemptyset(&pending);
	}
      */
      printf("#"); fflush(stdout);
    }
  outfile=fopen(outfname, append==1?"a":"w");
  fwrite(&tarf, sizeof(tfile),1,outfile);
  fwrite(contender[1], tarf.nnodes*sizeof(tile), 1, outfile);
  fclose(outfile);
  fclose(tilefile);

  printf("\n%d\n",tarf.nnodes);
  for(i=0; i<tarf.nnodes; i++)
    printf("%d %s score=%d exp=%d\n",
	   tree[i].side,
	   contender[1][i].fname,
	   contender[1][i].score,
	   contender[1][i].exp);


  free(tree);
  free(contender[0]);
  free(contender[1]);
}


