


//require('bufferjs');
var crypto=require('crypto');


var Buffer = require("./buffer").Buffer;
console.log(typeof(Buffer));

exports.Buffer = Buffer;
exports.dump = hexdump;
exports.hexdump = hexdump;




Buffer.prototype.XOR = function(buf){
	var nn = new Buffer(this.length);
	var mi = buf.length;
	var fi = 0;
	var n = this.length;
	for(var i=0;i<n;i++){
		if(i>mi){
			fi = 0;
			}
			nn[i] = this[i] ^ (buf[fi]);
		fi ++;
	}
	return nn;
}
Buffer.prototype.AND = function(buf){
	var nn = new Buffer(this.length);
	var mi = buf.length;
	var fi = 0;
	var n = this.length;
	for(var i=0;i<n;i++){
		if(i>mi){
			fi = 0;
			}
			nn[i] = this[i] & (buf[fi]);
		fi ++;
	}
	return nn;
}
Buffer.prototype.OR = function(buf){
	var nn = new Buffer(this.length);
	var mi = buf.length;
	var fi = 0;
	var n = this.length;
	for(var i=0;i<n;i++){
		if(i>mi){
			fi = 0;
			}
			nn[i] = this[i] | (buf[fi]);
		fi ++;
	}
	return nn;
}

Buffer.prototype.clone = function(){
	var n = new Buffer(this.length);
		for(var i=0;i<this.length;i++){
			n[i] = this[i];
		}
	return n;
	}

Buffer.prototype.append = function(buf,baselength){
	var nlen = this.length + buf.length;
	if(baselength){
		nlen = 	Math.ceil( (nlen) / baselength) * baselength;
	}
	var tmp = new Buffer( nlen );
		tmp.fill(0);
	for(var i=0;i<this.length;i++){
		tmp[i]=this[i];
		}
	for(var i=0;i<buf.length;i++){
		tmp[this.length+i]=buf[i];
		}
 	return tmp;
}


var BASE = 
["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","_","=","/","!","#","$","%","&","'","(",")","*","+",",","-",".",":",";","<",">","@","[","]","^","`","{","|","}","~","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","®","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ"];

function getnum(num,base){
		var ss = ""
		while(num > 0){
			var t = num % base;
				ss =  BASE[t] + ss;
				num = Math.floor(num/base);
		}
		return ss;
}
var bigi = require("../bigint");

Buffer.prototype.toExpand = function(string,base){
	var asa = bigi.str2bigInt(string,base);
 	var ss = bigi.bigInt2str(asa,16);
 
	var re = new Buffer(ss.length%2===0?ss:"0"+ss,'hex');
	return re;
}


Buffer.prototype.toBase = function(base){
	var ss = this.toString("hex");
	var asa = bigi.str2bigInt(ss,16);
	var s = bigi.bigInt2str(asa,base);

	return  s;
	console.log(base,"sass",asa,s,ss);

	return ;

	var nn = this.clone();
		var nwords = Math.floor(nn.length/4);
		var padding = [0,1,2,3][nn.length % 4];
		var rest = parseInt(nn.slice(nn.length-padding).toString("hex"),16);
		var s = "";
		var at = 0;
	while(at < nwords){
		var num = nn.readUInt32BE(at*4);


		s += getnum(num,base);
		s += ss+" ";	 
		at += 1;
	}
	console.log(rest);

	s += getnum(rest,base);

return s;

 
}



Buffer.prototype.prepend = function(buf){
	var tmp = new Buffer(this.length+buf.length);
	for(var i=0;i<buf.length;i++){
		tmp[i]=buf[i];
		}
	for(var i=0;i<this.length;i++){
		tmp[buf.length+i]=this[i];
		}
	return tmp;
}
Buffer.prototype.SHA1= function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('sha1');
		h.update(this);
		return h.digest(encoding);
}
Buffer.prototype.SHA224 = function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('sha224');
		h.update(this);
		return h.digest(encoding);
}
Buffer.prototype.SHA256 = function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('sha256');
		h.update(this);
		return h.digest(encoding);
}
Buffer.prototype.SHA384 = function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('sha384');
		h.update(this);
		return h.digest(encoding);
}
Buffer.prototype.SHA512 = function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('sha512');
		h.update(this);
		return h.digest(encoding);
}

Buffer.prototype.MD5= function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('md5');
		h.update(this);
		return h.digest(encoding);
}
Buffer.prototype.RIPE= function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('ripemd');
		h.update(this);
		return h.digest(encoding);
}
Buffer.prototype.RIPE160= function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('ripemd160');
		h.update(this);
		return h.digest(encoding);
}

Buffer.prototype.WHIRLPOOL= function(encoding){
	var encoding = encoding || null;
	var h=crypto.createHash('whirlpool');
		h.update(this);
		return h.digest(encoding);
}

Buffer.prototype.cmp = function(cmp){
	return !this.cmpNotSame.apply(this,[cmp]);
	}

Buffer.prototype.cmpNotSame = function(cmp){
	var f=false;
	var nmax = this.length > cmp.length ? cmp.length : this.length;
	var n = 0;
	while(!f){
		if(cmp[n]===this[n]){
			n++
		}else{
			f=true;
		}
		if(n>nmax){
			return f;
			}
		}
		return f;
	}

//console.log(crypto.getHashes());


//console.log(new Buffer("10"));

/*
Buffer.prototype.scan = function(chunksize,each,end){
	var end = end || function(){};
	var each = each || function(){};
	var maxi = this.length;
	var items = 0;
	if( maxi % chunksize === 0){
		items = maxi/chunksize;
		}

	var indexat = 0;
	var self = this;
	var count = 0;
	function chunk(){
		var pp = (indexat+chunksize);
			pp = (pp > maxi ? maxi : pp);

		each.apply(each,[self.slice(indexat,pp),count]);
		count ++;
		if(indexat < self.length-chunksize){
				indexat += chunksize;
				process.nextTick(chunk);
			}else{
				end.apply(end,[count]);
				}
		}

	chunk();

	}

*/


/*
Buffer.prototype.extract = function(obj){
	var o = {};
	for(var prop in obj){

		if(obj[prop].pos){
			o[prop] = obj[prop].type(this.slice(obj[prop].pos[0],obj[prop].pos[1]));
		}else{
			if(typeof(obj[prop]) === "object"){
				o[prop] = {};
				for(var subprop in obj[prop]){
						if(obj[prop][subprop].pos){

					o[prop][subprop] = obj[prop][subprop].type(this.slice(obj[prop][subprop].pos[0],obj[prop][subprop].pos[1]));
					}

					}


				}

			}
	}

	return o;


	}






Buffer.prototype.chksum = function(encoding){
	var encoding = encoding || 'base64';
	var hash=crypto.createHash('sha256');
		hash.update(this);
		var r = hash.digest(encoding);
		if(encoding==="binary"){
			var rr = new Buffer(32);
			for(var i=0;i<32;i++){
				rr[i] = r.charCodeAt(i);
				}
				r = rr;
			}
	return r;
}
Buffer.prototype.chksuma = function(encoding){
	var encoding = encoding | 'base64';
	var hash=crypto.createHash('sha1');
		hash.update(this);
	return	hash.digest(encoding);
}



Buffer.prototype.toHex = function(){
	var s = "";
	for(var i=0;i<this.length;i++){
		var byte = this[i].toString(16);
			byte = (byte.length<2) ? '0'+byte : byte;
			s += byte;
		}
	return s;
	}




Buffer.prototype.toInt = function(){
	var l=this.length-1;
	var i=this[l];
	l--;
	var b = 256;
	while(l>-1){
		i += this[l]*b;
		l--;
		b *= 256;
		}
	return i;
	}






Buffer.prototype.indexOf = function(bytes,start){
	var i=start||0;
	var len=this.length-bytes.length,found=false;
	while(!found && i<len){
		var a = this.slice(i,i+bytes.length);
		if(a.toString()===bytes.toString()){
			return i;
			}

		i++;
		}
	return false;



	};

Buffer.prototype.fill = function(a){
	if(typeof(a)==="function"){
		for(var i=0;i<this.length;i++){
			 this[i] = a.apply(this,[i]);
		}

		}else{

		for(var i=0;i<this.length;i++){
				this[i] = a;
		}
	}
}

Buffer.prototype.filla = function(a,ii,is){
	if(typeof(a)==="function"){
		for(var i=ii;i<is;i++){
			 this[i] = a.apply(this,[i]);
		}

		}else{

		for(var i=ii;i<is;i++){
				this[i] = a;
		}
	}
}

function random_byte(){
	return Math.floor(Math.random()*255);
	}
function add_byte(i){
	this[i] = this[i]+1;

	}
*/

function hexdump(buf,showascii,perline,space,padit,linenums,showtype){
	var showtype = showtype || false;
		var s = "";
		if(showtype){
			s += "type: "+typeof(buf)+" "+((buf instanceof Buffer))+"\n";
		}
	if(typeof(buf) !== "object"){
		buf = new Buffer(buf);
		}

	var usebuf;
	var perline = (perline===0||perline) ? perline : 32;
	var space = (space===0||space) ? space : 8;
	var showascii = showascii || false;
	var linenums = linenums || false;
	if(perline === 0){
		perline = buf.length;
		}
	usebuf = buf;
	if(padit){
		var shouldbelength = Math.ceil(buf.length/perline)*perline;
		var nbuf = new Buffer(shouldbelength);
			nbuf.fill(0);
			buf.copy(nbuf,0,0,buf.length);
			usebuf = nbuf;
		}

	var tl = Math.ceil(buf.length/perline);



	for(var i=0;i<tl;i++){
		var mx = (i*perline)+perline;
			if(mx > usebuf.length){
				mx = usebuf.length;
			}
			if(linenums){
				s += intToHex(i*perline,3)+" ";

				}
			var a = "";
			var t = usebuf.slice(i*perline,mx);
			for(var y=0;y<t.length;y++){
				s += int2hex(t[y]);
					if((t[y] > 31) && (t[y] !== 127)){
						a += String.fromCharCode(t[y]);
					}else{
						a += ".";
					}

				if(y % space === (space-1)){
					s += " ";
					a += " ";
					}

				}

				if(showascii){
					s += " | " +a;
				}
				if(tl>1){
					s += "\n";

					}

		}

return s;

}


function int2hex(integer) {
  integer = integer.toString(16);
  if (integer.length % 2 !== 0) {
    integer = '0' + integer;
  }
  return integer;
};

function int2word(integer) {
  integer = integer.toString(16);
  if (integer.length % 8 !== 0) {
	  while(integer.length<8){
		    integer = '0' + integer;
	  }
  }
  return integer;
};
function int2longword(integer) {
  integer = integer.toString(16);
  if (integer.length % 16 !== 0) {
	  while(integer.length<16){
		    integer = '0' + integer;
	  }
  }
  return integer;
};


exports.intToHex = intToHex;

exports.hexToBytes = hexToBytes;

exports.hexToBuffer = hexToBuffer;

function hexToBuffer (hexa) {
	return new Buffer(hexToBytes(hexa));
}


function hexToBytes (hexa) {
	for (var bytes = [], c = 0; c < hexa.length/2; c ++)
		bytes.push(parseInt(hexa.substr(c*2, 2), 16));
	return bytes;
};

function intToHex (integera,bytes) {
	var bytes = bytes || 1;
	   integera = integera.toString(16);
	  if (integera.length % (bytes*2) !== 0) {
		  while(integera.length<bytes*2){
			    integera = '0' + integera;
		  }
	  }
	  return integera;
};

exports.bufferToInt = function (arr){
	var l=arr.length-1;
	var i=arr[l];
	l--;
	var b = 256;
	while(l>-1){
		i += arr[l]*b;
		l--;
		b *= 256;
		}
	return i;
	}
exports.intToBuffer = function (integer,bytesa){
	var hex = intToHex(integer,bytesa);
	var bb = hexToBytes(hex);
	return new Buffer(bb);
	}


String.prototype.lpad = function(l,ww){
var w = ww || " ";
var s = this;
while(s.length<l){
	s = w + s;
	}
return s;
}
String.prototype.rpad = function(l,ww){
	var w = ww || " ";
	var s = this;
	while(s.length<l){
		s = s+w;
		}
	return s;
	}



/*


function hexdump(buf,showascii,perline,space,padit,linenums,showtype){
	var showtype = showtype || false;
		var s = "";
		if(showtype){
			s += "type: "+typeof(buf)+" "+((buf instanceof Buffer))+"\n";
		}
	if(typeof(buf) !== "object"){
		buf = new Buffer(buf);
		}

	var usebuf;
	var perline = (perline===0||perline) ? perline : 32;
	var space = (space===0||space) ? space : 8;
	var showascii = showascii || false;
	var linenums = linenums || false;
	if(perline === 0){
		perline = buf.length;
		}
	usebuf = buf;
	if(padit){
		var shouldbelength = Math.ceil(buf.length/perline)*perline;
		var nbuf = new Buffer(shouldbelength);
			nbuf.fill(0);
			buf.copy(nbuf,0,0,buf.length);
			usebuf = nbuf;
		}

	var tl = Math.ceil(buf.length/perline);



	for(var i=0;i<tl;i++){
		var mx = (i*perline)+perline;
			if(mx > usebuf.length){
				mx = usebuf.length;
			}
			if(linenums){
				s += intToHex(i*perline,3)+" ";

				}
			var a = "";
			var t = usebuf.slice(i*perline,mx);
			for(var y=0;y<t.length;y++){
				s += int2hex(t[y]);
					if((t[y] > 31) && (t[y] < 127 || t[y] > 127) && (t[y] !== 129 && t[y] !== 143 && t[y] !== 144 && t[y] !== 157  && t[y] !== 160 && t[y] !== 173 ) ){
						a += String.fromCharCode(t[y]);
					}else{
						a += ".";
					}

				if(y % space === (space-1)){
					s += " ";
					a += " ";
					}

				}

				if(showascii){
					s += " | " +a;
				}
				if(tl>1){
					s += "\n";

					}

		}

return s;

}



*/