/*  Tux Commander VFS: basic tree_path routines
 *  Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net>
 *   Check for updates on tuxcmd.sourceforge.net
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <stdio.h>
#include <string.h>
#include <glib.h>

#include "vfs_types.h"
#include "strutils.h"
#include "vfsutils.h"
#include "treepathutils.h"
#include "treepath_vfs.h"






struct VfsFilelistData* vfs_filelist_new(struct PathTree *files)
{
  struct VfsFilelistData *data= (struct VfsFilelistData*)malloc(sizeof(struct VfsFilelistData));
  memset(data, 0, sizeof(struct VfsFilelistData));

  log("vfs_filelist_new()\n");
  data->files = files;

  return data;
}


void vfs_filelist_free(struct VfsFilelistData *data)
{
  if (! data) {
	  fprintf(stderr, "vfs_filelist_free: data == NULL !\n");
	  return;
  }
  if (data)
  {
	  free(data);
  }
}

void vfs_filelist_set_files(struct VfsFilelistData *data, struct PathTree *files)
{
  if (data) data->files = files;
}





u_int64_t internal_get_dir_size(struct VfsFilelistData *data, struct PathTree *tree)
{
  if (data->break_get_dir_size) return 0;
  u_int64_t Size = 0;
  if (tree) {
	  struct PathTree *n = NULL;
	  unsigned long idx = 0;
	  while ((n = filelist_tree_get_item_by_index(tree, idx))) {
		  if (data->break_get_dir_size) break;
		  if (n->data) {
			  log("internal_get_dir_size: found item '%s', size = %zd \n", n->node, n->data->iSize);
			  Size += (n->data->ItemType == vDirectory) ? internal_get_dir_size(data, n) : n->data->iSize;
		  }
		  idx++;
	  }
  }
  return Size;
}

u_int64_t vfs_filelist_get_dir_size(struct VfsFilelistData *data, char *APath)
{
  if (! data) return 0;
  data->break_get_dir_size = FALSE;

  struct PathTree* node = filelist_tree_find_node_by_path(data->files, APath);
  if (node) {
	  return internal_get_dir_size(data, node);
  } else {
	  printf("(EE) VFSGetDirSize: path '%s' not found\n", APath);
	  return 0;
  }
}

void vfs_filelist_get_dir_size_break(struct VfsFilelistData *data)
{
  if (data) data->break_get_dir_size = TRUE;
}






long vfs_filelist_file_exists(struct VfsFilelistData *data, const char *FileName, const long Use_lstat)
{
  if ((data) && (data->files)) {
	  struct PathTree* node = filelist_tree_find_node_by_path(data->files, FileName);
	  return node != NULL;
  } else {
	  printf ("(EE) VFSFileExists: Invalid pointers to data objects.\n");
	  return FALSE;
  }
}


TVFSResult vfs_filelist_file_info(struct VfsFilelistData *data, char *AFileName, struct TVFSItem *Item)
{
  if ((data) && (data->files)) {
	  struct PathTree* node = filelist_tree_find_node_by_path(data->files, AFileName);
	  if (node) {
		  if (node->data) {
			  copy_vfs_item(node->data, Item);
			  Item->FName = strdup(AFileName);
			  Item->FDisplayName = strdup(AFileName);
			  printf("(II) VFSFileInfo: found file: '%s'\n", Item->FName);
			  return cVFS_OK;
		  } else {
			  printf("(EE) VFSFileInfo: node->data == NULL! \n");
			  return cVFS_Failed;
		  }
	  } else {
		  printf("(EE) VFSFileInfo: file specified not found\n");
		  return cVFS_No_More_Files;
	  }
  } else {
	  printf ("(EE) VFSFileInfo: Invalid pointers to data objects.\n");
	  return cVFS_Failed;
  }
}






TVFSResult vfs_filelist_list_first(struct VfsFilelistData *data, char *sDir, struct TVFSItem *Item)
{
  data->list_dir_index = -1;
  data->list_dir_node = NULL;

  if (sDir == NULL) {
    printf("(EE) VFSListFirst: sDir is NULL!\n");
    return cVFS_Failed;
  }

  data->list_dir_index = 0;
  data->list_dir_node = filelist_tree_find_node_by_path(data->files, sDir);

  //  Find the directory in the filelist
  if (data->list_dir_node) {
	  struct PathTree* node = filelist_tree_get_item_by_index(data->list_dir_node, data->list_dir_index);
	  if (node) {
		  copy_vfs_item(node->data, Item);
		  printf("(II) VFSListFirst: found file: %s\n", Item->FName);
		  return cVFS_OK;
	  } else {
		  printf("(II) VFSListFirst: no more files\n");
		  return cVFS_No_More_Files;
	  }
  } else {
	  printf ("(EE) VFSListFirst: Directory '%s' not found.\n", sDir);
	  return cVFS_Failed;
  }
}

TVFSResult vfs_filelist_list_next(struct VfsFilelistData *data, char *sDir, struct TVFSItem *Item)
{
  if (! data->list_dir_node) {
	  printf("(EE) VFSListNext: data->list_dir_node is NULL!\n");
	  return cVFS_Failed;
  }
  data->list_dir_index++;

  struct PathTree* node = filelist_tree_get_item_by_index(data->list_dir_node, data->list_dir_index);
  if (node) {
	  copy_vfs_item(node->data, Item);
	  printf("(II) VFSListNext: found file: %s\n", Item->FName);
	  return cVFS_OK;
  } else {
	  printf("(II) VFSListNext: no more files\n");
	  return cVFS_No_More_Files;
  }
}

TVFSResult vfs_filelist_list_close(struct VfsFilelistData *data)
{
  data->list_dir_index = -1;
  data->list_dir_node = NULL;
  return cVFS_OK;
}


char* vfs_filelist_change_dir(struct VfsFilelistData *data, char *NewPath)
{
  if (NewPath == NULL) {
    printf("(EE) VFSChangeDir: NewPath is NULL!\n");
    return NULL;
  }

  //  Make up the target path
  printf ("(--) VFSChangeDir: Going to change dir from '%s'\n", NewPath);
  char *ANewPath = exclude_trailing_path_sep(NewPath);
  if (strlen(ANewPath) <= 0) ANewPath = strdup("/");
  printf ("(--) VFSChangeDir: Going to change dir to   '%s'\n", ANewPath);

  //  Find the directory in the filelist
  if (filelist_tree_find_node_by_path(data->files, ANewPath)) {
	  return ANewPath;
  } else {
	  printf ("(EE) VFSChangeDir: Directory '%s' not found.\n", ANewPath);
	  free(ANewPath);
	  return NULL;
  }
}
