// Using Chain of responsability to detect the language.
// Each logic will have its class and the first that succeeds is used.

const Deduction = function(language, method){
  this.language = language;
  this.method = method;
}

export const LanguageDeducer = function(ad){
  this.ad = ad;
}

function deductionOrNull(value, method){
  if(!value){
    return null;
  }
  return new Deduction(value,method);
}

LanguageDeducer.prototype = {
  appendDeducer: function(deducer){
    this.deducerChain.append(deducer);
  },
  deduce: async function(){
    var context = {
      ad: this.ad,
      recipients: {
        to: await this.ad.getRecipients(),
        cc: await this.ad.getRecipients('cc')
      }
    };
    var deduction = null;
    for(const deducer of this.deducerChain) {
      deduction = await deducer(context);
      if(deduction) break;
    }
    return deduction;
  },
  deducerChain: [
    async function(context){
      const toandcc_key = context.ad.getKeyForRecipients(context.recipients);
      context.ad.logger.debug("Deducing language for: " + toandcc_key);
      const lang = await context.ad.getLangFor( toandcc_key );
      return deductionOrNull(lang, context.ad.METHODS.REMEMBER);
    },
    async function(context){
      const alltogether_key = context.ad.stringifyRecipientsGroup( context.recipients.to );
      const lang = await context.ad.getLangFor( alltogether_key );
      return deductionOrNull(lang, context.ad.METHODS.REMEMBER);
    },
    async function(context){
      var lang = null;
      for( const recipient of context.recipients.to ){
        lang = await context.ad.getLangFor( recipient );
        if( lang ){
          break;
        }
      }
      return deductionOrNull(lang, context.ad.METHODS.REMEMBER);
    },
    async function(context){
      var lang = null;
      for( const recipient of context.recipients.cc ){
        lang = await context.ad.getLangFor( recipient );
        if( lang ){
          break;
        }
      }
      return deductionOrNull(lang, context.ad.METHODS.REMEMBER);
    },
    async function(context){
      if(await context.ad.allowHeuristic()){
        const lang = await context.ad.heuristic_guess(context.recipients.to);
        return deductionOrNull(lang, context.ad.METHODS.GUESS);
      }
    }
  ]
}

@@ -283,16 +283,161 @@
 ad = ad;
+%0A%0A  this.deducerChain = %5B%0A    this.findByAllRecipients,%0A    this.findByTos,%0A    this.findByAnyTo,%0A    this.findByAnyCC,%0A    this.guessFromTos%0A  %5D
 %0A%7D%0A%0Afunc
@@ -583,88 +583,8 @@
 = %7B%0A
-  appendDeducer: function(deducer)%7B%0A    this.deducerChain.append(deducer);%0A  %7D,%0A
   de
@@ -948,29 +948,31 @@
  %7D,%0A
+%0A
   
-deducerChain: %5B%0A   
+findByAllRecipients:
  asy
@@ -974,32 +974,33 @@
 : async function
+ 
 (context)%7B%0A     
@@ -984,36 +984,35 @@
 nction (context)
+ 
 %7B%0A
-  
     const toandc
@@ -1071,18 +1071,16 @@
 ients);%0A
-  
     cont
@@ -1141,26 +1141,24 @@
 c_key);%0A    
-  
 const lang =
@@ -1186,17 +1186,16 @@
 LangFor(
- 
 toandcc_
@@ -1193,34 +1193,31 @@
 (toandcc_key
- 
 );%0A    
-  
 return deduc
@@ -1259,34 +1259,41 @@
 .REMEMBER);%0A
-  
   %7D,%0A  
- 
+findByTos:
  async funct
@@ -1302,26 +1302,24 @@
 n(context)%7B%0A
-  
     const al
@@ -1392,26 +1392,24 @@
 ients.to );%0A
-  
     const la
@@ -1461,26 +1461,24 @@
 _key );%0A    
-  
 return deduc
@@ -1520,34 +1520,43 @@
 .REMEMBER);%0A
-  
   %7D,%0A  
- 
+findByAnyTo:
  async funct
@@ -1561,34 +1561,32 @@
 ction(context)%7B%0A
-  
     var lang = n
@@ -1586,34 +1586,32 @@
 ang = null;%0A    
-  
 for( const recip
@@ -1639,26 +1639,24 @@
 ients.to )%7B%0A
-  
       lang =
@@ -1696,34 +1696,32 @@
 ipient );%0A      
- 
- 
 if( lang )%7B%0A    
@@ -1720,35 +1720,31 @@
  )%7B%0A        
-  
 break;%0A
-  
       %7D%0A    
@@ -1735,38 +1735,34 @@
 ak;%0A      %7D%0A    
-  %7D%0A  
+%7D%0A
     return deduc
@@ -1804,34 +1804,43 @@
 .REMEMBER);%0A
-  
   %7D,%0A  
- 
+findByAnyCC:
  async funct
@@ -1857,18 +1857,16 @@
 t)%7B%0A    
-  
 var lang
@@ -1874,18 +1874,16 @@
 = null;%0A
-  
     for(
@@ -1929,26 +1929,24 @@
 cc )%7B%0A      
- 
- 
 lang = await
@@ -1984,26 +1984,24 @@
 nt );%0A      
-  
 if( lang )%7B%0A
@@ -2004,26 +2004,24 @@
  )%7B%0A        
- 
- 
 break;%0A     
@@ -2025,22 +2025,16 @@
     
-  
 %7D%0A    
- 
- 
 %7D%0A
-  
     
@@ -2096,18 +2096,28 @@
 R);%0A
-  
   %7D,%0A  
- 
+guessFromTos:
  asy
@@ -2138,18 +2138,16 @@
 ntext)%7B%0A
-  
     if(a
@@ -2181,18 +2181,16 @@
 tic())%7B%0A
-  
       co
@@ -2263,18 +2263,16 @@
 ;%0A      
- 
- 
 return d
@@ -2327,20 +2327,12 @@
     
+%7D%0A
   %7D
-%0A    %7D%0A  %5D
 %0A%7D%0A

Improve readability by using named methods