var Feedback;
var Values;
var Totals;
var TotalItems;


function init()
{
  Feedback=document.getElementById('Feedback');
}

function getLimit()
{
  var limit=Number(document.form.limit.value);
  if(isNaN(limit))
    limit=100;
  return limit;
}

function TidyStr(str)
{
// Presto & Trident use carriage returns in text areas
// Gecko & Webkit don't. Remove to make all equal
  str=str.replace(/\r/g,'');
  str=str.replace(/\n/g,'%£');
  str=str.replace(/(%£)+$/,'');

  return str
}

function Factorial(n)
{
  if(n<=1)
    return 1;
  else
    return Factorial(n-1)*n;
}



function GetCombinations()
{
  var limit=getLimit();
  var str=document.form.input.value;
  str=TidyStr(str);

  var Input=str.split('%£');
  Values=new Array();

  var b=Input.length;
  var c=0;
  var d=0;
  Values[0]=new Array();

  for(var a=0;a<b;a++)
    {
      if(Input[a]=='')
        {
          if(Values[c].length>0 && Input[a+1]!='')
            {
              c++;
              d=0;
              Values[c]=new Array();
            }
        }
      else
      if(Input[a].charAt(0)=='*')
        {
          var f=Number(Input[a].substr(1))-1;
          for(var e=0;e<f;e++)
            {
              c++;
              Values[c]=Values[c-1].slice(); // copies array
            }
        }
      else
        {
          Values[c][d]=Input[a];
          d++;
        }
    }


  TotalItems=Values.length;
  b=Values.length;
  c=1;

  Totals=new Array();

  for(var a=b-1;a>-1;a--)
    {
      Totals[a]=c;
      c=c*Values[a].length;
    }

// C ends up as the total number of combinations

  Show(1,limit,c,'Combinations');
}

// returns number of ways to fill N positions with k objects
function Choose(n,k)
{
//alert(n+'\n'+k)
  var x=Factorial(n)/(Factorial(k)*Factorial(n-k));
  return x;
}

function GetPositions(Positions,Items,n)
{
  var Output=new Array();
  for(var a=0;a<Items;a++)
    Output[a]=a+1;

  var b=Items-1;

  for(a=0;a<n;a++)
    {
      if(Output[b]<(Positions-(Items-b-1)))
        Output[b]++;
      else
        {
          while(b>0 && Output[b]==(Positions-(Items-b-1)))
            b--;

          Output[b]++;
          for(;b<Items-1;b++)
            Output[b+1]=Output[b]+1;
        }
    }

  return Output;
}

function GetPermutations()
{
  var limit=getLimit();
  var str=document.form.input.value;
  str=TidyStr(str);
  str=str.replace(/(%£)+/g,'%£');
  var Input=str.split('%£');
  Input.sort();

  Values=new Array();

  TotalItems=Input.length;

  var b=Input.length;
  var c=0;
  var d=0;
  Values[0]=new Array();

  for(var a=0;a<b;a++)
    {
      if(a==0 || Input[a]==Input[a-1])
        Values[c].push(Input[a]);
      else
        {
          c++;
          Values[c]=new Array(Input[a]);
        }
    }


  Totals=new Array();

  var b=Values.length;
  var spaces=Input.length;
  for(a=0;a<b;a++)
    {
      Totals[a]=Choose(spaces,Values[a].length);
      spaces=spaces-Values[a].length;
    }



  var c=1;
  var b=Totals.length;

  for(a=0;a<b;a++)
    c=c*Totals[a];

  var d=c;

  Totals2=new Array();
  for(a=0;a<b;a++)
    {
      Totals2[a]=d/Totals[a];
      d=Totals2[a];
    }

  Totals2[Totals2.length-1]=0;

  Show(1,limit,c,'Permutations');
}

function Show(From,To,Of,Type)
{
  while(Feedback.firstChild)
    Feedback.removeChild(Feedback.firstChild);

  var Seperator=document.form.seperator.value;

  if(To>Of)
    To=Of;

  var E=document.createElement('h4');
  if(To<Of || From>1)
    E.appendChild(document.createTextNode(From+' to '+To+' of '));

  E.appendChild(document.createTextNode(Of+' '+Type));
  Feedback.appendChild(E);

  AddButtons(From,To,Of,Type);

  var b=0;
  var str='';

  var list=document.createElement('ul');
  for(var a=From-1;a<To;a++)
    {
      var ThisStr=new Array();
      ThisStr.length=TotalItems;

      for(b=0;b<Values.length;b++)
        {
          if(Type=='Combinations')
            {
              f=Math.floor(a/Totals[b])%Values[b].length;
              ThisStr[b]=Values[b][f];
            }
          else
            {
              var FreePos=new Array();
              for(var d=0;d<ThisStr.length;d++)
                if(ThisStr[d]==null)
                  FreePos.push(d);

              if(b==0)
                n=Math.floor(a/(Of/Totals[0]));
              else if(b==Values.length-1)
                n=0;
              else
                n=Math.floor(a/Totals2[b])%Totals[b];


              var Pos=GetPositions(FreePos.length,Values[b].length,n);

              for(var d=0;d<Pos.length;d++)
                ThisStr[FreePos[Pos[d]-1]]=Values[b][0];
            }
        }

      E=document.createElement('li')
      E.appendChild(document.createTextNode(ThisStr.join(Seperator)));
      list.appendChild(E);
    }

  Feedback.appendChild(list);
  AddButtons(From,To,Of,Type);
}


function AddButtons(From,To,Of,Type)
{
  var E=document.createElement('p');
  var limit=getLimit();

  if(From>1)
    {
      var B=document.createElement('input');
      B.setAttribute('type','button');
      B.setAttribute('value','Prev');
//      B.setAttribute('onClick','Show('+(From-limit)+','+(From-1)+','+Of+')'); // IE=FAIL
      B.onclick=function(){Show((From-limit),(From-1),Of,Type);};
      E.appendChild(B);
    }

  if(To<Of)
    {
      var B=document.createElement('input');
      B.setAttribute('type','button');
      B.setAttribute('value','Next');
//      B.setAttribute('onClick','Show('+(To+1)+','+(To+limit)+','+Of+')'); // IE=FAIL
      B.onclick=function(){Show((To+1),(To+limit),Of,Type);};
      E.appendChild(B);
    }

  Feedback.appendChild(E);
}
