var textCache = {};
String.Typography = function(text, cfg) {
  const {html} = cfg;
  if(typeof text !== 'string')
    return text;

  text = text.trim();
  if(text[0] === ',')text = text.substr(1);
  if(text[text.length-1] === ',')text = text.substr(0, text.length - 1);
  const income = text;
  if(text.split(/[«"»]/).length % 2 === 0){
    // odd count of quotes
    text = text.replace(/[«»]/,'')
  }

  let valids = {}, id = 1, add = (val)=>{
    const uid = '_!@#'+id+'#@!_';
    id++;
    valids[uid] = val;
    return uid;
  };

  text = text
    .trim()
    .replace(/\n\n/g,'|||||')
    .replace(/\s\s+/g,' ')
    .replace(/ /g,' ')

    .replace(/([а-я][-–—][0-9][-–—][а-я])/g, add)

    .replace(/(\d)(руб)/g,'$1 $2')
    //.replace(/([а-яА-Я])[—-]([а-яА-Я])/g, (full, a, b)=>add(a+'-'+b))
    .replace(/([а-яА-Я])[—-]([а-яА-Я])/g, (full, a, b)=>add(html?'<nobr>'+a+'-'+b+'</nobr>': a+'-'+b))
    .replace(/([0-9])[,]([0-9])/g, (full, a, b)=>add(a+','+b))



    .replace(/(ВкусВилл)/g, add)
    .replace(/([^\s])[—-]/g, '$1 —')
    .replace(/([,\.:])([а-яА-Я0-9\.,"])/g, '$1 $2')
    .replace(/\s([,\.:])/g, '$1')

    .replace(/([\(])\s/g, '$1')
    .replace(/[^\s]([\(])/g, ' $1')
    .replace(/[\s+]([\)])/g, '$1')

    .replace(/([а-я\?\.])(\d+\.)/g, '$1 $2')

    .replace(/ [-–—] /g, (html?'&nbsp;':' ')+'— ')

    .replace(/-(\d)/g, '–$1')

    .replace(/ (\d\. [а-яА-Я])/g, '\n$1')
    .replace(/"([а-яА-Я][^"]+)\s+"([а-яА-Я\s][^"]+)"\s+([а-яА-Я][^"]+)"/g,'«$1 “$2” $3»')

    .replace(/"([^"]+)"/g,'«$1»')
    .replace(/«\s+/g,'«')
    .replace(/\s+»/g,'»')
    .replace(/([а-я])([А-Я])/g,(ful, a, b)=>a+' '+b.toLowerCase())
    //.replace(/\. /g,'.&shy; ')

    // phone
    .replace(/(\+7|8)[\s\(]*(\d{3})[\s\)]*(\d{3})[\s\-—–]*(\d{2})[\s-—–]*(\d{2})/, html ?'+7&nbsp;($2)&nbsp;$3-$4-$5' : '+7 ($2) $3-$4-$5')

    .replace(/свершении/g,'совершении')


    [html?'replace':'trim'](/[А-Я]+/g, function(text) {
    return text.length > 2 || text === 'НЕ' ? '<span class="important">'+text.toLowerCase()+'</span>': text;
  })

    [html?'replace':'trim'](/, ([А-Я])/g, (f, a)=>', '+a.toLowerCase())
    .replace(/\|\|\|\|\|/g,'\n\n')
    [html?'replace':'trim'](/\*\*([^*]+)\*\*/g,'<span class="notificate-text">$1</span>')

  ;


  // HANGING
  /*

    text = text
      .replace(/([«(])/g,'<span class="before-hanging-open"></span>&shy;<span class="hanging-open">$1</span>')
      .replace(/([»)])/g,'<span class="hanging-close">$1</span>');
  */

  //<span class="hanging-close">»</span>');

  var lines = text.split('\n');
  var numberStarting = 0;
  var lastNumber = 0;
  var remake = [];
  lines.forEach(function(line) {

    line.replace(/^(\d+)\.\s/, function(full, num) {
      num = num-0;
      if(lastNumber !== num - 1){
        if(lastNumber>num){
          // ok
        }else{
          var text = remake.pop();
          while(lastNumber<num - 1){
            text.replace(new RegExp('[^\\d]'+(lastNumber+1)+'[^\\d]'), function(ful, pos,a){
              remake.push(text.substr(0, pos).replace(lastNumber+1, lastNumber+1+'.'))
              text = text.substr(pos+(lastNumber+1+'').length)
            });
            lastNumber++;
          }
          remake.push(text.replace(lastNumber, lastNumber+'.'));
        }
      }
      lastNumber = num;
    });
    remake.push(line);
  });

  var longSentance = 200;
  if(remake.length === 1 && remake[0].length>longSentance){
    remake = remake[ 0 ].split( '. ' ).map( a => a + '.' ).reduce((store, sentance)=>{
      var last = (store.pop()||'');
      if(last.length+sentance.length< longSentance*1.3){
        store.push([ last, sentance ].join( ' ' ));
      }else{
        if(last)
          store.push(last);
        store.push(sentance);
      }
      return store
    },[]);

    remake = [].concat.apply( [], remake.map( a => [ a, '' ] ));
  }




  let out = remake.length === 1 ? remake[0] : remake.map(a=>html?'<p>'+a+'</p>':a).join('\n');
  out = out.replace(/_!@#(\d+)#@!_/g, (f, num)=>{
    return valids[f]
  });
  out = out.trim();
  if(out.length>70)
    out = out[0].toUpperCase()+out.substr(1);
  /*console.log(income);
  console.log(out);*/

  return out;
};

String.Search = function(string, search) {
  var prepared = textCache[search];
  if(!prepared){
    var tokens = search.split(/\s/)
    textCache[search] = prepared = tokens
      .map(token => token[0] === '-' ? {has: false, text: token.substr(1)}: {has: true, text: token});
  }

  var yep = true;
  for( var i = 0, _i = prepared.length; i < _i; i++ ){
    var preparedElement = prepared[ i ];
    if(preparedElement.text === '')
      continue;
    var matched = string.indexOf(preparedElement.text)>-1;
    if(preparedElement.has === false && matched){
      return false
    }else if(preparedElement.has === true && !matched)
      yep = false;
  }

  return yep;
};