package org.mwg.plugin;

import org.mwg.Type;

import java.util.HashMap;
import java.util.Map;

public class Enforcer {

    private final Map<String, EnforcerChecker> checkers = new HashMap<String, EnforcerChecker>();

    public Enforcer asBool(String propertyName) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                if (input != null && inputType != Type.BOOL) {
                    throw new RuntimeException("Property " + propertyName + " should be long value, currently " + input);
                }
            }
        });
    }

    public Enforcer asString(String propertyName) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                if (input != null && inputType != Type.STRING) {
                    throw new RuntimeException("Property " + propertyName + " should be long value, currently " + input);
                }
            }
        });
    }

    public Enforcer asLong(String propertyName) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                if (input != null && inputType != Type.LONG && inputType != Type.INT) {
                    throw new RuntimeException("Property " + propertyName + " should be long value, currently " + input);
                }
            }
        });
    }

    public Enforcer asLongWithin(String propertyName, long min, long max) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                long inputDouble = (long) input;
                if (input != null && ((inputType != Type.LONG && inputType != Type.INT) || inputDouble < min || inputDouble > max)) {
                    throw new RuntimeException("Property " + propertyName + " should be long value [" + min + "," + max + "], currently " + input);
                }
            }
        });
    }

    public Enforcer asDouble(String propertyName) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                if (input != null && inputType != Type.DOUBLE) {
                    throw new RuntimeException("Property " + propertyName + " should be double value, currently " + input);
                }
            }
        });
    }

    public Enforcer asDoubleWithin(String propertyName, double min, double max) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                double inputDouble = (double) input;
                if (input != null && (inputType != Type.DOUBLE || inputDouble < min || inputDouble > max)) {
                    throw new RuntimeException("Property " + propertyName + " should be double value [" + min + "," + max + "], currently " + input);
                }
            }
        });
    }

    public Enforcer asInt(String propertyName) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                if (input != null && inputType != Type.INT && inputType != Type.LONG) {
                    throw new RuntimeException("Property " + propertyName + " should be integer value, currently " + input);
                }
            }
        });
    }

    public Enforcer asIntWithin(String propertyName, int min, int max) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                int inputDouble = (int) input;
                if (input != null && ((inputType != Type.INT && inputType != Type.LONG) || inputDouble < min || inputDouble > max)) {
                    throw new RuntimeException("Property " + propertyName + " should be integer value [" + min + "," + max + "], currently " + input);
                }
            }
        });
    }

    public Enforcer asDoubleArray(String propertyName) {
        return declare(propertyName, new EnforcerChecker() {
            @Override
            public void check(byte inputType, Object input) throws RuntimeException {
                if (input != null && inputType != Type.DOUBLE_ARRAY) {
                    throw new RuntimeException("Property " + propertyName + " should be doubleArray value, currently " + input);
                }
            }
        });
    }

    public Enforcer declare(String propertyName, EnforcerChecker checker) {
        this.checkers.put(propertyName, checker);
        return this;
    }

    public void check(String propertyName, byte propertyType, Object propertyValue) {
        EnforcerChecker checker = checkers.get(propertyName);
        if (checker != null) {
            checker.check(propertyType, propertyValue);
        }
    }

}

@@ -575,36 +575,39 @@
 e + %22 should be 
-long
+Boolean
  value, currentl
@@ -1037,34 +1037,36 @@
 e + %22 should be 
-lo
+Stri
 ng value, curren
@@ -4890,32 +4890,1007 @@
      %7D);%0A    %7D%0A%0A
+    public Enforcer asPositiveInt(String propertyName) %7B%0A        return declare(propertyName, new EnforcerChecker() %7B%0A            @Override%0A            public void check(byte inputType, Object input) throws RuntimeException %7B%0A                if (input != null && inputType != Type.INT && inputType%3C=0) %7B%0A                    throw new RuntimeException(%22Property %22 + propertyName + %22 should be a positive integer, currently %22 + input);%0A                %7D%0A            %7D%0A        %7D);%0A    %7D%0A%0A    public Enforcer asPositiveDouble(String propertyName) %7B%0A        return declare(propertyName, new EnforcerChecker() %7B%0A            @Override%0A            public void check(byte inputType, Object input) throws RuntimeException %7B%0A                if (input != null && inputType != Type.DOUBLE && inputType%3C=0) %7B%0A                    throw new RuntimeException(%22Property %22 + propertyName + %22 should be a positive double, currently %22 + input);%0A                %7D%0A            %7D%0A        %7D);%0A    %7D%0A%0A
     public Enfor

Update enforcer