export class MaterializeFormValidationRenderer {

  className = 'md-input-validation';
  classNameFirst = 'md-input-validation-first';

  render(instruction) {
    for (let { error, elements } of instruction.unrender) {
      for (let element of elements) {
        this.remove(element, error);
      }
    }
    for (let { error, elements } of instruction.render) {
      for (let element of elements) {
        this.add(element, error);
      }
    }
  }

  add(element, error) {
    switch (element.tagName) {
    case 'MD-INPUT': {
      let label = element.querySelector('label');
      let input = element.querySelector('input') || element.querySelector('textarea');
      if (label) {
        label.removeAttribute('data-error');
      }
      if (input) {
        input.classList.remove('valid');
        input.classList.add('invalid');
        error.target = input;
        if (input.hasAttribute('data-show-errortext')) {
          this.addMessage(element, error);
        }
      }
      break;
    }
    case 'SELECT': {
      const selectWrapper = element.closest('.select-wrapper');
      if (!selectWrapper) {
        return;
      }
      let input = selectWrapper.querySelector('input');
      if (input) {
        input.classList.remove('valid');
        input.classList.add('invalid');
        error.target = input;
        if (!(input.hasAttribute('data-show-errortext') &&
            input.getAttribute('data-show-errortext') === 'false')) {
          this.addMessage(selectWrapper, error);
        }
      }
      break;
    }
    case 'INPUT' : {
      if (element.hasAttribute('md-datepicker')) {
        element.classList.remove('valid');
        element.classList.add('invalid');
        if (!(element.hasAttribute('data-show-errortext') &&
            element.getAttribute('data-show-errortext') === 'false')) {
          this.addMessage(element.parentNode, error);
        }
      }
      break;
    }
    default: break;
    }
  }

  remove(element, error) {
    switch (element.tagName) {
    case 'MD-INPUT': {
      this.removeMessage(element, error);

      let input = element.querySelector('input') || element.querySelector('textarea');
      if (input && element.querySelectorAll('.' + this.className).length === 0) {
        input.classList.remove('invalid');
        input.classList.add('valid');
      }
      break;
    }
    case 'SELECT': {
      const selectWrapper = element.closest('.select-wrapper');
      if (!selectWrapper) {
        return;
      }

      if ($(selectWrapper.parentElement).children().hasClass('md-input-validation') ) {
        this.removeMessage(selectWrapper.parentElement, error);
      } else {
        this.removeMessage(selectWrapper, error);
      }

      let input = selectWrapper.querySelector('input');
      if (input && selectWrapper.querySelectorAll('.' + this.className).length === 0) {
        input.classList.remove('invalid');
        input.classList.add('valid');
      }
      break;
    }
    case 'INPUT' : {
      if (element.hasAttribute('md-datepicker')) {
        this.removeMessage(element.parentNode, error);
        if (element && element.parentNode.querySelectorAll('.' + this.className).length === 0) {
          element.classList.remove('invalid');
          element.classList.add('valid');
        }
      }
      break;
    }
    default: break;
    }
  }

  addMessage(element, error) {
    let message = document.createElement('div');
    message.id = `md-input-validation-${error.id}`;
    message.textContent = error.message;
    message.className = this.className;
    if (element.querySelectorAll('.' + this.className).length === 0) {
      message.className += ' ' + this.classNameFirst;
    }
    message.style.opacity = 0;
    element.appendChild(message, element.nextSibling);
    window.getComputedStyle(message).opacity;
    message.style.opacity = 1;
  }

  removeMessage(element, error) {
    let message = element.querySelector(`#md-input-validation-${error.id}`);
    if (message) {
      element.removeChild(message);
    }
  }

}

@@ -160,37 +160,38 @@
 %0A    for (let %7B 
-error
+result
 , elements %7D of 
@@ -273,37 +273,38 @@
 remove(element, 
-error
+result
 );%0A      %7D%0A    %7D
@@ -319,21 +319,22 @@
  (let %7B 
-error
+result
 , elemen
@@ -419,37 +419,38 @@
 is.add(element, 
-error
+result
 );%0A      %7D%0A    %7D
@@ -466,32 +466,77 @@
 dd(element, 
-error) %7B
+result) %7B%0A    if (result.valid) %7B%0A      return;%0A    %7D
 %0A    switch 
@@ -887,37 +887,38 @@
 alid');%0A        
-error
+result
 .target = input;
@@ -1002,37 +1002,38 @@
 essage(element, 
-error
+result
 );%0A        %7D%0A   
@@ -1357,21 +1357,22 @@
         
-error
+result
 .target 
@@ -1542,37 +1542,38 @@
 (selectWrapper, 
-error
+result
 );%0A        %7D%0A   
@@ -1924,37 +1924,38 @@
 ent.parentNode, 
-error
+result
 );%0A        %7D%0A   
@@ -2023,32 +2023,77 @@
 ve(element, 
-error) %7B
+result) %7B%0A    if (result.valid) %7B%0A      return;%0A    %7D
 %0A    switch 
@@ -2169,21 +2169,22 @@
 lement, 
-error
+result
 );%0A%0A    
@@ -2738,21 +2738,22 @@
 lement, 
-error
+result
 );%0A     
@@ -2804,21 +2804,22 @@
 rapper, 
-error
+result
 );%0A     
@@ -3193,21 +3193,22 @@
 ntNode, 
-error
+result
 );%0A     
@@ -3470,37 +3470,38 @@
 essage(element, 
-error
+result
 ) %7B%0A    let mess
@@ -3573,29 +3573,30 @@
 alidation-$%7B
-error
+result
 .id%7D%60;%0A    m
@@ -3616,21 +3616,22 @@
 ntent = 
-error
+result
 .message
@@ -3996,21 +3996,22 @@
 lement, 
-error
+result
 ) %7B%0A    
@@ -4070,21 +4070,22 @@
 ation-$%7B
-error
+result
 .id%7D%60);%0A

Update validationRenderer to comply with aurelia-validation@1.0.0