#include "x17.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

#include "x17/sph_blake.h"
#include "x17/sph_bmw.h"
#include "x17/sph_groestl.h"
#include "x17/sph_jh.h"
#include "x17/sph_keccak.h"
#include "x17/sph_skein.h"
#include "x17/sph_luffa.h"
#include "x17/sph_cubehash.h"
#include "x17/sph_shavite.h"
#include "x17/sph_simd.h"
#include "x17/sph_echo.h"
#include "x17/sph_hamsi.h"
#include "x17/sph_fugue.h"
#include "x17/sph_shabal.h"
#include "x17/sph_whirlpool.h"
#include "x17/sph_sha2.h"
#include "x17/sph_haval.h"


void x17_hash(const char * input, const char * output)
{
    sph_blake512_context      ctx_blake;
    sph_bmw512_context        ctx_bmw;
    sph_groestl512_context    ctx_groestl;
    sph_jh512_context         ctx_jh;
    sph_keccak512_context     ctx_keccak;
    sph_skein512_context      ctx_skein;
    sph_luffa512_context      ctx_luffa;
    sph_cubehash512_context   ctx_cubehash;
    sph_shavite512_context    ctx_shavite;
    sph_simd512_context       ctx_simd;
    sph_echo512_context       ctx_echo;
    sph_hamsi512_context      ctx_hamsi;
    sph_fugue512_context      ctx_fugue;
    sph_shabal512_context     ctx_shabal;
    sph_whirlpool_context     ctx_whirlpool;
    sph_sha512_context        ctx_sha2;
    sph_haval256_5_context    ctx_haval;

    uint32_t hashA[16], hashB[16]; 

    sph_blake512_init(&ctx_blake);
    sph_blake512 (&ctx_blake, input, 80);
    sph_blake512_close (&ctx_blake, hashA);
    
    sph_bmw512_init(&ctx_bmw);
    sph_bmw512 (&ctx_bmw, hashA, 64);
    sph_bmw512_close(&ctx_bmw, hashB);

    sph_groestl512_init(&ctx_groestl);
    sph_groestl512 (&ctx_groestl, hashB, 64);
    sph_groestl512_close(&ctx_groestl, hashA);

    sph_skein512_init(&ctx_skein);
    sph_skein512 (&ctx_skein, hashA, 64);
    sph_skein512_close(&ctx_skein, hashB);
    
    sph_jh512_init(&ctx_jh);
    sph_jh512 (&ctx_jh, hashB, 64);
    sph_jh512_close(&ctx_jh, hashA);
    
    sph_keccak512_init(&ctx_keccak);
    sph_keccak512 (&ctx_keccak, hashA, 64);
    sph_keccak512_close(&ctx_keccak, hashB);

    sph_luffa512_init(&ctx_luffa);
    sph_luffa512 (&ctx_luffa, hashB, 64);
    sph_luffa512_close(&ctx_luffa, hashA);
    
    sph_cubehash512_init(&ctx_cubehash);
    sph_cubehash512 (&ctx_cubehash, hashA, 64);
    sph_cubehash512_close(&ctx_cubehash, hashB);
    
    sph_shavite512_init(&ctx_shavite);
    sph_shavite512(&ctx_shavite, hashB, 64);
    sph_shavite512_close(&ctx_shavite, hashA);
        
    sph_simd512_init(&ctx_simd);
    sph_simd512 (&ctx_simd, hashA, 64);
    sph_simd512_close(&ctx_simd, hashB);

    sph_echo512_init(&ctx_echo);
    sph_echo512 (&ctx_echo, hashB, 64);
    sph_echo512_close(&ctx_echo, hashA);

    sph_hamsi512_init(&ctx_hamsi);
    sph_hamsi512 (&ctx_hamsi, hashA, 64);
    sph_hamsi512_close(&ctx_hamsi, hashB);

    sph_fugue512_init(&ctx_fugue);
    sph_fugue512 (&ctx_fugue, hashB, 64);
    sph_fugue512_close(&ctx_fugue, hashA);

    sph_shabal512_init(&ctx_shabal);
    sph_shabal512 (&ctx_shabal, hashA, 64);
    sph_shabal512_close(&ctx_shabal, hashB);

    sph_whirlpool_init(&ctx_whirlpool);
    sph_whirlpool (&ctx_whirlpool, hashB, 64);
    sph_whirlpool_close(&ctx_whirlpool, hashA);

    sph_sha512_init(&ctx_sha2);
    sph_sha512 (&ctx_sha2, hashA, 64);
    sph_sha512_close(&ctx_sha2, hashB);

    sph_haval256_5_init(&ctx_haval);
    sph_haval256_5 (&ctx_haval, hashB, 64);
    sph_haval256_5_close(&ctx_haval, hashA);

    memcpy(output, hashA, 32);
}

