// ---------------------------------------------------------------------------
// - Predsec.cpp                                                             -
// - afnix:sec module - 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 "Dsa.hpp"
#include "Des.hpp"
#include "Aes.hpp"
#include "Rc2.hpp"
#include "Rc4.hpp"
#include "Rc5.hpp"
#include "Rsa.hpp"
#include "Md2.hpp"
#include "Md4.hpp"
#include "Md5.hpp"
#include "Sha1.hpp"
#include "Kdf1.hpp"
#include "Kdf2.hpp"
#include "Hmac.hpp"
#include "Cons.hpp"
#include "Crypto.hpp"
#include "Sha224.hpp"
#include "Sha256.hpp"
#include "Sha384.hpp"
#include "Sha512.hpp"
#include "Hasher.hpp"
#include "Keyring.hpp"
#include "Predsec.hpp"
#include "Boolean.hpp"
#include "Signature.hpp"
#include "Exception.hpp"
#include "InputCipher.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);
  }

  // hashp: hasher object predicate

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

  // keyp: key object predicate

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

  // sgnp: signature object predicate

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

  // dsap: dsa object predicate

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

  // md2p: MD-2 object predicate

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

  // md4p: MD-4 object predicate

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

  // md5p: MD-5 object predicate

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

  // sha1p: SHA-1 object predicate

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

  // sha224p: SHA-224 object predicate

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

  // sha256p: SHA-256 object predicate

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

  // sha384p: SHA-384 object predicate

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

  // sha512p: SHA-512 object predicate

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

  // kdfp: kdf object predicate

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

  // hkdfp: hashed kdf object predicate

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

  // kdf1p: kdf1 object predicate

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

  // kdf2p: kdf2 object predicate

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

  // macp: mac object predicate

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

  // hmacp: mac object predicate

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

  // desp: des object predicate

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

  // aesp: aes object predicate

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

  // rc2p: rc2 object predicate

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

  // rc4p: rc4 object predicate

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

  // rc5p: rc5 object predicate

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

  // rsap: rsa object predicate

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

  // cifrp: cipher object predicate

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

  // bcfrp: block cipher object predicate

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

  // p;cfrp: public cipher object predicate

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

  // icfrp: input cipher object predicate

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

  // cptop: generic crypto object predicate

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

   // krng: keyring  object predicate

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