function complexComissionObj_afterComission(inval,last_comm)
{
   this.error = '';
   dbgMsg('complexComissionObj_afterComission('+inval+')');

   if (this.whopays == 0) // TODO: this works only when comission is growing from diapason to diapason
   {
       dbgMsg('complexComissionObj_afterComission: sender pays ');

       // first check direct hit into comission diapason
       for (i=0; i<this.n; i++)
       {
           dbgMsg('i: '+i+', from(i): '+this.arr[i].from_amount+', to(i): '+this.arr[i].to_amount+'\nrev(from): '+this.arr[i].reverseComission(this.arr[i].from_amount)+', rev(to): '+
                 this.arr[i].reverseComission(this.arr[i].to_amount)+', inval: '+inval);

           if ((this.arr[i].reverseComission(this.arr[i].from_amount,last_comm) <= inval && 
                this.arr[i].to_amount == 0) ||
               (this.arr[i].reverseComission(this.arr[i].from_amount,last_comm) <= inval && 
                this.arr[i].reverseComission(this.arr[i].to_amount,last_comm) >= inval)
               )
           {
               this.curr_comm = i;
               dbgMsg('got it: ' +inval + '=>'+ this.arr[this.curr_comm].toString());
               result = this.arr[this.curr_comm].afterComission(inval,last_comm);
               if ((result > this.arr[this.curr_comm].to_amount && this.arr[i].to_amount != 0) || 
                       result < this.arr[this.curr_comm].from_amount) {
                       this.curr_comm = -1;//i;
                   this.error = 'Извините, данную сумму нельзя перевести в связи с особенностями механизма расчета комиссий';//Внимание, получаемая сумма будет округлена до '+this.arr[i].to_amount;
                   return 0;        
               } else {
                   return result;
               }
           }
       }

       // now check intra-diapason gaps ( >1 diapason & reverseComission(to[i]) < reverseComission(from[i+1]) )
       for (i=0; i<this.n-1;i++)
       {
           dbgMsg('i: '+i+', to(i): '+this.arr[i].to_amount+', from(i+1): '+this.arr[i+1].from_amount+'\nrev(to): '+
                 this.arr[i].reverseComission(this.arr[i].to_amount)+', rev(from): '+this.arr[i+1].reverseComission(this.arr[i+1].from_amount)+', inval: '+inval);
           if (this.arr[i].to_amount != 0 &&
               this.arr[i].reverseComission(this.arr[i].to_amount,last_comm) <= inval && 
               this.arr[i+1].reverseComission(this.arr[i+1].from_amount,last_comm) >= inval
               )
           {
                   if (Math.abs(this.arr[i].to_amount-this.arr[i].afterComission(inval, last_comm))<0.001) {
                       this.curr_comm = i;
                       return this.arr[i].to_amount;
                   }
                   
               this.curr_comm = -1;//i;
               this.error = 'Извините, данную сумму нельзя перевести в связи с особенностями механизма расчета комиссий';//Внимание, получаемая сумма будет округлена до '+this.arr[i].to_amount;
               return 0;//this.arr[i].to_amount;
           }
       }

       this.curr_comm = -1;
       this.error = 'Извините, эту сумму нельзя перевести'; // TODO: fix this
       return 0;
   } else {
       for (i=0; i<this.n; i++)
       {
           dbgMsg('i: '+i+', from(i): '+this.arr[i].from_amount+', to(i): '+this.arr[i].to_amount+
                 ', inval: '+inval);

           if ((this.arr[i].from_amount <= inval && this.arr[i].to_amount == 0) ||
               (this.arr[i].from_amount <= inval && this.arr[i].to_amount >= inval) 
               )
           {
               this.curr_comm = i;
               dbgMsg('got it: ' +inval + '=>'+ this.arr[this.curr_comm].toString());
               return this.arr[this.curr_comm].afterComission(inval,last_comm);
           }
       } 

       // NB: extend borders for now, better use 
       if (this.arr[this.n-1].to_amount != 0 && this.arr[this.n-1].to_amount <= inval)
       {
           this.curr_comm = this.n-1;
           return this.arr[this.curr_comm].afterComission(inval,last_comm);
       }
       if (this.arr[0].from_amount >=0 && this.arr[0].from_amount >= inval && inval > 0)
       {
           this.curr_comm = 0;
           return this.arr[this.curr_comm].afterComission(inval,last_comm);
       }
       this.curr_comm = -1;
       return nullComission.afterComission(inval);
   }
}

function complexComissionObj_reverseComission(outval,last_comm)
{
   if (this.whopays == 0) // TODO: currently this works only when comission is growing from diapason to diapason
   {
       for (i=0; i<this.n; i++)
       {
           dbgMsg('i: '+i+', from(i): '+this.arr[i].from_amount+', to(i): '+this.arr[i].to_amount+
                 ', outval: '+outval);

           if ((this.arr[i].from_amount <= outval && this.arr[i].to_amount == 0) ||
               (this.arr[i].from_amount <= outval && this.arr[i].to_amount >= outval) 
               )
           {
               this.curr_comm = i;
               dbgMsg('got it: ' + outval + '=>'+ this.arr[this.curr_comm].toString());
               return this.arr[this.curr_comm].reverseComission(outval,last_comm);
           }
       } 

       // NB: extend borders for now, better use 
       if (this.arr[this.n-1].to_amount != 0 && this.arr[this.n-1].to_amount <= outval)
       {
           this.curr_comm = this.n-1;
           return this.arr[this.curr_comm].reverseComission(outval,last_comm);
       }
       if (this.arr[0].from_amount >=0 && this.arr[0].from_amount >= outval && outval > 0)
       {
           this.curr_comm = 0;
           return this.arr[this.curr_comm].reverseComission(outval,last_comm);
       }
       
       //this.curr_comm = -1;
       //return nullComission.reverseComission(outval);
       this.curr_comm = -1;
       this.error = 'Извините, эту сумму нельзя перевести'; // TODO: fix this
       return 0;
       
   } else {
       // first check direct hit into comission diapason
       for (i=0; i<this.n; i++)
       {
           dbgMsg('i: '+i+', from(i): '+this.arr[i].from_amount+', to(i): '+this.arr[i].to_amount+'\nrev(from): '+this.arr[i].reverseComission(this.arr[i].from_amount)+', rev(to): '+
                 this.arr[i].reverseComission(this.arr[i].to_amount,last_comm)+', outval: '+outval);

           if ((this.arr[i].reverseComission(this.arr[i].from_amount,last_comm) <= outval && 
                this.arr[i].to_amount == 0) ||
               (this.arr[i].reverseComission(this.arr[i].from_amount,last_comm) <= outval && 
                this.arr[i].reverseComission(this.arr[i].to_amount,last_comm) >= outval)
               )
           {
               this.curr_comm = i;
               dbgMsg('got it: ' +outval + '=>'+ this.arr[this.curr_comm].toString());
               return this.arr[this.curr_comm].reverseComission(outval,last_comm);
           }
       }

       // now check intra-diapason gaps ( >1 diapason & reverseComission(to[i]) < reverseComission(from[i+1]) )
       for (i=0; i<this.n-1;i++)
       {
           dbgMsg('i: '+i+', to(i): '+this.arr[i].to_amount+', from(i+1): '+this.arr[i+1].from_amount+'\nrev(to): '+
                 this.arr[i].reverseComission(this.arr[i].to_amount)+', rev(from): '+this.arr[i+1].reverseComission(this.arr[i+1].from_amount)+', outval: '+outval);
           if (this.arr[i].to_amount != 0 &&
               this.arr[i].reverseComission(this.arr[i].to_amount,last_comm) <= outval && 
               this.arr[i+1].reverseComission(this.arr[i+1].from_amount,last_comm) >= outval
               )
           {
               this.curr_comm = i;
               this.error = 'Внимание, отправляемая сумма будет округлена до '+this.arr[i].to_amount;
               return this.arr[i].to_amount;
           }
       }

       this.curr_comm = -1;
       this.error = 'Извините, эту сумму нельзя перевести'; // TODO: fix this
       return 0;
   }
}

function complexComissionObj_toString()
{
   return (this.curr_comm == -1)?nullComission.toString():this.arr[this.curr_comm].toString();
}

function complexComissionObj(arr, whopays)
{
   this.n = arr.length;
   this.arr = arr;
   this.whopays = whopays;
   this.curr_comm = -1;
   this.error = '';

//   this.toString         = complexComissionObj_toString;
   this.afterComission   = complexComissionObj_afterComission;
   this.reverseComission = complexComissionObj_reverseComission;
   this.hasError         = comissionObj_hasError;
   this.getError         = comissionObj_getError;

   return this;
}
