var NDIGITS = 16;
var STACKSIZE = 12;

var value = 0;		
var memory = GetCookie("CalcMemory");	
if (!memory) memory = 0;
var level = 0;		
var entered = true;	
var decimal = 0;		
var fixed = 0;		
var exponent = false;	
var inverse = false;	

if (location.search)
{
	// pass in value through command line
	value = location.search.substring(1,location.search.length);
}

function stackItem()
{
	this.value = 0;
	this.op = "";
}

function array(length)
{
	this[0] = 0;
	for (i=0; i<length; ++i)
	{
		this[i] = 0;
		this[i] = new stackItem();
	}
	this.length = length;
}

stack = new array(STACKSIZE);

function push(value,op,prec)
{
	if (level==STACKSIZE)
		return false;
	for (i=level;i>0; --i)
	{
		stack[i].value = stack[i-1].value;
		stack[i].op = stack[i-1].op;
		stack[i].prec = stack[i-1].prec;
	}
	stack[0].value = value;
	stack[0].op = op;
	stack[0].prec = prec;
	++level;
	return true;
}

function pop()
{
	if (level==0)
		return false;
	for (i=0;i<level; ++i)
	{
		stack[i].value = stack[i+1].value;
		stack[i].op = stack[i+1].op;
		stack[i].prec = stack[i+1].prec;
	}
	--level;
	return true;
}

function format(value)
{
	var valStr = "" + value;
	if (valStr.indexOf("N")>=0 || (value == 2*value && value == 1+value))
		return "Я перегрелся... ";
	var i = valStr.indexOf("e")
	if (i>=0)
	{
		var expStr = valStr.substring(i+1,valStr.length);
		if (i>11) i=11;  // max 11 digits
		valStr = valStr.substring(0,i);
		if (valStr.indexOf(".")<0) valStr += ".";
		valStr += " " + expStr;
	}
	else
	{
		var valNeg = false;
		if (value < 0)
			{ value = -value; valNeg = true; }
		var valInt = Math.floor(value);
		var valFrac = value - valInt;
		var prec = NDIGITS - (""+valInt).length - 1;	
		if (! entered && fixed>0)
			prec = fixed;
		var mult = " 1000000000000000000".substring(1,prec+2);
		var frac = Math.floor(valFrac * mult + 0.5);
		valInt = Math.floor(Math.floor(value * mult + .5) / mult);
		if (valNeg)
			valStr = "-" + valInt;
		else
			valStr = "" + valInt;
		var fracStr = "00000000000000"+frac;
		fracStr = fracStr.substring(fracStr.length-prec, fracStr.length);
		i = fracStr.length-1;
		if (entered || fixed==0)
		{
			// remove trailing zeros unless fixed during entry.
			while (i>=0 && fracStr.charAt(i)=="0")
				--i;
			fracStr = fracStr.substring(0,i+1);
		}
		if (i>=0) valStr += "." + fracStr;
//		document.result.debugField.value = "prec "+prec+", mult "+mult+", frac "+frac;
	}
	return valStr;
}

function refresh()
{
	var display = format(value);
	if (exponent)
	{
		if (expval<0)
			display += " " + expval;
		else
			display += " +" + expval;
	}
	if (display.indexOf(".")<0 && display != "Я перегрелся... ")
	{
		if (entered || decimal>0)
			display += '.';
		else
			display += ' ';
	}
	display = "               " + display;
	display = display.substring(display.length-NDIGITS-1,display.length);
	document.result.result.value = display;
	inverse = false;
}

function clearAll()
{
	level = 0;
	clear();
}

function clear()
{
	exponent = false;
	value = 0;
	enter();
	refresh();
}

function evalx()
{
	if (level==0)
		return false;
	op = stack[0].op;
	sval = stack[0].value;
//	alert("eval "+sval+op+value);
	if (op == '+')
		value = parseFloat(sval) + value;
	else if (op == '-')
		value = sval - value;
	else if (op == '*')
		value = sval * value;
	else if (op == '/')
		value = sval / value;
	else if (op == 'pow')
		value = Math.pow(sval,value);
	pop();
	if (op=='(')
		return false;
	return true;
}

function openp()
{
	enter();
	if (!push(0,'(',0))
	{
		value = "NAN";
	}
	refresh();
}

function closep()
{
	enter();
	while (evalx())
		;
	refresh();
}

function operator(op)
{
	enter();
	if (op=='+' || op=='-')
		prec = 1;
	else if (op=='*' || op=='/')
		prec = 2;
	else if (op=="pow")
		prec = 3;
	if (level>0 && prec <= stack[0].prec)
		evalx();
	if (!push(value,op,prec))
	{
		value = "NAN";
	}
	refresh();
}

function enter()
{
	if (exponent)
		value = value * Math.exp(expval * Math.LN10);
	entered = true;
	exponent = false;
	decimal = 0;
	fixed = 0;
}

function equals()
{
	enter()
	while (level>0)
		evalx();
	refresh();
}

function digit(n)
{
	if (entered)
	{
		value = 0;
		digits = 0;
		entered = false;
	}
	if (n==0 && digits==0)
	{
		refresh();
		return;
	}
	if (exponent)
	{
		if (expval<0)
			n = -n;
		if (digits < 3)
		{
			expval = expval * 10 + n;
			++digits;
			refresh();
		}
		return;
	}
	if (value<0)
		n = -n;
	if (digits < NDIGITS-1)
	{
		++digits;
		if (decimal>0)
		{
			decimal = decimal * 10;
			value = value + (n/decimal);
			++fixed;
		}
		else
			value = value * 10 + n;
	}
	refresh();
}

function sign()
{
	if (exponent)
		expval = -expval;
	else
		value = -value;
	refresh();
}

function period()
{
	if (entered)
	{
		value = 0;
		digits = 1;
	}
	entered = false;
	if (decimal == 0)
	{
		decimal = 1;
	}
	refresh();
}

function exp()
{
	if (entered || exponent)
		return;
	exponent = true;
	expval = 0;
	digits = 0;
	decimal = 0;
	refresh();
}

function inv()
{
	inverse = !inverse;
}

function func(f)
{
	enter();
	if (f=="1/x")
		value = 1/value;
	else if (f=="swap")
	{
		var tmp = value;
		value = stack[0].value;
		stack[0].value = tmp;
	}
	else if (f=='n!')
	{
		if (value<0 || value>200 || value != Math.round(value))
			value = "NAN";
		else
		{
			var n = 1;
			var i;
			for (i=1;i<=value;++i)
				n *= i;
			value = n;
		}
	}
	else if (f=="MR")
		value = memory;
	else if (f=="M+")
	{
		memory += value;
		SetCookie("CalcMemory", memory);
	}
	else if (f=="Min")
	{
		memory = value;
		SetCookie("CalcMemory", memory);
	}
	else if (inverse)
	{
	 	if (f=="sin")
			value = Math.asin(value)*180/Math.PI;
		else if (f=="cos")
			value = Math.acos(value)*180/Math.PI;
		else if (f=="tan")
			value = Math.atan(value)*180/Math.PI;
		else if (f=="log")
			value = Math.exp(value * Math.LN10);
		else if (f=="log2")
			value = Math.exp(value * Math.LN2);
		else if (f=="ln")
			value = Math.exp(value);
		else if (f=="sqrt")
			value = value*value;
		else if (f=="pi")
			value = Math.E;
	}
	else
	{
	 	if (f=="sin")
			value = Math.sin(value/180 * Math.PI);
		else if (f=="cos")
			value = Math.cos(value/180 * Math.PI);
		else if (f=="tan")
			value = Math.tan(value/180 * Math.PI);
		else if (f=="log")
			value = Math.log(value)/Math.LN10;
		else if (f=="log2")
			value = Math.log(value)/Math.LN2;
		else if (f=="ln")
			value = Math.log(value);
		else if (f=="sqrt")
			value = Math.sqrt(value);
		else if (f=="pi")
			value = Math.PI;
	}
	refresh();
}

function hex()
{
	location = "raschet_rezistora.html?"+value;
}

function info()
{
	alert("Желаем хорошего моддинга! Функция ПОКА не доступна...");
}

function getCookieVal (offset) {
  var endstr = document.cookie.indexOf (";", offset);
  if (endstr == -1)
    endstr = document.cookie.length;
  return unescape(document.cookie.substring(offset, endstr));
}

function GetCookie (name) {
  var arg = name + "=";
  var alen = arg.length;
  var clen = document.cookie.length;
  var i = 0;
  while (i < clen) {
    var j = i + alen;
    if (document.cookie.substring(i, j) == arg)
      return getCookieVal (j);
    i = document.cookie.indexOf(" ", i) + 1;
    if (i == 0) break; 
  }
  return null;
}

function SetCookie (name, value) {
  var argv = SetCookie.arguments;
  var argc = SetCookie.arguments.length;
  var expires = (argc > 2) ? argv[2] : null;
  var path = (argc > 3) ? argv[3] : null;
  var domain = (argc > 4) ? argv[4] : null;
  var secure = (argc > 5) ? argv[5] : false;
  document.cookie = name + "=" + escape (value) +
    ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
    ((path == null) ? "" : ("; path=" + path)) +
    ((domain == null) ? "" : ("; domain=" + domain)) +
    ((secure == true) ? "; secure" : "");
}

function DeleteCookie (name) {
  var exp = new Date();
  exp.setTime (exp.getTime() - 1);  // This cookie is history
  var cval = GetCookie (name);
  document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
}




