/* --------------------------------------------------------------------------*/
/*                                                                           */
/* object for getting files names in a source tree structure

   Copyright (c) 2013 Santi Noreña <belfegor@gmail.com>

  

/* 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 3            */
/* of the License, or (at your option) any later version.                    */
/*                                                                           */
/* See file LICENSE for further informations on licensing terms.             */
/*                                                                           */
/* 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           */
/*                                                                           */
/* --------------------------------------------------------------------------*/

#include <m_pd.h>
#include <stdlib.h>
#include <glob.h>
#include <stdio.h>
#include <string.h>

/*------------------------------------------------------------------------------
 *  CLASS DEF
 */
static t_class *fileselector_class;

typedef struct _fileselector {
	t_object            x_obj;
	t_symbol*           x_pattern;
	int		        			x_folder;
  int		              x_file;
  int							    x_type;
	t_outlet            *x_out;
} t_fileselector;

/*------------------------------------------------------------------------------
 * IMPLEMENTATION                    
 */

static void fileselector_output(t_fileselector* x)
{
  if (strlen(x->x_pattern->s_name) < 6)
  {
    post("fileselector: Set path first");
	  return;
  }  
	if(x->x_type < 25) // Don't make anything
		{ 
			return;	  	
    }	
  char path[FILENAME_MAX] = "";
  glob_t glob_buffer;
  unsigned int i;	
  strncpy(path, x->x_pattern->s_name, FILENAME_MAX);
  if(sys_isabsolutepath(path)) {
		if((x->x_type > 24) && (x->x_type<50)) // Make the path video
		{ 
 			strncat(path,"/video/*",8);
			switch(glob(path, GLOB_TILDE, NULL, &glob_buffer))
			{
			  	case GLOB_NOSPACE: 
      	     	  		pd_error(x,"[fileselector] out of memory for \"%s\"",path); 
      		    		break;
				# ifdef GLOB_ABORTED
	       		case GLOB_ABORTED: 
			        	pd_error(x,"[fileselector] aborted \"%s\"",path); 
			        	break;
				# endif
				# ifdef GLOB_NOMATCH
			    case GLOB_NOMATCH: 
		   		    	pd_error(x,"[fileselector] nothing found for %s ",path); 
		   		    	break;
				# endif
			}
			i = x->x_folder;
			if (i < glob_buffer.gl_pathc)
			{
				strncpy(path, glob_buffer.gl_pathv[i],strnlen(glob_buffer.gl_pathv[i],FILENAME_MAX));				
				strncat(path, "/*", 2);
 			}
			else
			{
				post("fileselector: folder is greater than the number of folders");
				globfree(&glob_buffer);
				return;		
			}    
   	}		
		if((x->x_type > 49) && (x->x_type<75)) // Make the path image
		{ 
		  strncat(path,"/image/*",8);
  	  switch(glob(path, GLOB_TILDE, NULL, &glob_buffer))
			{
			  	case GLOB_NOSPACE: 
      		  		pd_error(x,"[fileselector] out of memory for \"%s\"",path); 
      	  	   		break;
				# ifdef GLOB_ABORTED
	    		case GLOB_ABORTED: 
			       	pd_error(x,"[fileselector] aborted \"%s\"",path); 
			       	break;
				# endif
				# ifdef GLOB_NOMATCH
				case GLOB_NOMATCH: 
		    	   	pd_error(x,"[fileselector] nothing found for %s ",path); 
		    	   	break;
				# endif
			}
			i = x->x_folder;
			if (i < glob_buffer.gl_pathc)
			{
				strncpy(path, glob_buffer.gl_pathv[i],strnlen(glob_buffer.gl_pathv[i],FILENAME_MAX));				
				strncat(path, "/*", 2);
      }
			else
			{
				post("fileselector: folder is greater than the number of folders");
        globfree(&glob_buffer);
				return;		
			}    
    }    
 	  if((x->x_type > 74) && (x->x_type<100)) // Make the fonts path
	  { 
		  strncat(path,"/fonts/*",8);
      switch(glob(path, GLOB_TILDE, NULL, &glob_buffer))
			{
			  	case GLOB_NOSPACE: 
     		  		pd_error(x,"[fileselector] out of memory for \"%s\"",path); 
   	  	   		break;
				# ifdef GLOB_ABORTED
	    		case GLOB_ABORTED: 
			       	pd_error(x,"[fileselector] aborted \"%s\"",path); 
			       	break;
				# endif
				# ifdef GLOB_NOMATCH
				case GLOB_NOMATCH: 
		    	   	pd_error(x,"[fileselector] nothing found for %s ",path); 
		    	   	break;
				# endif
			}
			i = x->x_folder;
			if (i < glob_buffer.gl_pathc)
			{
				strncpy(path, glob_buffer.gl_pathv[i],strnlen(glob_buffer.gl_pathv[i],FILENAME_MAX));				
				strncat(path, "/*", 2);
      }
			else
			{
				post("fileselector: folder is greater than the number of folders");
        globfree(&glob_buffer);
				return;		
			}    
    }    	  
	  if(x->x_type == 256) // Make the path sound
	  { 
 		  strncat(path,"/sound/*",8);
		  switch(glob(path, GLOB_TILDE, NULL, &glob_buffer))
		  {
	    	case GLOB_NOSPACE: 
   	  	pd_error(x,"[fileselector] out of memory for \"%s\"",path); 
   	  	break;
		  # ifdef GLOB_ABORTED
	 	  	case GLOB_ABORTED: 
	     	pd_error(x,"[fileselector] aborted \"%s\"",path); 
	     	break;
		  # endif
		  # ifdef GLOB_NOMATCH
		  	case GLOB_NOMATCH: 
       	pd_error(x,"[fileselector] nothing found for %s ",path); 
 	     	break;
		  # endif
		   }
     i = x->x_folder;
		 if (i < glob_buffer.gl_pathc)
		 {
		 	strncpy(path, glob_buffer.gl_pathv[i],strnlen(glob_buffer.gl_pathv[i],FILENAME_MAX));				
		 	strncat(path, "/*", 2);
		 }
		 else
		 {
		  	post("fileselector: folder is greater than the number of folders");
		  	globfree(&glob_buffer);
		  	return;		
		 }    
    }     
    if(x->x_type == 257) // Make the path to texts files
	  { 
 		   strncat(path,"/texts/*",8);	  
    } 		
    // Look for the file		
  	switch(glob(path, GLOB_TILDE, NULL,&glob_buffer))
   	{ 
   	  case GLOB_NOSPACE: 
     	  pd_error(x,"[fileselector] out of memory for \"%s\"",path); 
       	break;
   	 # ifdef GLOB_ABORTED
   	  case GLOB_ABORTED: 
        pd_error(x,"[fileselector] aborted \"%s\"",path); 
  	    break;
  	# endif
  	# ifdef GLOB_NOMATCH
      case GLOB_NOMATCH: 
      	pd_error(x,"[fileselector] nothing found for \"%s\"",path); 
        break;
  	# endif
  	}
  	i = x->x_file;				
  	if (i < glob_buffer.gl_pathc)
    {				
   	 outlet_symbol(x->x_out, gensym(glob_buffer.gl_pathv[i]));
    }				
  } 
	globfree( &(glob_buffer) );
}

static void fileselector_set(t_fileselector* x, t_symbol *s) 
{
  x->x_pattern = s;
}

static void fileselector_folder(t_fileselector* x, t_floatarg f)
{
  x->x_folder = f;
  return;
}

static void fileselector_file(t_fileselector* x, t_floatarg f)
{
  x->x_file = f;
  return;
}
 
static void fileselector_type(t_fileselector* x, t_floatarg f)
{
  x->x_type = f;
  return;
}

static void *fileselector_new() 
{
	t_fileselector *x = (t_fileselector *)pd_new(fileselector_class);
  x->x_out = outlet_new((t_object *)x, &s_symbol);
	x->x_folder = 0;
	x->x_file = 0;
	x->x_type = 0;	
	x->x_pattern = gensym("empty");
	return (x);
}

void fileselector_setup(void) 
{
	fileselector_class = class_new(gensym("fileselector"),(t_newmethod)fileselector_new,0,sizeof(t_fileselector),0,A_DEFSYMBOL,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT, 0); 
	/* add inlet datatype methods */
	class_addbang(fileselector_class,(t_method) fileselector_output);
	/* add inlet message methods */
	class_addmethod(fileselector_class,(t_method)fileselector_set,gensym("set"),A_DEFSYMBOL, 0);
	// add inlet folder
	class_addmethod(fileselector_class,(t_method)fileselector_folder,gensym("folder"),A_FLOAT, 0);
	// add inlet file
	class_addmethod(fileselector_class,(t_method)fileselector_file,gensym("file"),A_FLOAT, 0);
	// add inlet type
	class_addmethod(fileselector_class,(t_method)fileselector_type,gensym("type"),A_FLOAT, 0);
}

