/*===========================================================================
  Copyright (C) 1989-2009 European Southern Observatory (ESO)
 
  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., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        tbmerge.c
.LANGUAGE    C
.AUTHOR      IPG-ESO Garching
.CATEGORY    table utilities
.COMMENTS	This module implements the following Midas commands:
\begin{TeX}
\begin{enumerate}
\item {\tt MERGE/TABLE} intable {\em [intable ...]} outable
\item {\tt COPY/TABLE} intable outable
\end{enumerate}
\end{TeX}

.VERSION 1.0 	25-Mar-1989   Definition     J.D. Ponz
.VERSION 3.0 	05-Jul-1990   New version with column arrays   F.O.
.VERSION 3.1    18-Apr-1991   Copy non standard descriptors  MP

 090708		last modif
------------------------------------------------------------*/

#include <tbldef.h>
#include <midas_def.h>
#include <proto_tbl.h>

#include <stdio.h>


#define PARLEN 80
#define TABLES 7	


extern int tbl_getarg(), tbl_argc(), tbl_copycol(), tbl_appcol();


int tbl_merge()
/*++++++++++++++++++
.PURPOSE Merge several tables into one new output table. Or copy one to another
.RETURNS Status
------------------*/
{
  char intable[PARLEN], outable[PARLEN], field[PARLEN];
  char nhform[PARLEN],fname[PARLEN];
  char label[1+TBL_LABLEN], form[10], unit[11+TBL_UNILEN];
  char linesel[77+PARLEN],line[65],action[1];
  int  kuni;
  int  table[TABLES], nc[TABLES], nr[TABLES];
  int  tid, nac, nar, phform;
  int  nsel, ntot, npar, nstart,len,ii;
  int  ncol, nrow;
  int  status, i, j,  nout, oc, type, items;
  int  tid1, tid2;
  int  dummy,bytes;

  npar = tbl_argc();
  tid = -1;

                                        /* open main input tables */
  status = tbl_getarg(1, PARLEN, intable);
  status = TCTOPN(intable,F_I_MODE,&tid);
  if (status != ERR_NORMAL) 
  {
	SCTPUT("Error opening input table");
        return (status);
  }
                              /* read table size information: */	
  status = TCIGET(tid,&ncol,&nrow,&dummy,&nac,&nar);
                              /* read storage foramt F_TRANS or F_RECORD: */
  status = TCDGET(tid,&phform);
                              /* count selected rows: */
  status = TCSCNT(tid,&nsel);
  
  table[0] = tid;             /* ID of input table */
  nc[0]    = ncol;            /* number of columns in input table */
  nr[0]    = nrow;            /* number of rows in input table */
  ntot     = nsel;            /* number of selected rows */ 
  (void) SCKRDC("ACTION",1,1,1,&dummy,action,&kuni,&dummy);

                                                /* count input rows */
  if ((action[0] == 'M')) 			/* only for merge/table */
  {
     	for (i=2; i<npar; i++) 
     	{
        	status = tbl_getarg(i, PARLEN, fname);
        	status = CGN_FRAME(fname,3,field,0);
        	status = TCTOPN(field,F_I_MODE,&tid);
        	if (status != ERR_NORMAL) 
		{
                	SCTPUT("Error opening input table");
                	return (status);
        	}
        	status = TCIGET(tid,&ncol,&nrow,&dummy,&dummy,&nar);
        	status = TCSCNT(tid,&nsel);
        	table[i-1] = tid;
        	nc[i-1]    = ncol;
        	nr[i-1]    = nrow;
        	ntot       = ntot + nsel;       /* add all selected rows! */
    	}
  }                                        /* init output table */
	


/*  status = tbl_getarg(npar, PARLEN, outable); */

  if ((action[0] == 'C') && (npar == 3))    /* only for COPY/TABLE and only*/
  {					/* if 3 parameters entered*/
       	status = tbl_getarg(2, PARLEN, fname);
        status = CGN_FRAME(fname,3,outable,0);
       	status = tbl_getarg(3, PARLEN, nhform);
	
       	if ((nhform[0] == 'R') || (nhform[0] == 'r')) 
	{
		phform = F_RECORD;		/*data organisation=RECORD*/
	}
       	else  
	{
		phform = F_TRANS;		/*data organisation=TRANSPOSED*/
	}
  }
  else  
   {
   int   begin, lenn;
   char  cfield[64], kfield[64];

   status = tbl_getarg(npar, PARLEN, fname);	/* get last param */
   begin = 0;
   lenn = (int) strlen(fname); 
   
   /* check, if we have too many input tables: tba tbb ... outable */

   for (i=0; i<20; i++)
      {
      ii = CGN_EXTRSS(fname,lenn,' ',&begin,cfield,60);
      if (ii < 0)			/* end of string reached */
         {
         if (i > 1)
            {			/* several names here... */
            char  texto[80];

            SCTMES(M_BLUE_COLOR,"WARNING: more than 7 input tables!");
            (void) tbl_getarg(7, PARLEN, fname);	/* get 7th in_table */
            (void) sprintf(texto,"last input table: %s - others are ignored",
                           fname);
            SCTMES(M_BLUE_COLOR,texto);
            (void) sprintf(texto,"output table used: %s",kfield);
            SCTMES(M_BLUE_COLOR,texto);
            }
         break;
         }
      else
         (void) strcpy(kfield,cfield);
      }

   status = CGN_FRAME(kfield,3,outable,0);
   }
	
/* initialize outtable: */
  status = TCTINI(outable,phform,F_O_MODE, nac, ntot, &tid1);

  if (status != ERR_NORMAL) 
  {
	SCTPUT("Error creating output table");
        return (status);
  }

                                        /* create the columns and copy them*/
  ncol = nc[0]; 
  tid = table[0];
  nrow = nr[0];
  
  nout = 0;
  for (i=1; i<=ncol; i++)  /* step through all columns */
  {	
        TCFGET(table[0],i, form, &dummy, &type);   /* read column format */
        TCLGET(table[0],i, label);                 /* reads column label */
        TCUGET(table[0],i, unit);                  /* reads column unit */
        TCBGET(table[0],i, &type, &items, &bytes); /* reads binary storage*/
	                                           /* characteristics of column*/
                                                   /* returns D_xx_FORMAT */ 
        if (type == D_C_FORMAT) 
	{ 
            /* initialize character table column */
            TCCINI(tid1, type, bytes, form, unit, label, &oc);
        }
	else
	{ 
            /* initialize other table column */
            TCCINI(tid1, type,items, form, unit, label, &oc);
        }
        if (type == D_C_FORMAT && items !=1 )
            TCAPUT(tid1,oc,items);
        if (nrow != 0) /* if number of input rows not zero */
        {
            tbl_copycol(table[0],i, tid1,oc, type, nrow, &nout);
        }
  }
  nstart = nout;


					/* append rest of the rows */
  if (( action[0] == 'M')) 		/* only for merge/table */
  {
	for (j=2; j<npar; j++)
	{		/* in all the input tables */
		tid2 = table[j-1]; 
		nrow = nr[j-1]; 
        	if (nrow == 0) continue;
		for (i = 1; i<=ncol; i++) 
		{
			/* and for all the columns */
			TCLGET(tid,i,label);
			TCFGET(tid,i,form,&dummy,&type);
			TCLSER(tid2,label,&ii);
			if (ii <= 0) continue;
			nout = nstart;
			tbl_appcol(tid2,ii,tid1,i,type,nrow,&nout);
 		}
		nstart = nout;
     	}
  }

  if (( action[0] == 'C')) 		/*only for COPY/TABLE*/
  {
	SCDCOP(tid,tid1,3," ");  /* copy descriptors from tid to tid1 */ 
	TCSINF(tid,line);        /* get selection info */
	
	if (line[0] != '-')            /* sel/tab is NOT all */
        {                           
	   /* update the descriptor HISTORY */
           (void) sprintf(linesel,"SELECT/TAB %s ",intable);
           (void) strcat(linesel,line);
           len = (int) strlen(linesel); 
           SCDWRC(tid1,"HISTORY",1,linesel,-1,80,&kuni);
           while (len>80)
           {
            	ii = 0;
            	while (linesel[ii+80])
	    		{
			linesel[ii] = linesel[ii+80];
			ii++;    		    
	    		}
            	(void) SCDWRC(tid1,"HISTORY",1,linesel,-1,80,&kuni);
            	len -= 80;
           }
        }
  }

  else                         /* if not COPY/TABLE ===> for MERGE/TABLE*/
  {
     	for (j=1; j<npar; j++)
	{
        	tid2 = table[j-1];
         	(void) SCDCOP(tid2,tid1,3," "); 
         	TCSINF(tid,line);
         	if (line[0] != '-')
           	{
            	    (void) sprintf(linesel,"SELECT/TAB %s ",intable);
            	    (void) strcat(linesel,line);
            	    len = (int) strlen(linesel);
            	    (void) SCDWRC(tid1,"HISTORY",1,linesel,-1,80,&kuni);
            	    while (len>80)
                    {
            		ii = 0;
           		while (linesel[ii]) 
	    		{
			    linesel[ii] = linesel[ii+80];
			    ii++;
			}
            		(void) SCDWRC(tid1,"HISTORY",1,linesel,-1,80,&kuni);
          		len -= 80;
                    }
           	}
      	}
  }

  if (status == ERR_NORMAL) 
  {
	/*copy all descriptors and append to HISTORY*/
	CGN_DSCUPD(tid1,tid1," ");
	/* blank -> get HISTORY from keyword HISTORY and keys P1, P2, ... */
  }

  TCTCLO(tid);
  TCTCLO(tid1);

  return (status);
}
