// ---------------------------------------------------------------------------
// - SioCalls.cpp                                                            -
// - afnix:sio module - file system path functions implementation            -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - 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.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2006 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Cons.hpp"
#include "Vector.hpp"
#include "System.hpp"
#include "SioCalls.hpp"
#include "Exception.hpp"

namespace afnix {

  // remove a directory by names

  Object* sio_rmdir (Runnable* robj, Nameset* nset, Cons* args) {
    // evaluate the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    try {
      for (long i = 0; i < argc; i++) {
	System::rmdir (argv->getstring (i));
      }
      delete argv;
      return nilp;
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // remove a file by names

  Object* sio_rmfile (Runnable* robj, Nameset* nset, Cons* args) {
    // evaluate the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    try {
      for (long i = 0; i < argc; i++) {
	System::rmfile (argv->getstring (i));
      }
      delete argv;
      return nilp;
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // create a temporary name

  Object* sio_tmp_name (Runnable* robj, Nameset* nset, Cons* args) {
    // evaluate the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    try {
      if (argc == 0) {
	delete argv;
	return new String (System::tempnam ());
      }
      if (argc == 1) {
	String prefix = argv->getstring (0);
	delete argv;
	return new String (System::tempnam (prefix));
      }
      throw Exception ("argument-error", "too many arguments with tmp-name");
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // create a temporary path

  Object* sio_tmp_path (Runnable* robj, Nameset* nset, Cons* args) {
    // evaluate the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    try {
      if (argc == 0) {
	delete argv;
	return new String (System::temppth ());
      }
      if (argc == 1) {
	String prefix = argv->getstring (0);
	delete argv;
	return new String (System::temppth (prefix));
      }
      throw Exception ("argument-error", "too many arguments with tmp-path");
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // create an absolute path name

  Object* sio_abs_path (Runnable* robj, Nameset* nset, Cons* args) {
    // evaluate the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    try {
      // root directory first
      if (argc == 0) {
	delete argv;
	return new String (System::rootdir ());
      }
      // first argument build root
      String result = System::rootdir ();
      result = result + argv->getstring (0);
      if (argc == 1) {
	delete argv;
	return new String (result);
      }
      // loop with the rest
      for (long i = 1; i < argc; i++)
	result = System::join (result, argv->getstring (i));
      delete argv;
      return new String (result);
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // create a relative path name

  Object* sio_rel_path (Runnable* robj, Nameset* nset, Cons* args) {
    // evaluate the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    try {
      // check for at least one argument
      if (argc == 0) {
	throw Exception ("argument-error", 
			 "missing arguments with absolute-path");
      }
      // first argument starts the path
      String result = argv->getstring (0);
      // loop with the rest
      for (long i = 1; i < argc; i++)
	result = System::join (result, argv->getstring (i));
      delete argv;
      return new String (result);
    } catch (...) {
      delete argv;
      throw;
    }
  }
}
