/*****************************************************************************
 * controls the dynamic behavior
 * of the elements in the multilayer tab
*****************************************************************************/

// global variables

// init drill holes for each column
// values are set in editspec.tpl/php (PHP_INIT_HOLES)
var holes = new Array();

// init drill hole size for each column
// values are set in editspec.tpl/php (PHP_INIT_HOLES)
var holesmin = new Array();


/*****************************************************************************
 * attention: not for array at the moment
 * replace a string or array (search) with an string or array (replace)
 * in an string or array (subject) and returns the new string or array
 *
 * params:
 * 		- search: needle  (string/array)
 * 		- replace: with a new needle  (string/array)
 * 		- subject: is the haystack  (string/array)
 *
 * return:
 * 		- edited subject (string/array)
*****************************************************************************/

function str_replace(search, replace, subject) {

    // ToDo: repair code
    /*
    var s = subject;
    var f = [].concat(search);
    var r = [].concat(replace);

    var ra = r instanceof Array;
    var sa = s instanceof Array;

    var i = (s = [].concat(s)).length;
    var j = 0;
    var x = 0;

    while (i > 0) {
        i--;
        if (s[i]) {
            while (++j in f){
                s[i] = (s[i]+'').split(f[j]).join(ra ? r[j] || "" : r[0]);
            };
        }
        x++;
        j = 0;
    }
    return sa ? s : s[0];
    */

    // quick and dirty alternative
    return subject.split(search).join(replace);
}

/*****************************************************************************
 * create drill grafic and both drill infos
 *
 * params:
 *      - how many layers (layerNumber)
 *      - drill code (data)
 * is called by:
 *      -  editspec.tpl
 * calls:
 *      - updatevalues()
 * return:
 *      - allways false
*****************************************************************************/

    function my_showLayers(layerNumber, drillData){

        // determine the div container for the output we like to create
        outputelement = document.getElementById('my_layers');
        // if this container not exist
        if(!outputelement) {
            // stop this here
            return false;
        }

        // init the output
        var outstr='';

        // if drillData param is empty
        if(drillData==undefined || !drillData.length){
            // init drillData
            drillData='';
            drillSign = '';
            // now set drillData default
            if(holes[0] == 0){
                // zero drill holes per spacer
                drillSign = '.';
            } else {
                // one drill hole on each spacer
                drillSign = '|.';
            }
            for(lines = 0; lines < layerNumber - 1; lines++) {
                drillData += drillSign;
            }
            inp       = document.getElementById('layersinput');
            inp.value = drillData;
        }

        // determine the sign lenght of each spacer part in the drillData element
        // e.g. '|||.|||.|||.' = 12 signs / 3 spacer = 4 signs for each spacer
        linelength = drillData.length / (layerNumber-1);

        // build drill grafic
        // for each spacer (column)
        var firstOrLastLine = '';
        outstr +='<div id="drills">';
        for(lines = 0; lines < layerNumber - 1; lines++) {
            // for each sign in spacer part of the drillData (line)
            // on last or first line, add a special class to div
            switch (lines) {
            case 0:
                firstOrLastLine = 'first';
                break;
            case layerNumber-2:
                   firstOrLastLine = 'last';
                   break;
            }
            outstr +='<div class="drillHole '+firstOrLastLine+'">';
            for(column = 0; column < linelength; column++) {
                //init the image
                var img = "";
                firstOrLastLine = '';
                // look what kind of sign we have and choose the right image
                switch(drillData.charAt(column+linelength*lines)){
                    case ".":
                        // empty image
                        img='<img border=0 src="/images/_layer_empty.png">';
                        break;
                    case "|":
                        // drill hole
                        img='<img border=0 src="/images/_layer_hole.jpg">';
                        break;
                    case "v":
                        // hole frome top
                        img='<img border=0 src="/images/_layer_hole_topdown.png">';
                        break;
                    case "^":
                        // hole from bottom
                        img='<img border=0 src="/images/_layer_hole_bottomup.png">';
                        break;
                    case "a":
                        // a hand?
                        img='<img border=0 src="/images/_layer_action.gif"  width=25 height=60>';
                        break;
                }
                // build linked image to change drills
                outstr += '<a href="javascript:void(my_layerswitch('+layerNumber+', '+column+', '+lines+', \''+drillData+'\'))">';
                outstr += img;
                outstr += '</a>';
            }
            // add a linebreak in the drill grafic
            outstr += '</div>';
        }
        // add a linebreak in the drill grafic
        outstr += '</div>';

        // add drill counter
        outstr += '<div id="drillNumberLine">';
        for(column = 0; column < linelength - 1; column++) {
            // if drill counter is empty
            if(holes[column] == undefined){
                // use default
                holes[column] = 0;
            }
            // if drill size is empty
            if(holesmin[column] == undefined){
                // use default
                holesmin[column] = 0.4;
            }
            outstr += '<div id="drillNumber' + column + '" class="drillNumber">';
            outstr += '<label class="sequenzesLabel">'+ document.getElementById("labelHolesSum").value +'</label><br>';
            outstr += '<input name="holes_'+ column +'" value="'+holes[column]+'" onChange="setHoleValue('+column+', this.value, '+linelength+')">';
            outstr += '</div>';
        }
        outstr += '</div>';
        //outstr += '<div style="clear:both;">&nbsp;</div>';
        // add drill size info
        outstr += '<div id="drillWidthLine">';
        for(column = 0; column < linelength - 1; column++) {
            outstr += '<div id="drillWidth' + column + '" class="drillWidth">';
            outstr += '<label class="sequenzesLabel">'+ document.getElementById("labelMinHolesWidth").value +'</label><br>';
            outstr += '<input name="holesmin_'+column+'" value="'+holesmin[column]+'" onChange="setHoleMinValue('+column+', this.value, '+linelength+')">';
            outstr += '</div>';
        }
        outstr += '</div>';
        //outstr += '<div style="clear:both;">&nbsp;</div>';


        // write output to screen
        // create new div
        var newdiv = document.createElement("div");
        // add output to div
        newdiv.innerHTML = outstr;
        // add new div to output div
        document.getElementById("my_layers").appendChild(newdiv);
        // remove old output div
        document.getElementById("my_layers").removeChild(document.getElementById("my_layers").firstChild);
        // ?
        updatevalues(linelength);
        update_grafical_multilayer();
        // end function
        return false;
    }

/*****************************************************************************
 *  called by onChange event from the holes input field
 *  write input to data store
 *  update input field
 *  update drill hole sum
 ****************************************************************************/

function setHoleValue(h, value, linelength){

    // update data store
    holes[h]=value;
    // set status to changed
    document.forms['tab_f'].elements['change'].value=1;
    // update sum info
    updatevalues(linelength);
}

/*****************************************************************************
*  called by onChange event from the holesmin input field
*  checks the input (replace comma, no strings)
*  update input field
*  write input to data store
*****************************************************************************/
function setHoleMinValue(h, value, linelength){

    // replace comma width point
    value = value.replace(',','.');
    // prevent input of non-floats
    value = parseFloat(value);

    // none float and greater null
    if (!isNaN(value) && value > 0) {
        // set new holes min
        holesmin[h]=value;
        // update input field
        document.forms['tab_f'].elements['holesmin_'+h].value=value;
        // set status to changed
        document.forms['tab_f'].elements['change'].value=1;
    } else {
        // set input to old value
        document.forms['tab_f'].elements['holesmin_'+h].value=0.4;
    }
}

/*****************************************************************************
* xxx
*
*****************************************************************************/
function updatedicken()
{
  sum = 0;
  calcable = true;
  for(i=1; i < 99; i++)
  {
    if(document.forms['tab_f'].elements['dickelayer_'+i])
    {
      if (document.forms['tab_f'].elements['dickelayer_'+i].value == "0")
      {
        calcable = false;
      }
      sum += Math.round(parseFloat(str_replace(',','.',document.forms['tab_f'].elements['dickelayer_'+i].value)));

        if(document.forms['tab_f'].elements['spacerlayer_'+i])
        {
          sum += Math.round(parseFloat(str_replace(',','.',document.forms['tab_f'].elements['spacerlayer_'+i].value)));
        }
    }
    else
    {
      i=99;
    }
  }
  if (!calcable)
  {
    sum = '--';
  } else {
    sum = sum/1000; // micro to mm
    sum = sum.toFixed(4);
  }
  document.getElementById('gesamtdicke').innerHTML = sum;
}
/*****************************************************************************
* calculates the sum of all drill holes
* called after changed one of the input fields
*****************************************************************************/
function updatevalues(linelength)
{
  var i = 0;
  var sum = 0;
  for(i=0; i < linelength-1; i++)
  {
    sum += parseFloat(holes[i]);
  }
  document.getElementById('bohrungengesamt').innerHTML = String(sum);
  updatedicken();
}
/*****************************************************************************
* ?
*
* params:
* e.g. for one empty sequenze  (12, 0, 0, '...........')

*   1. numberOfLayers (l   - layers
*   2. clickedColumn (x)   - sequenz (column)
*   3. clickedRow (y)      - hole (row)
*   4. seqDataBlock (data) - information of all sequenzes
*             - in a sequenze are Z holes (Z = numberOfLayers -1)
*             - each hole of a seqenze is marked with:
*               - . = no hole
*               - v = one hole from top
*               - ^ = one hole from bottom
*               - | = hole sequenze (more than one hole)
*             - holes are sorted by row
*               - row 1 seqenze 1, row 1 sequenze 2, row 2 seqenze 1, row 2 sequenze 2, ...

*****************************************************************************/
function my_layerswitch(numberOfLayers, clickedColumn, clickedRow, seqDataBlock){

    // mark spec as changed
    // script is defined in editspec.tpl
    report_changes ();

    // get the number of sequenzes
    var numberOfSequenzes = seqDataBlock.length/(numberOfLayers-1);
    // get the position of the clicked element in seqDataBlock string
    pos = clickedColumn + numberOfSequenzes*clickedRow;
    var fixed_pos = pos;
    // get the type of the clicked element in seqDataBlock string
    c = seqDataBlock.charAt(pos);
    //alert('pos='+pos+'['+c+']');
    remove_below = false;

    // no symbol at click position yet
    if(c == '.'){
        // fill empty elements from click to allready filled position
        // but must not be the last sequenz where every click is the first click
        if (clickedColumn != numberOfSequenzes - 1){
            // and it must be not connected above or below
            // (first segment or segement above is empty) and (last segment or segment below is empty)
            if ( ((clickedRow == 0)          || (seqDataBlock.charAt(fixed_pos - numberOfSequenzes) == '.')) &&
                 ((clickedRow == numberOfLayers - 2) || (seqDataBlock.charAt(fixed_pos + numberOfSequenzes) == '.'))
                ) {
                    // then we got a Have-To-Fill-Siuation
                    // so initialize some global variables
                    var i = 0;
                    var fillToPosition = "";
                    var fillDeriction = "";
                    // then go through the whole clicked column and
                    for (i = 0; i < numberOfLayers-1; i++) {
                        // get all entrys from the clicked column
                        // alert ((clickedColumn + i*numberOfSequenzes) + " - " +seqDataBlock.charAt(clickedColumn + i*numberOfSequenzes));
                        // current position
                        loopPosition     = clickedColumn + i*numberOfSequenzes;
                        // current sign there
                        loopPositionSign = seqDataBlock.charAt(clickedColumn + i*numberOfSequenzes);
                        // we have to find out the fill start and the fill end
                        if ((loopPosition <= fixed_pos) && (loopPositionSign == '|' || loopPositionSign == 'v' || loopPositionSign == '^')){
                            // save last found position with an not empty cell
                            fillToPosition = loopPosition;
                            // fill direction from top to click position
                            fillDirection = "above";
                        }
                        // the end position lay below the click
                        else if ((fillToPosition == "") && (loopPositionSign == '|' || loopPositionSign == 'v' || loopPositionSign == '^')) {
                            // save first found position that is not empty
                            fillToPosition = loopPosition;
                            // fill direction is from bottom to clicked position
                            fillDirection = "below";
                        }
                    }
                    // set start point and end point, but allways from top to bottom
                    //alert (fillDirection + " to " + fillToPosition);
                    var startPosition = 0;
                    var endPosition = 0;
                    // so the start point depends on fill direction
                    if (fillDirection == "below"){
                        // fill below click
                        // startpoint is click position to fill position
                        startPosition = fixed_pos;
                        endPosition = fillToPosition;
                    }
                    else {
                        // fill above click
                        // startpoint is fillposition to clickposition
                        startPosition = fillToPosition;
                        endPosition = fixed_pos;
                    }

                    // change all elements from start to end and set a hole symbol
                    for (i = startPosition; i <= endPosition; i = i + numberOfSequenzes) {
                        //alert (i + " - " + startPosition + " - " + endPosition);
                        //alert (i + " - " + Math.round(i/numberOfSequenzes) );
                        seqDataBlock = my_replaceCharAt(seqDataBlock,i,'|');
                    }
            }
        }

        if(clickedRow >  (numberOfLayers/2)-1) n = '^';
        if(clickedRow <= (numberOfLayers/2)-1) n = 'v';
    }
    else {
        n = '.';
        // check whether the drill came from above and goes deeper still below
        if ((clickedRow > 0) && (clickedRow < numberOfLayers - 2) && (seqDataBlock.charAt(fixed_pos - numberOfSequenzes) != '.')) {
            remove_below = true;
        }
    }

    seqDataBlock = my_replaceCharAt(seqDataBlock,pos,n);
    seqDataBlock = my_drillUp(numberOfLayers, clickedColumn, clickedRow, seqDataBlock, true);
    seqDataBlock = my_drillDown(numberOfLayers, clickedColumn, clickedRow, seqDataBlock, true);

    if (remove_below) {
        var i = 0;
        // loop through the drill rows below clickedRow
        for (i = 1; i < numberOfLayers - 1 - clickedRow; i++) {
            // if there is a drill remove it
            if (seqDataBlock.charAt(fixed_pos + i * numberOfSequenzes) != '.') {
                seqDataBlock = my_replaceCharAt(seqDataBlock,fixed_pos + i * numberOfSequenzes,'.');
                seqDataBlock = my_drillUp(numberOfLayers, clickedColumn, clickedRow + i, seqDataBlock, true);
                seqDataBlock = my_drillDown(numberOfLayers, clickedColumn, clickedRow + i, seqDataBlock, true);
            }
        }
    }

    seqDataBlock = my_checkSingles(numberOfLayers, seqDataBlock);
    numberOfSequenzes = seqDataBlock.length/(numberOfLayers-1);
    add=false;

    for(i=0; i<seqDataBlock.length; i++){
        //  alert('i='+i+' numberOfSequenzes='+numberOfSequenzes+' i%numberOfSequenzes='+((i+1)%numberOfSequenzes));
        if(0==((i+1)%numberOfSequenzes) && seqDataBlock.charAt(i)!='.'){
        //      alert('adding, found char '+seqDataBlock.charAt(i));
        add=true;
        }
    }

    if(add){
        newSeqDataBlock = '';
        for(i=0; i<seqDataBlock.length; i++){
            newSeqDataBlock+=seqDataBlock.charAt(i);
            if(0==((i+1)%numberOfSequenzes)){
                newSeqDataBlock+='.';
            }
        }
        seqDataBlock=newSeqDataBlock;
        //    alert(newseqDataBlock);
    }

    //  alert('seqDataBlock=['+seqDataBlock+']');
    inp=document.getElementById('layersinput');
    inp.value = seqDataBlock;
    my_showLayers(numberOfLayers, seqDataBlock);
}

/*****************************************************************************
* xxx
*
*****************************************************************************/
function my_drillUp(l, x, y, data, init){
  var linelength=data.length/(l-1);
  pos=x+linelength*y;
  posupper=x+linelength*(y-1);
//  alert('x='+x+' y='+y+' pos='+pos+' posupper='+posupper);
  if(!init){
    data=my_replaceCharAt(data,pos,'|');
  }
  if(posupper>=0){
    if(data.charAt(posupper)!='.' && data.charAt(pos)!='.'){
        data=my_replaceCharAt(data,posupper,'|');
        data=my_replaceCharAt(data,pos,'|');
        data=my_drillUp(l, x, y-1, data, false);
      }
  }
  return data;
}
/*****************************************************************************
* xxx
*
*****************************************************************************/
function my_drillDown(l, x, y, data, init){
  var linelength=data.length/(l-1);
  pos=x+linelength*y;
  poslower=x+linelength*(y+1);
//  alert('x='+x+' y='+y+' pos='+pos+' posupper='+posupper);
  if(!init){
    data=my_replaceCharAt(data,pos,'|');
  }
  if(poslower<data.length){
    if(data.charAt(poslower)!='.' && data.charAt(pos)!='.'){
        data=my_replaceCharAt(data,poslower,'|');
        data=my_replaceCharAt(data,pos,'|');
        data=my_drillDown(l, x, y+1, data, false);
      }
  }
  return data;
}
/*****************************************************************************
* xxx
*
*****************************************************************************/
function my_checkSingles(l, data){
  var linelength=data.length/(l-1);
  for(x=0; x<linelength; x++){
    for(y=0; y<(l-1); y++){
      pos=x+linelength*y;
      if(y>(l/2)-1) n='^';
      if(y<=(l/2)-1) n='v';
      if(data.charAt(pos)=='|'){
        posupper=x+linelength*(y-1);
        poslower=x+linelength*(y+1);
        if( (posupper<0 || data.charAt(posupper)=='.') && (poslower>data.length || data.charAt(poslower)=='.')){
          data=my_replaceCharAt(data,pos,n);
        }
      }
    }
  }
  colcnt=new Array();
  for(x=0; x<linelength; x++){
    for(y=0; y<(l-1); y++){
      pos=x+linelength*y;
      if(data.charAt(pos)!='.'){
        if(colcnt[x]==undefined){
          colcnt[x]=1;
        } else {
          colcnt[x]++;
        }
      }
    }
  }
  for(x=linelength-2; x>=0; x--){
    if(colcnt[x]==undefined){
//alert('delete column '+x);
      data=my_deleteColumn(l, x, data);
      break;
    }
  }
  return data;
}
/*****************************************************************************
* xxx
*
*****************************************************************************/
function my_replaceCharAt(data, pos, newchar){
  data=data.substr(0,pos)+newchar+data.substr(pos+1,data.length-(pos+1));
  return data;
}
/*****************************************************************************
* xxx
*****************************************************************************/
function my_deleteColumn(l, x, data){
  var r=x;
  while(holes[r+1]!=undefined){
    holes[r]=holes[r+1];
    r++;
  }
  r=x;
  while(holesmin[r+1]!=undefined){
    holesmin[r]=holesmin[r+1];
    r++;
  }
  var linelength=data.length/(l-1);
  del='';
  for(i=(l-2)*linelength+x; i>=0; i-=linelength){
    del+=' '+i;
    data=my_replaceCharAt(data, i, '');
  }
  //alert(del);
  return data;
}

/*****************************************************************************
 * update size of container
 * - each sequenz add some pixel to container width to prevent line breaks
 * - get ccontainer objekt
*****************************************************************************/
function update_grafical_multilayer() {
    var container = document.getElementById("grafical_multilayer");
    // initialize width of container
    var container_length = 0;
    // set width: base + some pixel per sequenze
    if (linelength > 3) {
        var base_length = 42*3; // width of 3 sequenzes
        if(!hasClass(document.getElementById("layerAndThickness"),"dimmed")){
            base_length = base_length + 140;
        }
        container_length = base_length + 42 * (linelength+1) + 10;
        // set width of container
        container.style.width = container_length + "px";
    } else {
        // max width
        container.style.width = "625px";
    }
}
