# Base class for all objects in the PS code. This provides all common routines for all classes that are created.
# Basic new() constructor should be sufficient for all classes. When its called it will involke the CLASS->init method to
# allow for more initialization from the actual object being created.
#
# A program should never create more then _1_ instance of the PS class (PS is a singleton)
# 
package PS::Base;

require 5.006_000;

use strict;
use Carp;
use Data::Dumper;

our ($VERSION, $DEBUG, $firstobj, $PS);

$VERSION 	= 1.00;
$DEBUG		= 0;

$firstobj	= 1;
$PS		= undef;

# ----------------------------------------------------------------------------------------------------------------------------
# All sub-classes should rely on this new method to create the object and use the 'init' method to allow for initialization
sub new {
  my $class = shift;
  my $args = (ref($_[0]) eq 'HASH') ? $_[0] : { @_ };
  my $self = {
	classname	=> $class,
	createtime	=> time(),
  };

  $DEBUG = $args->{DEBUG} if exists $args->{DEBUG};
  print "DEBUG >> Creating $class ... \n" if $DEBUG;

  bless($self, $class);

  if ($firstobj) {
    $firstobj = 0;
    $PS = $self;			# save reference to primary object (first obj is considered the primary)
  } else {
    $self->{ps} = $PS;			# all other objects created will have a reference to the primary for convienence
  }

  return $self->can('init') ? $self->init($args) : $self;
}
# ----------------------------------------------------------------------------------------------------------------------------
# Sub-classes will want to inherit this method to initialize themselves. The init method should ALWAYS return the 
# reference to its class
sub init { $_[0] }	# return self
# ----------------------------------------------------------------------------------------------------------------------------
# returns an 'object' from the class. This is mainly intended to pass around objects that some internal classes create 
# themselves, but it can be used to fetch the value of any class variable as well (which basically breaks 'encapsulation')
sub getobj {
  my ($self, $o) = @_;
  return exists $self->{$o} ? $self->{$o} : undef;
}
# ----------------------------------------------------------------------------------------------------------------------------
sub DEBUG {
  my ($self, $val) = @_;
  my $old = $DEBUG;
  $DEBUG = $val if defined $val;
  return $old;
}
# ----------------------------------------------------------------------------------------------------------------------------
# internal method to die on functions that have not been inherited and are supposed to be.
sub _notdefined { 
  die("FATAL error in class '" . $_[0]->{classname} . "'" .
	". Required method '" . 
	(split('::',$_[1]))[-1] . "'" .
	" has not been defined. It was called in " .
	(caller(1))[1] . 
	" at line " . 
	(caller(1))[2] . 
	"\n"
  );
}
# ----------------------------------------------------------------------------------------------------------------------------



1;

