/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.provider;

import android.content.ComponentName;
import android.net.Uri;

import com.android.internal.util.ArrayUtils;

import java.util.Locale;

/**
 * This class provides both interface for validation and common validators
 * used to ensure Settings have meaningful values.
 *
 * @hide
 */
public class SettingsValidators {

    public static final Validator BOOLEAN_VALIDATOR =
            new DiscreteValueValidator(new String[] {"0", "1"});

    public static final Validator ANY_STRING_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            return true;
        }
    };

    public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            try {
                return Integer.parseInt(value) >= 0;
            } catch (NumberFormatException e) {
                return false;
            }
        }
    };

    public static final Validator ANY_INTEGER_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            try {
                Integer.parseInt(value);
                return true;
            } catch (NumberFormatException e) {
                return false;
            }
        }
    };

    public static final Validator URI_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            try {
                Uri.decode(value);
                return true;
            } catch (IllegalArgumentException e) {
                return false;
            }
        }
    };

    public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            return ComponentName.unflattenFromString(value) != null;
        }
    };

    public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            return value != null && isStringPackageName(value);
        }

        private boolean isStringPackageName(String value) {
            // The name may contain uppercase or lowercase letters ('A' through 'Z'), numbers,
            // and underscores ('_'). However, individual package name parts may only
            // start with letters.
            // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package)
            if (value == null) {
                return false;
            }
            String[] subparts = value.split("\\.");
            boolean isValidPackageName = true;
            for (String subpart : subparts) {
                isValidPackageName |= isSubpartValidForPackageName(subpart);
                if (!isValidPackageName) break;
            }
            return isValidPackageName;
        }

        private boolean isSubpartValidForPackageName(String subpart) {
            if (subpart.length() == 0) return false;
            boolean isValidSubpart = Character.isLetter(subpart.charAt(0));
            for (int i = 1; i < subpart.length(); i++) {
                isValidSubpart |= (Character.isLetterOrDigit(subpart.charAt(i))
                                || (subpart.charAt(i) == '_'));
                if (!isValidSubpart) break;
            }
            return isValidSubpart;
        }
    };

    public static final Validator LENIENT_IP_ADDRESS_VALIDATOR = new Validator() {
        private static final int MAX_IPV6_LENGTH = 45;

        @Override
        public boolean validate(String value) {
            if (value == null) {
                return false;
            }
            return value.length() <= MAX_IPV6_LENGTH;
        }
    };

    public static final Validator LOCALE_VALIDATOR = new Validator() {
        @Override
        public boolean validate(String value) {
            if (value == null) {
                return false;
            }
            Locale[] validLocales = Locale.getAvailableLocales();
            for (Locale locale : validLocales) {
                if (value.equals(locale.toString())) {
                    return true;
                }
            }
            return false;
        }
    };

    public interface Validator {
        boolean validate(String value);
    }

    public static final class DiscreteValueValidator implements Validator {
        private final String[] mValues;

        public DiscreteValueValidator(String[] values) {
            mValues = values;
        }

        @Override
        public boolean validate(String value) {
            return ArrayUtils.contains(mValues, value);
        }
    }

    public static final class InclusiveIntegerRangeValidator implements Validator {
        private final int mMin;
        private final int mMax;

        public InclusiveIntegerRangeValidator(int min, int max) {
            mMin = min;
            mMax = max;
        }

        @Override
        public boolean validate(String value) {
            try {
                final int intValue = Integer.parseInt(value);
                return intValue >= mMin && intValue <= mMax;
            } catch (NumberFormatException e) {
                return false;
            }
        }
    }

    public static final class InclusiveFloatRangeValidator implements Validator {
        private final float mMin;
        private final float mMax;

        public InclusiveFloatRangeValidator(float min, float max) {
            mMin = min;
            mMax = max;
        }

        @Override
        public boolean validate(String value) {
            try {
                final float floatValue = Float.parseFloat(value);
                return floatValue >= mMin && floatValue <= mMax;
            } catch (NumberFormatException e) {
                return false;
            }
        }
    }

    public static final class ComponentNameListValidator implements Validator {
        private final String mSeparator;

        public ComponentNameListValidator(String separator) {
            mSeparator = separator;
        }

        @Override
        public boolean validate(String value) {
            if (value == null) {
                return false;
            }
            String[] elements = value.split(mSeparator);
            for (String element : elements) {
                if (!COMPONENT_NAME_VALIDATOR.validate(element)) {
                    return false;
                }
            }
            return true;
        }
    }

    public static final class PackageNameListValidator implements Validator {
        private final String mSeparator;

        public PackageNameListValidator(String separator) {
            mSeparator = separator;
        }

        @Override
        public boolean validate(String value) {
            if (value == null) {
                return false;
            }
            String[] elements = value.split(mSeparator);
            for (String element : elements) {
                if (!PACKAGE_NAME_VALIDATOR.validate(element)) {
                    return false;
                }
            }
            return true;
        }
    }
}
