/*
 * Copyright (C) 2016 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.app.admin;

import static android.app.admin.DevicePolicyManager.MAX_PASSWORD_LENGTH;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;

import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
import static com.android.internal.widget.LockPatternUtils.MIN_LOCK_PASSWORD_SIZE;
import static com.android.internal.widget.PasswordValidationError.CONTAINS_INVALID_CHARACTERS;
import static com.android.internal.widget.PasswordValidationError.CONTAINS_SEQUENCE;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_DIGITS;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_LETTERS;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_LOWER_CASE;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_NON_DIGITS;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_NON_LETTER;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_SYMBOLS;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_UPPER_CASE;
import static com.android.internal.widget.PasswordValidationError.TOO_LONG;
import static com.android.internal.widget.PasswordValidationError.TOO_SHORT;
import static com.android.internal.widget.PasswordValidationError.WEAK_CREDENTIAL_TYPE;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager.PasswordComplexity;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.android.internal.widget.LockPatternUtils.CredentialType;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.PasswordValidationError;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * A class that represents the metrics of a credential that are used to decide whether or not a
 * credential meets the requirements.
 *
 * {@hide}
 */
public final class PasswordMetrics implements Parcelable {
    private static final String TAG = "PasswordMetrics";

    // Maximum allowed number of repeated or ordered characters in a sequence before we'll
    // consider it a complex PIN/password.
    public static final int MAX_ALLOWED_SEQUENCE = 3;

    // One of CREDENTIAL_TYPE_NONE, CREDENTIAL_TYPE_PATTERN or CREDENTIAL_TYPE_PASSWORD.
    // Note that this class still uses CREDENTIAL_TYPE_PASSWORD to represent both numeric PIN
    // and alphabetic password. This is OK as long as this definition is only used internally,
    // and the value never gets mixed up with credential types from other parts of the framework.
    // TODO: fix this (ideally after we move logic to PasswordPolicy)
    public @CredentialType int credType;
    // Fields below only make sense when credType is PASSWORD.
    public int length = 0;
    public int letters = 0;
    public int upperCase = 0;
    public int lowerCase = 0;
    public int numeric = 0;
    public int symbols = 0;
    public int nonLetter = 0;
    public int nonNumeric = 0;
    // MAX_VALUE is the most relaxed value, any sequence is ok, e.g. 123456789. 4 would forbid it.
    public int seqLength = Integer.MAX_VALUE;

    public PasswordMetrics(int credType) {
        this.credType = credType;
    }

    public PasswordMetrics(int credType , int length, int letters, int upperCase, int lowerCase,
            int numeric, int symbols, int nonLetter, int nonNumeric, int seqLength) {
        this.credType = credType;
        this.length = length;
        this.letters = letters;
        this.upperCase = upperCase;
        this.lowerCase = lowerCase;
        this.numeric = numeric;
        this.symbols = symbols;
        this.nonLetter = nonLetter;
        this.nonNumeric = nonNumeric;
        this.seqLength = seqLength;
    }

    private PasswordMetrics(PasswordMetrics other) {
        this(other.credType, other.length, other.letters, other.upperCase, other.lowerCase,
                other.numeric, other.symbols, other.nonLetter, other.nonNumeric, other.seqLength);
    }

    /**
     * Returns {@code complexityLevel} or {@link DevicePolicyManager#PASSWORD_COMPLEXITY_NONE}
     * if {@code complexityLevel} is not valid.
     *
     * TODO: move to PasswordPolicy
     */
    @PasswordComplexity
    public static int sanitizeComplexityLevel(@PasswordComplexity int complexityLevel) {
        switch (complexityLevel) {
            case PASSWORD_COMPLEXITY_HIGH:
            case PASSWORD_COMPLEXITY_MEDIUM:
            case PASSWORD_COMPLEXITY_LOW:
            case PASSWORD_COMPLEXITY_NONE:
                return complexityLevel;
            default:
                Log.w(TAG, "Invalid password complexity used: " + complexityLevel);
                return PASSWORD_COMPLEXITY_NONE;
        }
    }

    private static boolean hasInvalidCharacters(byte[] password) {
        // Allow non-control Latin-1 characters only.
        for (byte b : password) {
            char c = (char) b;
            if (c < 32 || c > 127) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(credType);
        dest.writeInt(length);
        dest.writeInt(letters);
        dest.writeInt(upperCase);
        dest.writeInt(lowerCase);
        dest.writeInt(numeric);
        dest.writeInt(symbols);
        dest.writeInt(nonLetter);
        dest.writeInt(nonNumeric);
        dest.writeInt(seqLength);
    }

    public static final @NonNull Parcelable.Creator<PasswordMetrics> CREATOR
            = new Parcelable.Creator<PasswordMetrics>() {
                @Override
                public PasswordMetrics createFromParcel(Parcel in) {
                    int credType = in.readInt();
                    int length = in.readInt();
                    int letters = in.readInt();
                    int upperCase = in.readInt();
                    int lowerCase = in.readInt();
                    int numeric = in.readInt();
                    int symbols = in.readInt();
                    int nonLetter = in.readInt();
                    int nonNumeric = in.readInt();
                    int seqLength = in.readInt();
                    return new PasswordMetrics(credType, length, letters, upperCase, lowerCase,
                            numeric, symbols, nonLetter, nonNumeric, seqLength);
                }

                @Override
                public PasswordMetrics[] newArray(int size) {
                    return new PasswordMetrics[size];
                }
    };

    /**
     * Returns the {@code PasswordMetrics} for a given credential.
     *
     * If the credential is a pin or a password, equivalent to {@link #computeForPassword(byte[])}.
     * {@code credential} cannot be null when {@code type} is
     * {@link com.android.internal.widget.LockPatternUtils#CREDENTIAL_TYPE_PASSWORD}.
     */
    public static PasswordMetrics computeForCredential(LockscreenCredential credential) {
        if (credential.isPassword() || credential.isPin()) {
            return PasswordMetrics.computeForPassword(credential.getCredential());
        } else if (credential.isPattern())  {
            return new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
        } else if (credential.isNone()) {
            return new PasswordMetrics(CREDENTIAL_TYPE_NONE);
        } else {
            throw new IllegalArgumentException("Unknown credential type " + credential.getType());
        }
    }

    /**
     * Returns the {@code PasswordMetrics} for a given password
     */
    public static PasswordMetrics computeForPassword(@NonNull byte[] password) {
        // Analyse the characters used
        int letters = 0;
        int upperCase = 0;
        int lowerCase = 0;
        int numeric = 0;
        int symbols = 0;
        int nonLetter = 0;
        int nonNumeric = 0;
        final int length = password.length;
        for (byte b : password) {
            switch (categoryChar((char) b)) {
                case CHAR_LOWER_CASE:
                    letters++;
                    lowerCase++;
                    nonNumeric++;
                    break;
                case CHAR_UPPER_CASE:
                    letters++;
                    upperCase++;
                    nonNumeric++;
                    break;
                case CHAR_DIGIT:
                    numeric++;
                    nonLetter++;
                    break;
                case CHAR_SYMBOL:
                    symbols++;
                    nonLetter++;
                    nonNumeric++;
                    break;
            }
        }

        final int seqLength = maxLengthSequence(password);
        return new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD, length, letters, upperCase, lowerCase,
                numeric, symbols, nonLetter, nonNumeric, seqLength);
    }

    /**
     * Returns the maximum length of a sequential characters. A sequence is defined as
     * monotonically increasing characters with a constant interval or the same character repeated.
     *
     * For example:
     * maxLengthSequence("1234") == 4
     * maxLengthSequence("13579") == 5
     * maxLengthSequence("1234abc") == 4
     * maxLengthSequence("aabc") == 3
     * maxLengthSequence("qwertyuio") == 1
     * maxLengthSequence("@ABC") == 3
     * maxLengthSequence(";;;;") == 4 (anything that repeats)
     * maxLengthSequence(":;<=>") == 1  (ordered, but not composed of alphas or digits)
     *
     * @param bytes the pass
     * @return the number of sequential letters or digits
     */
    public static int maxLengthSequence(@NonNull byte[] bytes) {
        if (bytes.length == 0) return 0;
        char previousChar = (char) bytes[0];
        @CharacterCatagory int category = categoryChar(previousChar); //current sequence category
        int diff = 0; //difference between two consecutive characters
        boolean hasDiff = false; //if we are currently targeting a sequence
        int maxLength = 0; //maximum length of a sequence already found
        int startSequence = 0; //where the current sequence started
        for (int current = 1; current < bytes.length; current++) {
            char currentChar = (char) bytes[current];
            @CharacterCatagory int categoryCurrent = categoryChar(currentChar);
            int currentDiff = (int) currentChar - (int) previousChar;
            if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
                maxLength = Math.max(maxLength, current - startSequence);
                startSequence = current;
                hasDiff = false;
                category = categoryCurrent;
            }
            else {
                if(hasDiff && currentDiff != diff) {
                    maxLength = Math.max(maxLength, current - startSequence);
                    startSequence = current - 1;
                }
                diff = currentDiff;
                hasDiff = true;
            }
            previousChar = currentChar;
        }
        maxLength = Math.max(maxLength, bytes.length - startSequence);
        return maxLength;
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "CHAR_" }, value = {
            CHAR_UPPER_CASE,
            CHAR_LOWER_CASE,
            CHAR_DIGIT,
            CHAR_SYMBOL
    })
    private @interface CharacterCatagory {}
    private static final int CHAR_LOWER_CASE = 0;
    private static final int CHAR_UPPER_CASE = 1;
    private static final int CHAR_DIGIT = 2;
    private static final int CHAR_SYMBOL = 3;

    @CharacterCatagory
    private static int categoryChar(char c) {
        if ('a' <= c && c <= 'z') return CHAR_LOWER_CASE;
        if ('A' <= c && c <= 'Z') return CHAR_UPPER_CASE;
        if ('0' <= c && c <= '9') return CHAR_DIGIT;
        return CHAR_SYMBOL;
    }

    private static int maxDiffCategory(@CharacterCatagory int category) {
        switch (category) {
            case CHAR_LOWER_CASE:
            case CHAR_UPPER_CASE:
                return 1;
            case CHAR_DIGIT:
                return 10;
            default:
                return 0;
        }
    }

    /**
     * Returns the weakest metrics that is stricter or equal to all given metrics.
     *
     * TODO: move to PasswordPolicy
     */
    public static PasswordMetrics merge(List<PasswordMetrics> metrics) {
        PasswordMetrics result = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
        for (PasswordMetrics m : metrics) {
            result.maxWith(m);
        }

        return result;
    }

    /**
     * Makes current metric at least as strong as {@code other} in every criterion.
     *
     * TODO: move to PasswordPolicy
     */
    public void maxWith(PasswordMetrics other) {
        credType = Math.max(credType, other.credType);
        if (credType != CREDENTIAL_TYPE_PASSWORD) {
            return;
        }
        length = Math.max(length, other.length);
        letters = Math.max(letters, other.letters);
        upperCase = Math.max(upperCase, other.upperCase);
        lowerCase = Math.max(lowerCase, other.lowerCase);
        numeric = Math.max(numeric, other.numeric);
        symbols = Math.max(symbols, other.symbols);
        nonLetter = Math.max(nonLetter, other.nonLetter);
        nonNumeric = Math.max(nonNumeric, other.nonNumeric);
        seqLength = Math.min(seqLength, other.seqLength);
    }

    /**
     * Returns minimum password quality for a given complexity level.
     *
     * TODO: this function is used for determining allowed credential types, so it should return
     * credential type rather than 'quality'.
     *
     * TODO: move to PasswordPolicy
     */
    public static int complexityLevelToMinQuality(int complexity) {
        switch (complexity) {
            case PASSWORD_COMPLEXITY_HIGH:
            case PASSWORD_COMPLEXITY_MEDIUM:
                return PASSWORD_QUALITY_NUMERIC_COMPLEX;
            case PASSWORD_COMPLEXITY_LOW:
                return PASSWORD_QUALITY_SOMETHING;
            case PASSWORD_COMPLEXITY_NONE:
            default:
                return PASSWORD_QUALITY_UNSPECIFIED;
        }
    }

    /**
     * Enum representing requirements for each complexity level.
     *
     * TODO: move to PasswordPolicy
     */
    private enum ComplexityBucket {
        // Keep ordered high -> low.
        BUCKET_HIGH(PASSWORD_COMPLEXITY_HIGH) {
            @Override
            boolean canHaveSequence() {
                return false;
            }

            @Override
            int getMinimumLength(boolean containsNonNumeric) {
                return containsNonNumeric ? 6 : 8;
            }

            @Override
            boolean allowsNumericPassword() {
                return false;
            }

            @Override
            boolean allowsCredType(int credType) {
                return credType == CREDENTIAL_TYPE_PASSWORD;
            }
        },
        BUCKET_MEDIUM(PASSWORD_COMPLEXITY_MEDIUM) {
            @Override
            boolean canHaveSequence() {
                return false;
            }

            @Override
            int getMinimumLength(boolean containsNonNumeric) {
                return 4;
            }

            @Override
            boolean allowsNumericPassword() {
                return false;
            }

            @Override
            boolean allowsCredType(int credType) {
                return credType == CREDENTIAL_TYPE_PASSWORD;
            }
        },
        BUCKET_LOW(PASSWORD_COMPLEXITY_LOW) {
            @Override
            boolean canHaveSequence() {
                return true;
            }

            @Override
            int getMinimumLength(boolean containsNonNumeric) {
                return 0;
            }

            @Override
            boolean allowsNumericPassword() {
                return true;
            }

            @Override
            boolean allowsCredType(int credType) {
                return credType != CREDENTIAL_TYPE_NONE;
            }
        },
        BUCKET_NONE(PASSWORD_COMPLEXITY_NONE) {
            @Override
            boolean canHaveSequence() {
                return true;
            }

            @Override
            int getMinimumLength(boolean containsNonNumeric) {
                return 0;
            }

            @Override
            boolean allowsNumericPassword() {
                return true;
            }

            @Override
            boolean allowsCredType(int credType) {
                return true;
            }
        };

        int mComplexityLevel;

        abstract boolean canHaveSequence();
        abstract int getMinimumLength(boolean containsNonNumeric);
        abstract boolean allowsNumericPassword();
        abstract boolean allowsCredType(int credType);

        ComplexityBucket(int complexityLevel) {
            this.mComplexityLevel = complexityLevel;
        }

        static ComplexityBucket forComplexity(int complexityLevel) {
            for (ComplexityBucket bucket : values()) {
                if (bucket.mComplexityLevel == complexityLevel) {
                    return bucket;
                }
            }
            throw new IllegalArgumentException("Invalid complexity level: " + complexityLevel);
        }
    }

    /**
     * Returns whether current metrics satisfies a given complexity bucket.
     *
     * TODO: move inside ComplexityBucket.
     */
    private boolean satisfiesBucket(ComplexityBucket bucket) {
        if (!bucket.allowsCredType(credType)) {
            return false;
        }
        if (credType != CREDENTIAL_TYPE_PASSWORD) {
            return true;
        }
        return (bucket.canHaveSequence() || seqLength <= MAX_ALLOWED_SEQUENCE)
                && length >= bucket.getMinimumLength(nonNumeric > 0 /* hasNonNumeric */);
    }

    /**
     * Returns the maximum complexity level satisfied by password with this metrics.
     *
     * TODO: move inside ComplexityBucket.
     */
    public int determineComplexity() {
        for (ComplexityBucket bucket : ComplexityBucket.values()) {
            if (satisfiesBucket(bucket)) {
                return bucket.mComplexityLevel;
            }
        }
        throw new IllegalStateException("Failed to figure out complexity for a given metrics");
    }

    /**
     * Validates password against minimum metrics and complexity.
     *
     * @param adminMetrics - minimum metrics to satisfy admin requirements.
     * @param minComplexity - minimum complexity imposed by the requester.
     * @param isPin - whether it is PIN that should be only digits
     * @param password - password to validate.
     * @return a list of password validation errors. An empty list means the password is OK.
     *
     * TODO: move to PasswordPolicy
     */
    public static List<PasswordValidationError> validatePassword(
            PasswordMetrics adminMetrics, int minComplexity, boolean isPin, byte[] password) {

        if (hasInvalidCharacters(password)) {
            return Collections.singletonList(
                    new PasswordValidationError(CONTAINS_INVALID_CHARACTERS, 0));
        }

        final PasswordMetrics enteredMetrics = computeForPassword(password);
        return validatePasswordMetrics(adminMetrics, minComplexity, isPin, enteredMetrics);
    }

    /**
     * Validates password metrics against minimum metrics and complexity
     *
     * @param adminMetrics - minimum metrics to satisfy admin requirements.
     * @param minComplexity - minimum complexity imposed by the requester.
     * @param isPin - whether it is PIN that should be only digits
     * @param actualMetrics - metrics for password to validate.
     * @return a list of password validation errors. An empty list means the password is OK.
     *
     * TODO: move to PasswordPolicy
     */
    public static List<PasswordValidationError> validatePasswordMetrics(
            PasswordMetrics adminMetrics, int minComplexity, boolean isPin,
            PasswordMetrics actualMetrics) {
        final ComplexityBucket bucket = ComplexityBucket.forComplexity(minComplexity);

        // Make sure credential type is satisfactory.
        // TODO: stop relying on credential type ordering.
        if (actualMetrics.credType < adminMetrics.credType
                || !bucket.allowsCredType(actualMetrics.credType)) {
            return Collections.singletonList(new PasswordValidationError(WEAK_CREDENTIAL_TYPE, 0));
        }
        // TODO: this needs to be modified if CREDENTIAL_TYPE_PIN is added.
        if (actualMetrics.credType != CREDENTIAL_TYPE_PASSWORD) {
            return Collections.emptyList(); // Nothing to check for pattern or none.
        }

        if (isPin && actualMetrics.nonNumeric > 0) {
            return Collections.singletonList(
                    new PasswordValidationError(CONTAINS_INVALID_CHARACTERS, 0));
        }

        final ArrayList<PasswordValidationError> result = new ArrayList<>();
        if (actualMetrics.length > MAX_PASSWORD_LENGTH) {
            result.add(new PasswordValidationError(TOO_LONG, MAX_PASSWORD_LENGTH));
        }

        final PasswordMetrics minMetrics = applyComplexity(adminMetrics, isPin, bucket);

        // Clamp required length between maximum and minimum valid values.
        minMetrics.length = Math.min(MAX_PASSWORD_LENGTH,
                Math.max(minMetrics.length, MIN_LOCK_PASSWORD_SIZE));
        minMetrics.removeOverlapping();

        comparePasswordMetrics(minMetrics, actualMetrics, result);

        return result;
    }

    /**
     * TODO: move to PasswordPolicy
     */
    private static void comparePasswordMetrics(PasswordMetrics minMetrics,
            PasswordMetrics actualMetrics, ArrayList<PasswordValidationError> result) {
        if (actualMetrics.length < minMetrics.length) {
            result.add(new PasswordValidationError(TOO_SHORT, minMetrics.length));
        }
        if (actualMetrics.letters < minMetrics.letters) {
            result.add(new PasswordValidationError(NOT_ENOUGH_LETTERS, minMetrics.letters));
        }
        if (actualMetrics.upperCase < minMetrics.upperCase) {
            result.add(new PasswordValidationError(NOT_ENOUGH_UPPER_CASE, minMetrics.upperCase));
        }
        if (actualMetrics.lowerCase < minMetrics.lowerCase) {
            result.add(new PasswordValidationError(NOT_ENOUGH_LOWER_CASE, minMetrics.lowerCase));
        }
        if (actualMetrics.numeric < minMetrics.numeric) {
            result.add(new PasswordValidationError(NOT_ENOUGH_DIGITS, minMetrics.numeric));
        }
        if (actualMetrics.symbols < minMetrics.symbols) {
            result.add(new PasswordValidationError(NOT_ENOUGH_SYMBOLS, minMetrics.symbols));
        }
        if (actualMetrics.nonLetter < minMetrics.nonLetter) {
            result.add(new PasswordValidationError(NOT_ENOUGH_NON_LETTER, minMetrics.nonLetter));
        }
        if (actualMetrics.nonNumeric < minMetrics.nonNumeric) {
            result.add(new PasswordValidationError(NOT_ENOUGH_NON_DIGITS, minMetrics.nonNumeric));
        }
        if (actualMetrics.seqLength > minMetrics.seqLength) {
            result.add(new PasswordValidationError(CONTAINS_SEQUENCE, 0));
        }
    }

    /**
     * Drop requirements that are superseded by others, e.g. if it is required to have 5 upper case
     * letters and 5 lower case letters, there is no need to require minimum number of letters to
     * be 10 since it will be fulfilled once upper and lower case requirements are fulfilled.
     *
     * TODO: move to PasswordPolicy
     */
    private void removeOverlapping() {
        // upperCase + lowerCase can override letters
        final int indirectLetters = upperCase + lowerCase;

        // numeric + symbols can override nonLetter
        final int indirectNonLetter = numeric + symbols;

        // letters + symbols can override nonNumeric
        final int effectiveLetters = Math.max(letters, indirectLetters);
        final int indirectNonNumeric = effectiveLetters + symbols;

        // letters + nonLetters can override length
        // numeric + nonNumeric can also override length, so max it with previous.
        final int effectiveNonLetter = Math.max(nonLetter, indirectNonLetter);
        final int effectiveNonNumeric = Math.max(nonNumeric, indirectNonNumeric);
        final int indirectLength = Math.max(effectiveLetters + effectiveNonLetter,
                numeric + effectiveNonNumeric);

        if (indirectLetters >= letters) {
            letters = 0;
        }
        if (indirectNonLetter >= nonLetter) {
            nonLetter = 0;
        }
        if (indirectNonNumeric >= nonNumeric) {
            nonNumeric = 0;
        }
        if (indirectLength >= length) {
            length = 0;
        }
    }

    /**
     * Combine minimum metrics, set by admin, complexity set by the requester and actual entered
     * password metrics to get resulting minimum metrics that the password has to satisfy. Always
     * returns a new PasswordMetrics object.
     *
     * TODO: move to PasswordPolicy
     */
    public static PasswordMetrics applyComplexity(
            PasswordMetrics adminMetrics, boolean isPin, int complexity) {
        return applyComplexity(adminMetrics, isPin, ComplexityBucket.forComplexity(complexity));
    }

    private static PasswordMetrics applyComplexity(
            PasswordMetrics adminMetrics, boolean isPin, ComplexityBucket bucket) {
        final PasswordMetrics minMetrics = new PasswordMetrics(adminMetrics);

        if (!bucket.canHaveSequence()) {
            minMetrics.seqLength = Math.min(minMetrics.seqLength, MAX_ALLOWED_SEQUENCE);
        }

        minMetrics.length = Math.max(minMetrics.length, bucket.getMinimumLength(!isPin));

        if (!isPin && !bucket.allowsNumericPassword()) {
            minMetrics.nonNumeric = Math.max(minMetrics.nonNumeric, 1);
        }

        return minMetrics;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final PasswordMetrics that = (PasswordMetrics) o;
        return credType == that.credType
                && length == that.length
                && letters == that.letters
                && upperCase == that.upperCase
                && lowerCase == that.lowerCase
                && numeric == that.numeric
                && symbols == that.symbols
                && nonLetter == that.nonLetter
                && nonNumeric == that.nonNumeric
                && seqLength == that.seqLength;
    }

    @Override
    public int hashCode() {
        return Objects.hash(credType, length, letters, upperCase, lowerCase, numeric, symbols,
                nonLetter, nonNumeric, seqLength);
    }
}
