// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
// 
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
// 
// 1. Redistributions of source code must retain the above copyright notice, this list of
//    conditions and the following disclaimer.
// 
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
//    of conditions and the following disclaimer in the documentation and/or other
//    materials provided with the distribution.
// 
// 3. Neither the name of the copyright holder nor the names of its contributors may be
//    used to endorse or promote products derived from this software without specific
//    prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "rctTypes.h"
using namespace crypto;
using namespace std;

namespace rct {

    //dp 
	//Debug printing for the above types
	//Actually use DP(value) and #define DBG    
    
	void dp(key a) {
		int j = 0;
		printf("\"");
		for (j = 0; j < 32; j++) {
			printf("%02x", (unsigned char)a.bytes[j]);
		}
		printf("\"");
		printf("\n");
	}

	void dp(bool a) {
		printf(" ... %s ... ", a ? "true" : "false");
		printf("\n");
	}

	void dp(char * a, int l) {
		int j = 0;
		printf("\"");
		for (j = 0; j < l; j++) {
			printf("%02x", (unsigned char)a[j]);
		}
		printf("\"");
		printf("\n");
	}
	void dp(keyV a) {
		int j = 0;
		printf("[");
		for (j = 0; j < a.size(); j++) {
			dp(a[j]);
			if (j < a.size() - 1) {
				printf(",");
			}
		}
		printf("]");
		printf("\n");
	}
	void dp(keyM a) {
		int j = 0;
		printf("[");
		for (j = 0; j < a.size(); j++) {
			dp(a[j]);
			if (j < a.size() - 1) {
				printf(",");
			}
		}
		printf("]");
		printf("\n");
	}
	void dp(xmr_amount vali) {
		printf("x: %"PRIu64"\n", vali);
		printf("\n");
	}

	void dp(int vali) {
		printf("x: %d\n", vali);
		printf("\n");
	}
	void dp(bits amountb) {
		int i = 0;
		for (int i = 0; i < 64; i++) {
			printf("%d", amountb[i]);
		}
		printf("\n");

	}

	void dp(char * st) {
		printf("%s\n", st);
	}

	//Various Conversions 
    
    //uint long long to 32 byte key
	void d2h(key & amounth, const xmr_amount in) {
		sc_0(amounth.bytes);
		xmr_amount val = in;
		int i = 0, byte = 0;
		while (val != 0) {
			amounth[i] = (unsigned char)(val & 0xFF);
			i++;
			val /= (xmr_amount)256;
		}
	}
    
    //uint long long to 32 byte key
	key d2h(const xmr_amount in) {
		key amounth;
		sc_0(amounth.bytes);
		xmr_amount val = in;
		int i = 0;
		while (val != 0) {
			amounth[i] = (unsigned char)(val & 0xFF);
			i++;
			val /= (xmr_amount)256;
		}
		return amounth;
	}

    //uint long long to int[64]
	void d2b(bits  amountb, xmr_amount val) {
		amountb;
		int i = 0;
		while (val != 0) {
			amountb[i] = val & 1;
			i++;
			val >>= 1;
		}
		while (i < 64) {
			amountb[i] = 0;
			i++;
		}
	}
    
	//32 byte key to uint long long
	// if the key holds a value > 2^64
	// then the value in the first 8 bytes is returned    
	xmr_amount h2d(const key & test) {
		xmr_amount vali = 0;
		int j = 0;
		for (j = 7; j >= 0; j--) {
			vali = (xmr_amount)(vali * 256 + (unsigned char)test[j]);
		}
		return vali;
	}
    
    //32 byte key to int[64]
	void h2b(bits amountb2, const key & test) {
		int val = 0, i = 0, j = 0;
		for (j = 0; j < 8; j++) {
			val = (unsigned char)test[j];
			i = 8 * j;
			while (val != 0) {
				amountb2[i] = val & 1;
				i++;
				val >>= 1;
			}
			while (i < 8 * (j + 1)) {
				amountb2[i] = 0;
			}
		}
	}
    
    //int[64] to 32 byte key
	void b2h(key & amountdh, const bits amountb2) {
		int byte, i, j;
		for (j = 0; j < 8; j++) {
			byte = 0;
			//val = (unsigned char) test[j];
			i = 8 * j;
			for (i = 7; i > -1; i--) {
				byte = byte * 2 + amountb2[8 * j + i];
			}
			amountdh[j] = (unsigned char)byte;
		}
		for (j = 8; j < 32; j++) {
			amountdh[j] = (unsigned char)(0x00);
		}
	}
    
    //int[64] to uint long long
	xmr_amount b2d(bits amountb) {
		xmr_amount vali = 0;
		int j = 0;
		for (j = 63; j >= 0; j--) {
			vali = (xmr_amount)(vali * 2 + amountb[j]);
		}
	}

}