/*
  vehicle.c: C equivalent of:

  implementation class Vehicle;

  void method move(double T) {  // move in the current direction for T seconds
      dir.normalize unless dir.magnitude == 1;
      Vector2 delta = new Vector2( dir.x, dir.y );
      delta.scale( T * speed );
      pos.add( delta );
  }
  void method print() {         // display this vehicle
      printf( "Vehicle( " );
      printf( "%s: pos:%OBJ, dir:%OBJ", name, pos, dir );
      printf( ", speed:%g, people: %d (max:%d)", speed, people_cur, people_max );
      printf( " )" );
  }
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "vector2.h"
#include "vehicle.h"

// methods

static void move( Vehicle this, double t ) {
	if( OM0(this->dir,magnitude) != 1 )
	{
		OM0( this->dir, normalize);
	}
	Vector2 delta = new_Vector2( this->dir->x, this->dir->y );
	OM1( delta, scale, t * this->speed );
	OM1( this->pos, add, delta );
	OM0( delta, dispose );			// essential not to leak memory!
}

static void print( Vehicle this ) {
	printf( "vehicle( " );
	printf( "%s: pos:", this->name );
	OM0( this->pos, print );
	printf( ", dir:" );
	OM0( this->dir, print );
	printf( ", speed:%g, people: %d (max:%d)",
		this->speed, this->people_cur, this->people_max );
	printf( " )" );
}

static void dispose( Vehicle this ) {
	// should this dispose pos and dir?  not clear.  yes for now.
	if( this->pos != NULL ) OM0( this->pos, dispose );
	if( this->dir != NULL ) OM0( this->dir, dispose );
	free( this );
}

Vehicle alloc_Vehicle( void ) {
	Vehicle v = (Vehicle) malloc( sizeof(struct Vehicle) );
	assert( v != NULL );
	return v;
}

void init_Vehicle( Vehicle v, char * name, Vector2 pos, Vector2 dir, double speed, int people_cur, int people_max ) {
	v->isa        = "Vehicle";
	v->name       = name;
	v->pos        = pos == NULL ? new_Vector2(-1,-1) : pos;
	v->dir        = dir == NULL ? new_Vector2(-1,-1) : dir;
	v->speed      = speed==-1 ? 0 : speed;
	v->people_max = people_max==-1 ? 4 : people_max;
	v->people_cur = people_cur==-1 ? 1 : people_cur;
	v->move       = &move;
	v->print      = &print;
	v->dispose    = &dispose;
}

Vehicle new_Vehicle( char * name, Vector2 pos, Vector2 dir, double speed, int people_cur, int people_max ) {
	Vehicle v = alloc_Vehicle();
	init_Vehicle( v, name, pos, dir, speed, people_cur, people_max );
	return v;
}
