/*****************************************************************************
   Major portions of this software are copyrighted by the Medical College
   of Wisconsin, 1994-2000, and are released under the Gnu General Public
   License, Version 2.  See the file README.Copyright for details.
******************************************************************************/

#include "mrilib.h"
#include "thd.h"

extern THD_3dim_dataset *THD_3dim_from_ROIstring(char *shar);

#undef  CHECK_FOR_DATA     /* 06 Jan 2005: message about empty files */
#define CHECK_FOR_DATA(fn)                                                \
 do{ if( fsize == 0 ){                                                    \
       if( isfile )                                                       \
         fprintf(stderr,"** Can't read ANY data from file '%s'\n",(fn));  \
       RETURN(NULL) ;                                                     \
     }} while(0)


/*-----------------------------------------------------------------
 * this is a list of known filename extensions
   (as found in THD_open_one_dataset())         28 Jun 2006 [rickr]
-------------------------------------------------------------------*/
static char * file_extension_list[] = {
    ".HEAD", ".BRIK", ".BRIK.gz",
    ".mnc",
    ".mri",
    ".svl",
    ".1D",
    ".3D",
    ".nii", ".nii.gz", ".nia", ".hdr", ".img",
    ".mpg", ".mpeg", ".MPG", ".MPEG",
    ".niml", ".niml.dset"
};


/*----------------------------------------------------------------
   simply given a pathname, try to open it as a dataset
   [allow for .HEAD, .BRIK, or just prefix+viewcode filenames]
------------------------------------------------------------------*/

THD_3dim_dataset * THD_open_one_dataset( char *pathname )
{
   int ii , plen ;
   char dirname[THD_MAX_NAME] , fullname[THD_MAX_NAME] ;
   THD_3dim_dataset *dset=NULL ;  /* NULL added 23 Feb 2007, from Bernd Feige */
   THD_datablock    *dblk ;
   char *sub ;
   char *fname ;   /* to skip directory during HEAD/BRIK search in filename */
   int   offset ;  /*                                 - [rickr 20 Sep 2002] */
   long long fsize ;     /* 06 Jan 2005, to unsigned 20 Feb 2006 [rickr] */
                                      /* to long long 22 Mar 2007 [RWC] */
   int   isfile = 1;

ENTRY("THD_open_one_dataset") ;

   /*-- sanity check --*/

   if( pathname == NULL              ||
       (plen=strlen(pathname)) == 0  ||
       pathname[plen-1]        == '/'  ) RETURN(NULL) ;

   /*-- perhaps open the new-fangled way [22 May 2000] --*/

   if( getenv("AFNI_USE_THD_open_dataset") != NULL &&
       strstr(pathname,"[")                != NULL   ){
      dset = THD_open_dataset(pathname) ;
      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
      RETURN(dset) ;
   }

   fsize = THD_filesize(pathname) ;                         /* 06 Jan 2005 */

   /* replace fsize == -1 use with isfile variable   28 Feb 2007 [rickr] */
   if( fsize == 0 && !THD_is_file(pathname) ) isfile = 0;

   /*-- perhaps the MINC way --*/

   if( STRING_HAS_SUFFIX(pathname,".mnc") ){
     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_minc(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- perhaps the ANALYZE way --*/

   if( STRING_HAS_SUFFIX(pathname,".hdr") ){
     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_analyze(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- perhaps the CTF way [04 Dec 2002] --*/

   if( STRING_HAS_SUFFIX(pathname,".mri") ){
     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_ctfmri(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   } else if( STRING_HAS_SUFFIX(pathname,".svl") ){
     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_ctfsam(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- 04 Mar 2003: allow input of .1D files --*/

   if( STRING_HAS_SUFFIX(pathname,".1D") ){
     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_1D(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   } else if( STRING_HAS_SUFFIX(pathname,".3D") ){  /* 21 Mar 2003 */
     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_3D(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- 28 Aug 2003: the NIFTI way! --*/

   if( STRING_HAS_SUFFIX(pathname,".nii")    ||
       STRING_HAS_SUFFIX(pathname,".nii.gz") ||
       STRING_HAS_SUFFIX(pathname,".nia")      ){

     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_nifti(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- 03 Dec 2003: the MPEG way! --*/

   if( STRING_HAS_SUFFIX_CASE(pathname,".mpg") ||
       STRING_HAS_SUFFIX_CASE(pathname,".mpeg")  ){

     CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
     dset = THD_open_mpeg(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- 26 May 2006 [rickr]: the NIML way! --*/

   if( STRING_HAS_SUFFIX(pathname,".niml") ){

     CHECK_FOR_DATA(pathname) ;
     dset = THD_open_niml(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /*-- 26 May 2006 [rickr]: the NI_SURF_DSET way! --*/

   if( STRING_HAS_SUFFIX(pathname,".niml.dset") ){

     CHECK_FOR_DATA(pathname) ;
     dset = THD_open_niml(pathname) ;
     THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
     RETURN(dset) ;
   }

   /* -- Try to read an AFNI dataset and if that fails,
         there is one more chance                 -- */

   /*-- Must be an AFNI-formatted dataset! -------------*/
   /*-- find directory and last names in the pathname --*/

   for( ii=plen-1 ; ii >= 0 ; ii-- ) if( pathname[ii] == '/' ) break ;

   if( ii < 0 ){
     strcpy( dirname , "./" ) ;      /* fake directory name */
   } else {
     strcpy( dirname , pathname ) ;
     dirname[ii+1] = '\0' ;
   }
   offset = ii + 1 ;  /* offset of file within pathname - rickr [20 Sep 2002] */

   /*-- perform surgery on the name to make it a valid .HEAD --*/

   strcpy( fullname , pathname ) ;
   fname = fullname + offset ; /* trailing filename (past directory) - rickr */

   /* (REPLACE) sub = strstr( fullname , DATASET_HEADER_SUFFIX ) ;  * .HEAD ? */
   sub = strstr( fname , DATASET_HEADER_SUFFIX ) ;   /* .HEAD ?  r:fname */

   if( sub == NULL ){                                   /* no! */
      sub = strstr( fname , DATASET_BRICK_SUFFIX ) ; /* .BRIK ?  r:fname */

      if( sub == NULL ){                               /* no! */
         ii = strlen(fullname) ;
         if( fullname[ii-1] != '.' ) strcat( fullname , "." ) ; /* tack .HEAD */
         strcat( fullname , DATASET_HEADER_SUFFIX ) ;           /* onto end */

      } else {                                     /* yes! */
         strcpy( sub , DATASET_HEADER_SUFFIX ) ;   /* replace .BRIK with .HEAD */
      }
   }

   /*-- open it up? --*/

   fsize = THD_filesize(fullname) ;                         /* 06 Jan 2005 */
   if( fsize == 0 && !THD_is_file(fullname) ) isfile = 0;
   else                                       isfile = 1;

   /* if it is not a file, check the ROI case   28 Feb 2007 [rickr] */
   if( isfile ) {
      dblk = THD_init_one_datablock( dirname , fullname ) ;
      if( dblk != NULL ) {
         dset = THD_3dim_from_block( dblk ) ;
         THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
         RETURN(dset) ;
      }
   } else {
      /*-- Nothing worked, see if name is that of an atlas based ROI -- */
      /* fprintf(stderr,"Here's your moment %s\n", pathname); */
      dset = THD_3dim_from_ROIstring(pathname) ;
      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
      RETURN(dset) ;
   }

   /* all else failed, give them the famed message */
   CHECK_FOR_DATA(fullname) ;

   RETURN(dset) ; /* not destined to get here */
}

/*--------------------------------------------------------------------
   Returns -1 if no dataset, otherwise returns view_type.
   * If sname==NULL, then "./" is used.
   * pname mustn't be NULL.
   * If vt is a good view type (>= 0), then we only check that,
       otherwise we check all possible view types (smallest one
       found wins).
----------------------------------------------------------------------*/

int THD_is_dataset( char *sname , char *pname , int vt ) /* 17 Mar 2000 */
{
   THD_3dim_dataset *dset ;
   int ii , vv ;

ENTRY("THD_is_dataset") ;

   if( pname == NULL ) RETURN(-1) ;

   dset = EDIT_empty_copy(NULL) ;
   EDIT_dset_items( dset , ADN_prefix , pname , ADN_none ) ;

   if( sname != NULL )
     EDIT_dset_items( dset , ADN_directory_name , sname , ADN_none ) ;

   if( vt >= FIRST_VIEW_TYPE && vt <= LAST_VIEW_TYPE ){
     EDIT_dset_items( dset , ADN_view_type , vt , ADN_none ) ;
     ii = THD_is_file(dset->dblk->diskptr->header_name);
     THD_delete_3dim_dataset(dset,False) ;
     if( ii ) RETURN(vt) ;
     RETURN(-1) ;
   }

   for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
     EDIT_dset_items( dset , ADN_view_type , vv , ADN_none ) ;
     ii = THD_is_file(dset->dblk->diskptr->header_name);
     if( ii ){ THD_delete_3dim_dataset(dset,False); RETURN(vv); }
   }

   THD_delete_3dim_dataset( dset , False ) ;
   RETURN(-1) ;
}

/*--------------------------------------------------------------------*/

static int THD_deconflict_nifti( char *pfx )
{
   int lp , ls ; char suf[9] ;
   char aa,bb,cc ;

   if( !THD_is_file(pfx) ) return 0 ;

   lp = strlen(pfx) ;
   if( STRING_HAS_SUFFIX(pfx,".nii") ){
     ls = lp-4 ; strcpy(suf,".nii") ;
   } else if( STRING_HAS_SUFFIX(pfx,".nii.gz") ){
     ls = lp-7 ; strcpy(suf,".nii.gz") ;
   } else if( STRING_HAS_SUFFIX(pfx,".hdr") ){
     ls = lp-4 ; strcpy(suf,".hdr") ;
   } else {
     ls = lp   ; strcpy(suf,"\0") ;
   }

   for( aa='A' ; aa <= 'Z' ; aa++ ){
    for( bb='A' ; bb <= 'Z' ; bb++ ){
     for( cc='1' ; cc <= '9' ; cc++ ){
       pfx[ls  ] = '_' ;
       pfx[ls+1] = aa  ;
       pfx[ls+2] = bb  ;
       pfx[ls+3] = cc  ;
       pfx[ls+4] = '\0';
       strcat(pfx,suf) ;
       if( ! THD_is_file(pfx) ) return 1 ;
   }}}

   if( ls > THD_MAX_PREFIX-45 ) ls = THD_MAX_PREFIX-45 ;
   pfx[ls++] = '_' ; UNIQ_idcode_fill( pfx+ls ) ; strcat(pfx,suf) ;
   return 1;
}

/*--------------------------------------------------------------------*/
/*! Modify the prefix of a dataset to make sure it doesn't conflict
    with an existing file.  Return value is 0 if no change was
    needed, 1 if a change was made.
----------------------------------------------------------------------*/

int THD_deconflict_prefix( THD_3dim_dataset *dset )
{
   char pfx[THD_MAX_PREFIX] ; int lp  ;
   char aa,bb,cc ;

ENTRY("THD_deconflict_prefix") ;

   if( !ISVALID_DSET(dset) ) RETURN(0) ;

   MCW_strncpy( pfx , DSET_PREFIX(dset) , THD_MAX_PREFIX ) ;

   if( PREFIX_IS_NIFTI(pfx) ){
     lp = THD_deconflict_nifti( pfx ) ;
     if( lp > 0 ) EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
     RETURN(lp) ;
   }

   if( ! THD_is_file(dset->dblk->diskptr->header_name) ) RETURN(0) ;

   lp = strlen(pfx) ;
   if( lp > THD_MAX_PREFIX-5 ) lp = THD_MAX_PREFIX-5 ;

   for( aa='A' ; aa <= 'Z' ; aa++ ){
    for( bb='A' ; bb <= 'Z' ; bb++ ){
     for( cc='1' ; cc <= '9' ; cc++ ){
       pfx[lp  ] = '_' ;
       pfx[lp+1] = aa  ;
       pfx[lp+2] = bb  ;
       pfx[lp+3] = cc  ;
       pfx[lp+4] = '\0';
       EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
       if( ! THD_is_file(dset->dblk->diskptr->header_name) ) RETURN(1) ;
   }}}

   /** ugly brute force final solution: should never happen! **/

   if( lp > THD_MAX_PREFIX-35 ) lp = THD_MAX_PREFIX-35 ;
   pfx[lp++] = '_' ; UNIQ_idcode_fill( pfx+lp ) ;
   EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
   RETURN(1) ;
}

/*--------------------------------------------------------------------*/

char * THD_dataset_headname( char *sname , char *pname , int vt )
{
   THD_3dim_dataset *dset ;
   char *str ; int ll ;

ENTRY("THD_dataset_headname") ;

   if( pname == NULL ) RETURN(NULL) ;

   dset = EDIT_empty_copy(NULL) ;
   EDIT_dset_items( dset , ADN_prefix , pname , ADN_none ) ;

   if( sname != NULL )
      EDIT_dset_items( dset , ADN_directory_name , sname , ADN_none ) ;

   if( vt >= FIRST_VIEW_TYPE && vt <= LAST_VIEW_TYPE )
      EDIT_dset_items( dset , ADN_view_type , vt , ADN_none ) ;

   ll = strlen(dset->dblk->diskptr->header_name) + 1 ;
   str = (char *) malloc(sizeof(char)*ll ) ;
   strcpy( str , dset->dblk->diskptr->header_name ) ;

   THD_delete_3dim_dataset( dset , False ) ;
   RETURN(str) ;
}


/* ------------------------------------------------------------- */
/* given a filename, return one STORAGE_BY_* value from 3ddata.h
 *                                           20 Apr 2006 [rickr] */
int storage_mode_from_filename( char * fname )

{
ENTRY("storage_mode_from_filename");

    if( !fname || !*fname )                     RETURN(STORAGE_UNDEFINED);

    /* STORAGE_BY_SLICES was never implemented   :'( */

    if( STRING_HAS_SUFFIX(fname, ".HEAD") ||
        STRING_HAS_SUFFIX(fname, ".BRIK") ||
        STRING_HAS_SUFFIX(fname, ".BRIK.gz") )  RETURN(STORAGE_BY_BRICK);

    if( STRING_HAS_SUFFIX(fname, ".mnc") )      RETURN(STORAGE_BY_MINC);

    if( 0 )                                     RETURN(STORAGE_BY_VOLUMES);

    if( 0 )   /* default is NIFTI */            RETURN(STORAGE_BY_ANALYZE);

    if( STRING_HAS_SUFFIX(fname, ".mri") )      RETURN(STORAGE_BY_CTFMRI);

    if( STRING_HAS_SUFFIX(fname, ".svl") )      RETURN(STORAGE_BY_CTFSAM);

    if( STRING_HAS_SUFFIX(fname, ".1D") )       RETURN(STORAGE_BY_1D);

    if( STRING_HAS_SUFFIX(fname, ".3D") )       RETURN(STORAGE_BY_3D);

    if( STRING_HAS_SUFFIX(fname, ".nii")    ||
        STRING_HAS_SUFFIX(fname, ".nii.gz") ||
        STRING_HAS_SUFFIX(fname, ".nia")    ||
        STRING_HAS_SUFFIX(fname, ".hdr")    ||
        STRING_HAS_SUFFIX(fname, ".img") )      RETURN(STORAGE_BY_NIFTI);

    if( STRING_HAS_SUFFIX_CASE(fname,".mpg") ||
        STRING_HAS_SUFFIX_CASE(fname,".mpeg")  )RETURN(STORAGE_BY_MPEG);

    /* 26 May 2006 [rickr] */
    if( STRING_HAS_SUFFIX(fname, ".niml") )     RETURN(STORAGE_BY_NIML);

    if( STRING_HAS_SUFFIX(fname,".niml.dset") ) RETURN(STORAGE_BY_NI_SURF_DSET);

    RETURN(STORAGE_UNDEFINED);
}


/* ---------------------------------------------------- */
/* given a filename, return a pointer to the extension
 * (from file_extension_list)
 *                                  28 Jun 2006 [rickr] */

char * find_filename_extension( char * fname )
{
    char ** eptr;
    int c, flen, num_ext;

ENTRY("find_filename_extension");

    if( !fname || !*fname ) RETURN(NULL);

    num_ext = sizeof(file_extension_list)/sizeof(char *);
    flen = strlen(fname);

    for( c = 0, eptr = file_extension_list; c < num_ext; c++, eptr++ )
        if( STRING_HAS_SUFFIX(fname, *eptr) )
            RETURN(fname + (flen - strlen(*eptr)));

    RETURN(NULL);   /* not found */
}


/* ------------------------------------------------------------- */
/* given a filename, return 1 if it has a know extension that is
 * not an AFNI extension                     20 Apr 2006 [rickr] */

int has_known_non_afni_extension( char * fname )
{
    int mode;

ENTRY("has_known_non_afni_extension");

    mode = storage_mode_from_filename(fname);

    /* UNDEFINED, BRICK and VOLUMES are the unknown or AFNI cases */
    if( mode <= STORAGE_UNDEFINED   ||
        mode == STORAGE_BY_BRICK    ||
        mode == STORAGE_BY_VOLUMES  ||
        mode  > LAST_STORAGE_MODE ) RETURN(0);

    RETURN(1); /* otherwise, we recognize it as non-AFNI */
}


syntax highlighted by Code2HTML, v. 0.9.1