// ---------------------------------------------------------------------------
// - Predgeo.cpp                                                             -
// - afnix:geo service - predicates 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-2019 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Cons.hpp"
#include "Plane.hpp"
#include "Pixmap.hpp"
#include "Mixmap.hpp"
#include "Cuboid.hpp"
#include "Boolean.hpp"
#include "Predgeo.hpp"
#include "Vector1.hpp"
#include "Vector2.hpp"
#include "Vector3.hpp"
#include "Vector4.hpp"
#include "Exception.hpp"
#include "Quaternion.hpp"

namespace afnix {

  // this procedure checks that we have one argument only and returns
  // the evaluated object
  static inline Object* get_obj (Runnable* robj, Nameset* nset, Cons* args,
                                 const String& pname) {
    Object* car = nullptr;
    if ((args == nullptr) || (args->length () != 1))
      throw Exception ("argument-error", "illegal arguments with predicate",
                       pname);
    car = args->getcar ();
    return (car == nullptr) ? nullptr : car->eval (robj,nset);
  }

  // pnt1p: point1 object predicate

  Object* geo_pnt1p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "point1-p");
    bool result = (dynamic_cast <Point1*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // pnt2p: point2 object predicate

  Object* geo_pnt2p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "point2-p");
    bool result = (dynamic_cast <Point2*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // pnt3p: point3 object predicate

  Object* geo_pnt3p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "point3-p");
    bool result = (dynamic_cast <Point3*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // pnt4p: point4 object predicate

  Object* geo_pnt4p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "point4-p");
    bool result = (dynamic_cast <Point4*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // vec1p: vector1 object predicate

  Object* geo_vec1p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "vector1-p");
    bool result = (dynamic_cast <Vector1*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // vec2p: vector2 object predicate

  Object* geo_vec2p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "vector2-p");
    bool result = (dynamic_cast <Vector2*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // vec3p: vector3 object predicate

  Object* geo_vec3p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "vector3-p");
    bool result = (dynamic_cast <Vector3*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // vec4p: vector4 object predicate

  Object* geo_vec4p (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "vector4-p");
    bool result = (dynamic_cast <Vector4*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // qtrnp: quternion object predicate

  Object* geo_qtrnp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "quaternion-p");
    bool result = (dynamic_cast <Quaternion*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // sldp: solid object predicate

  Object* geo_sldp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "solid-p");
    bool result = (dynamic_cast <Solid*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // cubp: cuboid object predicate
  
  Object* geo_cubp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "cuboid-p");
    bool result = (dynamic_cast <Cuboid*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // plnp: plane object predicate
  
  Object* geo_plnp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "plane-p");
    bool result = (dynamic_cast <Plane*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // pixp: pixel object predicate
  
  Object* geo_pixp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "pixel-p");
    bool result = (dynamic_cast <Pixel*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // imgp: image object predicate
  
  Object* geo_imgp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "image-p");
    bool result = (dynamic_cast <Image*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // slcp: slice object predicate
  
  Object* geo_slcp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "slice-p");
    bool result = (dynamic_cast <Slice*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // pxmp: pixmap object predicate
  
  Object* geo_pxmp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "pixmap-p");
    bool result = (dynamic_cast <Pixmap*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // wdgp: wedge object predicate
  
  Object* geo_wdgp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "wedge-p");
    bool result = (dynamic_cast <Wedge*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // mxmp: mixmap object predicate
  
  Object* geo_mxmp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "mixmap-p");
    bool result = (dynamic_cast <Mixmap*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
}
