/*
 *    SCCS ID: %Z%%M% %I% %E% SST 
 *
 *    Copyright (c) 1992-1993 Mark Soloway.  All rights reserved.
 *    See SST_LEGAL_NOTICE file for terms of the license.
 */

#include "TTFile.h"
#include "TTObjectSpec.h"

#include <string.h>

TTObjectSpec::TTObjectSpec (const char *file,
			    const char *otype,
			    Tt_status  &status)
{
  setTTObjectSpecDefaults ();

  char *new_objid = tt_spec_create (file);
  status = tt_spec_type_set (new_objid, otype);

  if (status == TT_OK)
    objid = strcpy (new char [strlen (new_objid) + 1], new_objid);

  if (new_objid) tt_free (new_objid);
}

TTObjectSpec::TTObjectSpec (const TTFile &tt_file,
                            const char   *otype,
                            Tt_status    &status)
{
  setTTObjectSpecDefaults ();

  char *file = tt_file.getFile (status);
  if (status == TT_OK) {
    char *new_objid = tt_spec_create (file);
    status = tt_spec_type_set (new_objid, otype);

    if (status == TT_OK)
      objid = strcpy (new char [strlen (new_objid) + 1], new_objid);
  }

  if (file) tt_free (file);
}

TTObjectSpec::TTObjectSpec (const char *spec_objid, Tt_status &status)
{
  setTTObjectSpecDefaults ();

  if (spec_objid) {
    status = TT_OK;
    objid = strcpy (new char [strlen (spec_objid) + 1], spec_objid);
  }
  else {
    status = TT_ERR_OBJID;
  }
}

TTObjectSpec::TTObjectSpec (const TTObjectSpec &spec)
{
  copy (spec);
}

TTObjectSpec &TTObjectSpec::operator= (const TTObjectSpec &spec)
{
  if (this != &spec) {
    destroyObject ();
    copy (spec);
  }

  return *this;
}

void TTObjectSpec::setTTObjectSpecDefaults ()
{
  file = (char *)NULL;
  otype = (char *)NULL;
  objid = (char *)NULL;
}

TTObjectSpec::~TTObjectSpec ()
{
  destroyObject ();
}

int TTObjectSpec::operator== (const TTObjectSpec &spec) const
{
  int       result = 0;
  Tt_status status;

  char *spec_objid = spec.getID (status);
  if (status < TT_WRN_LAST) {
    result = tt_objid_equal (objid, spec_objid);
  }

  return result;
}

int TTObjectSpec::operator== (const char *spec_objid) const
{
  return tt_objid_equal (objid, spec_objid);
}
 
char *TTObjectSpec::getID (Tt_status &status) const
{
  status = TT_OK;
  return (objid ?
          strcpy (tt_malloc (strlen (objid) + 1), objid) :
	  (char *)NULL);
}

char *TTObjectSpec::getFile (Tt_status &status) const
{
  char *spec_file = tt_spec_file (objid);
  status = tt_ptr_error (spec_file);
  return spec_file;
}

char *TTObjectSpec::getOType (Tt_status &status) const
{
  char *spec_otype = tt_spec_type (objid);
  status = tt_ptr_error (spec_otype);
  return spec_otype;
}

char *TTObjectSpec::getObjectKey (Tt_status &status) const
{
  char *object_key = tt_objid_objkey (objid);
  status = tt_ptr_error (object_key);
  return object_key;
}

Tt_status TTObjectSpec::createAfterDestroy ()
{
  if (objid)
    return TT_ERR_OBJID;

  if (!file)
    return TT_ERR_FILE;
 
  if (!otype)
    return TT_ERR_OTYPE;
 
  Tt_status    status; 
  TTObjectSpec new_spec (file, otype, status); 
 
  if (status == TT_OK) { 
    destroyObject (); 
    copy (new_spec);
  }  
 
  return status; 
}

Tt_status TTObjectSpec::createAfterDestroy (const char *spec_file,
					    const char *spec_otype)
{
  if (objid)
    return TT_ERR_OBJID;

  if (!spec_file)
    return TT_ERR_FILE;

  if (!spec_otype)
    return TT_ERR_OTYPE;

  Tt_status    status;
  TTObjectSpec new_spec (spec_file, spec_otype, status);

  if (status == TT_OK) {
    destroyObject ();
    copy (new_spec);
  } 

  return status;
}

Tt_status TTObjectSpec::write ()
{
  return tt_spec_write (objid);
}

Tt_status TTObjectSpec::destroy ()
{
  Tt_status status;

  char *spec_file = tt_spec_file (objid);
  status = tt_ptr_error (spec_file);
  if ((status != TT_OK) && (status != TT_WRN_STALE_OBJID))
    return status;
  file = strcpy (new char [strlen (spec_file) + 1], spec_file);

  char *spec_otype = tt_spec_type (objid);
  status = tt_ptr_error (spec_otype);
  if ((status != TT_OK) && (status != TT_WRN_STALE_OBJID)) {
    if (file) {
      file = (char *)NULL;
      delete file;
    }

    return status;
  }
  otype = strcpy (new char [strlen (spec_otype) + 1], spec_otype);

  status = tt_spec_destroy (objid);
  if ((status != TT_OK) && (status != TT_WRN_STALE_OBJID)) {
    if (file) {
      file = (char *)NULL;
      delete file;
    }

    if (otype) {
      otype = (char *)NULL;
      delete otype;
    }

    return status;
  }

  if (objid)
    delete objid;
  objid = (char *)NULL;

  return status;
}

Tt_status TTObjectSpec::move (const char *new_file)
{
  char      *new_objid = tt_spec_move (objid, new_file);
  Tt_status  status = tt_ptr_error (new_objid);

  if ((status == TT_OK) || (status == TT_WRN_STALE_OBJID)) {
    if (objid)
      delete objid;

    objid = strcpy (new char [strlen (new_objid) + 1], new_objid);
  }

  return status;
}

Tt_status TTObjectSpec::move (const TTFile &new_file)
{
  Tt_status  status;
  char      *new_objid = tt_spec_move (objid, new_file.getFile (status));

  status = tt_ptr_error (new_objid);
  if ((status == TT_OK) || (status == TT_WRN_STALE_OBJID)) {
    if (objid)
      delete objid;

    objid = strcpy (new char [strlen (new_objid) + 1], new_objid);
  }

  return status;
}

int TTObjectSpec::getPropertyNameCount (Tt_status &status) const
{
  int count = tt_spec_propnames_count (objid);
  status = tt_int_error (count);
  return count;
}

char *TTObjectSpec::getPropertyName (int index, Tt_status &status) const
{
  char *name = tt_spec_propname (objid, index);
  status = tt_ptr_error (name);
  return name;
}

int TTObjectSpec::getPropertyCount (const char *name, Tt_status &status) const
{
  int count = tt_spec_prop_count (objid, name);
  status = tt_int_error (count);
  return count;
}

Tt_status TTObjectSpec::getProperty (const char *name,
				     int         index,
				     char*      &property) const
{
  property = tt_spec_prop (objid, name, index);
  return tt_ptr_error (property);
}

Tt_status TTObjectSpec::getProperty (const char     *name,
				     int             index,
				     unsigned char* &property,
				     int            &length) const
{
  return tt_spec_bprop (objid, name, index, &property, &length);
}

Tt_status TTObjectSpec::setProperty (const char *name, const char *property)
{
  return tt_spec_prop_set (objid, name, property);
}

Tt_status TTObjectSpec::setProperty (const char          *name,
				     const unsigned char *property,
				     int                  length)
{
  return tt_spec_bprop_set (objid, name, property, length);
}

Tt_status TTObjectSpec::addProperty (const char *name, const char *property)
{
  return tt_spec_prop_add (objid, name, property);
}

Tt_status TTObjectSpec::addProperty (const char          *name,
				     const unsigned char *property,
				     int                  length)
{
  return tt_spec_bprop_add (objid, name, property, length);
}

void TTObjectSpec::copy (const TTObjectSpec &spec)
{
  setTTObjectSpecDefaults ();

  Tt_status status;
  objid = spec.getID (status);
}

void TTObjectSpec::destroyObject ()
{
  if (file)
    delete file;

  if (otype)
    delete otype;

  if (objid)
    delete objid;
}
