package com.alexfu.formvalidator;

import android.support.v4.util.ArrayMap;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.TextView;

import com.alexfu.formvalidator.rules.ValidationRule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public abstract class AbsValidator<T> {
  private ArrayMap<TextView, List<ValidationRule>> ruleMap;
  private ArrayMap<TextWatcher, TextView> textWatchers;

  protected AbsValidator() {
    ruleMap = new ArrayMap<>();
    textWatchers = new ArrayMap<>();
  }

  protected void watchForTextChange(TextView view) {
    if (!textWatchers.containsValue(view)) {
      TextWatcher watcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
          // No op
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
          // No op
        }

        @Override
        public void afterTextChanged(Editable s) {
          TextView editText = textWatchers.get(this);
          validate(editText);
        }
      };

      view.addTextChangedListener(watcher);
      textWatchers.put(watcher, view);
    }
  }

  public void addRule(TextView view, List<ValidationRule> rules) {
    if (!ruleMap.containsKey(view)) {
      ruleMap.put(view, new ArrayList<ValidationRule>());
    }

    ruleMap.get(view).addAll(rules);
     watchForTextChange(view);
  }

  public void addRule(TextView view, ValidationRule...rules) {
    if (!ruleMap.containsKey(view)) {
      ruleMap.put(view, new ArrayList<ValidationRule>());
    }

    ruleMap.get(view).addAll(Arrays.asList(rules));
     watchForTextChange(view);
  }

  public T validate() {
    ValidationTask[] tasks = new ValidationTask[ruleMap.size()];
    for (int i = 0; i < tasks.length; i++) {
      TextView view = ruleMap.keyAt(i);
      List<ValidationRule> rules = ruleMap.get(view);
      tasks[i] = new ValidationTask(view, rules);
    }
    return performValidate(tasks);
  }

  public T validate(TextView view) {
    ValidationTask task = new ValidationTask(view, ruleMap.get(view));
    return performValidate(task);
  }

  protected abstract T performValidate(ValidationTask[] tasks);
  protected abstract T performValidate(ValidationTask task);
}

@@ -73,71 +73,8 @@
 ap;%0A
-import android.text.Editable;%0Aimport android.text.TextWatcher;%0A
 impo
@@ -101,16 +101,16 @@
 xtView;%0A
+
 %0Aimport 
@@ -337,64 +337,8 @@
 Map;
-%0A  private ArrayMap%3CTextWatcher, TextView%3E textWatchers;
 %0A%0A  
@@ -400,729 +400,8 @@
 ();%0A
-    textWatchers = new ArrayMap%3C%3E();%0A  %7D%0A%0A  protected void watchForTextChange(TextView view) %7B%0A    if (!textWatchers.containsValue(view)) %7B%0A      TextWatcher watcher = new TextWatcher() %7B%0A        @Override%0A        public void beforeTextChanged(CharSequence s, int start, int count, int after) %7B%0A          // No op%0A        %7D%0A%0A        @Override%0A        public void onTextChanged(CharSequence s, int start, int before, int count) %7B%0A          // No op%0A        %7D%0A%0A        @Override%0A        public void afterTextChanged(Editable s) %7B%0A          TextView editText = textWatchers.get(this);%0A          validate(editText);%0A        %7D%0A      %7D;%0A%0A      view.addTextChangedListener(watcher);%0A      textWatchers.put(watcher, view);%0A    %7D%0A
   %7D%0A
@@ -612,39 +612,8 @@
 s);%0A
-     watchForTextChange(view);%0A
   %7D%0A
@@ -771,32 +771,32 @@
 ule%3E());%0A    %7D%0A%0A
+
     ruleMap.get(
@@ -835,39 +835,8 @@
 ));%0A
-     watchForTextChange(view);%0A
   %7D%0A

Remove built in text watcher management