// ---------------------------------------------------------------------------
// - AxsCalls.cpp                                                            -
// - afnix cross spreadsheet - command calls 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-2008 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Axs.hpp"
#include "Integer.hpp"
#include "AxsCalls.hpp"
#include "OutputFile.hpp"

namespace afnix {

  // create a new folio

  Object* axs_new (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 0 argument
    if (argc == 0) {
      Folio* result = axs->newf ();
      robj->post (result);
      delete argv;
      return result;
    }
    // check for 1 argument
    if (argc == 1) {
      String name   = argv->getstring (0);
      Folio* result = axs->newf (name);
      robj->post (result);
      delete argv;
      return result;
    }
    // check for 2 arguments
    if (argc == 2) {
      String name   = argv->getstring (0);
      String info   = argv->getstring (1);
      Folio* result = axs->newf (name, info);
      robj->post (result);
      delete argv;
      return result;
    }
    delete argv;
    throw Exception ("axs-error", "invalid new arguments");
  }

  // open a folio file

  Object* axs_open (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 1 argument
    if (argc == 1) {
      String fname = argv->getstring (0);
      Folio* result = axs->open (fname);
      robj->post (result);
      delete argv;
      return result;
    }
    delete argv;
    throw Exception ("axs-error", "invalid open arguments");
  }

  // save a folio in a file

  Object* axs_save (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 1 argument
    if (argc == 1) {
      String fname = argv->getstring (0);
      axs->save (fname);
      delete argv;
      return nilp;
    }
    delete argv;
    throw Exception ("axs-error", "invalid save arguments");
  }

  // print some folio info

  Object* axs_info (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 0 argument
    if (argc == 0) {
      axs->info (robj->getos ());
      delete argv;
      return nilp;
    }
    // check for one argument
    if (argc == 1) {
      Object* obj = argv->get (0);
      Output* os  = dynamic_cast <Output*> (obj);
      if (os == nilp) 
	throw Exception ("type-error", "invalid output stream object",
			 Object::repr (obj));
      try {
	axs->info (os);
	delete argv;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with info");
  }

  // sort the default sheet

  Object* axs_sort (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // sort the sheet
    try {
      // check for 0 argument
      if (argc == 0) {
	axs->sort (0, true);
	delete argv;
	return nilp;
      }
      // check for 1 argument
      if (argc == 1) {
	long col = argv->getint (0);
	axs->sort (col, true);
	delete argv;
	return nilp;
      } 
      // check for 2 arguments
      if (argc == 2) {
	long col  = argv->getint  (0);
	long mode = argv->getbool (1);
	axs->sort (col, mode);
	delete argv;
	return nilp;
      }
      throw Exception ("argument-error", "too many arguments with sort");
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // print the folio contents

  Object* axs_flist (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 0 argument
    if (argc == 0) {
      axs->flist (robj->getos ());
      delete argv;
      return nilp;
    }
    // check for one argument
    if (argc == 1) {
      Object* obj = argv->get (0);
      Output* os  = dynamic_cast <Output*> (obj);
      if (os == nilp) 
	throw Exception ("type-error", "invalid output stream object",
			 Object::repr (obj));
      try {
	axs->flist (os);
	delete argv;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with sheet info");
  }

  // create a new sheet - by name eventually - make it the default

  Object* axs_create (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 0 argument
    if (argc == 0) {
      try {
	Sheet* sht = axs->create ();
	delete argv;
	robj->post (sht);
	return sht;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    // check for one argument
    if (argc == 1) {
      try {
	String name = argv->getstring (0);
	Sheet* sht = axs->create ();
	sht->setname (name);
	robj->post (sht);
	delete argv;
	return sht;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    // check for two argument
    if (argc == 2) {
      try {
	String name = argv->getstring (0);
	String info = argv->getstring (1);
	Sheet* sht = axs->create ();
	sht->setname (name);
	sht->setinfo (info);
	robj->post (sht);
	delete argv;
	return sht;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with create");
  }

  // import data into the sheet

  Object* axs_import (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for one argument
    if (argc == 1) {
      try {
	String fname = argv->getstring (0);
	axs->import (fname);
	delete argv;
	return nilp;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with import");
  }

  // export a sheet into a file

  Object* axs_export (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long argc = (argv == nilp) ? 0 : argv->length ();
    // check for at lest one argument
    if (argc == 0) 
      throw Exception ("argument-error", "missing export file name");
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for one argument
    if (argc == 1) {
      try {
	String fname = argv->getstring (0);
	OutputFile os (fname);
	axs->view (&os, 0, 0, false);
	delete argv;
	return nilp;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with export");
  }

  // select a sheet by index or tag and make it the default one

  Object* axs_select (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for 0 argument
    if (argc == 0) {
      try {
	Sheet* sht = axs->select (0);
	delete argv;
	robj->post (sht);
	return sht;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    // check for one argument
    if (argc == 1) {
      try {
	Object* obj = argv->get (0);
	// check for an integer
	Integer* iobj = dynamic_cast <Integer*> (obj);
	if (iobj != nilp) {
	  long index = iobj->tointeger ();
	  Sheet* sht = axs->select (index);
	  delete argv;
	  robj->post (sht);
	  return sht;
	}
	// check for a string
	String* sobj = dynamic_cast <String*> (obj);
	if (sobj != nilp) {
	  Sheet* sht = axs->select (*sobj);
	  delete argv;
	  robj->post (sht);
	  return sht;
	}
	// invalid object
	throw Exception ("argument-error", "invalid object for select",
			 Object::repr (obj));
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with select");
  }

  // add a tag to the current sheet

  Object* axs_addtag (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // check for one argument
    if (argc == 1) {
      try {
	String tag = argv->getstring (0);
	axs->addtag (tag);
	delete argv;
	return nilp;
      } catch (...) {
	delete argv;
	throw;
      }
    }
    delete argv;
    throw Exception ("argument-error", "too many arguments with add-tag");
  }

  // add element marker to the current sheet

  Object* axs_addmark (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // try to add the element
    try {
      axs->addmark (argv);
      delete argv;
      return nilp;
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // add elements header to the current sheet

  Object* axs_addhead (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // try to add the element
    try {
      axs->addhead (argv);
      delete argv;
      return nilp;
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // add elements footer to the current sheet

  Object* axs_addfoot (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // try to add the element
    try {
      axs->addfoot (argv);
      delete argv;
      return nilp;
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // insert elements to the current sheet

  Object* axs_insert (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // try to add the element
    try {
      axs->insert (argv);
      delete argv;
      return nilp;
    } catch (...) {
      delete argv;
      throw;
    }
  }

  // print a report of the current sheet

  Object* axs_view (Runnable* robj, Nameset* nset, Cons* args) {
    // get the arguments
    Vector* argv = Vector::eval (robj, nset, args);
    long    argc = (argv == nilp) ? 0 : argv->length ();
    // get the command object
    Axs* axs = dynamic_cast <Axs*> (robj);
    // format the sheet
    try {
      // check for 0 argument
      if (argc == 0) {
	axs->view (axs->getos (), 0, 0, true);
	delete argv;
	return nilp;
      }
      // check for 1 argument
      if (argc == 1) {
	long max = argv->getint (0);
	axs->view (axs->getos (), max, 0, true);
	delete argv;
	return nilp;
      } 
      // check for 2 arguments
      if (argc == 2) {
	long max   = argv->getint (0);
	long start = argv->getint (1);
	axs->view (axs->getos (), max, start, true);
	delete argv;
	return nilp;
      }
      throw Exception ("argument-error", 
		       "too many arguments with sheet-report");
    } catch (...) {
      delete argv;
      throw;
    }
  }
}
