package jesse.keeblarcraft.BankMgr;

import java.util.Random;
/*
    Account number composition:

    EXAMPLE:
        KCSB-9284-0JKI94358732

    EXPLANATION:
        The composition of the above number is mostly not random. The composition is 'C' = LETTER, and the first 4 represent the 4-letter combination
        of the financial establishment (think of the stock market NASDAQ). The first 4 '#' (# = Number) digits represent the ROUTING number of the bank.
        The next '#' (in its own brackets) represents ACCOUNT TYPE. This means the mod supports up to 9 configurations; some examples would be CHECKING
        or SAVINGS. The next three '#' (in their own brackets too) will be the first three letters of the username of the account holder inside an ASCII
        table. If the letter is not UTF 8 compatible - then the default will be '0'. The LAST eight '#' (not in brackets) are randomly generated via Java.

        * Please note that the brackets in this example are only for demonstration of separating numbers from each other. They do not show up at all in generation.


        CCCC-####-[#][###]########

        * Additional note - enums are not implicitly integers under the hood like C++; so, a financial establishment could pass in ANY 0-9 digit for "account type" and
        each establishment is allowed to treat that however they want. In one banks case it make checking accounts 3; but in anothers it's 4. This is a general programming
        note for now. It is probably best to keep this consistent in your server/mod so tellers can understand them universally.
*/

/////////////////////////////////////////////////////////////////////////////
/// @class      AccountNumberGenerator
///
/// @brief      Utility class for the banking system. Can generate new account
///             numbers based on parameters and parse the account number
/////////////////////////////////////////////////////////////////////////////
public class AccountNumberGenerator {

    /////////////////////////////////////////////////////////////////////////////
    /// @fn         AccountNumberGenerator
    ///
    /// @param[in]  symbol is the bank/finance institution symbol
    ///
    /// @param[in]  routingNumber is the bank routing number
    ///
    /// @param[in]  accountType is the type of account being generated
    ///
    /// @param[in]  username is the players username who needs the account
    ///
    /// @brief      Creates a new account number for a user
    ///
    /// @return     String representation of account number
    /////////////////////////////////////////////////////////////////////////////
    public static String GenerateNewAccountNumber(String symbol, Integer routingNumber, Integer accountType, String username) {
        String generatedAccountNumber = symbol + "-" + routingNumber + "-" + accountType;

        // Block to translate part of username into number format
        for (int i = 0; i < 3; i++) {
            if (username.length() >= 3 && username.charAt(i) <= 255) { // 255 is largest ASCII value. Might be a sloppy check; can always test later (if I find someone with non ASCII)
                Integer asciiValueOfLetter = (int) username.charAt(i);
                String strValueOfAscii = asciiValueOfLetter.toString();
                strValueOfAscii = strValueOfAscii.substring(0, 1);

                generatedAccountNumber += strValueOfAscii;
            } else if (username.charAt(i) <= 255) { // Case where length is less than 3 but is still in ASCII table
                Integer asciiValueOfLetter = (int) username.charAt(i);
                String strValueOfAscii = asciiValueOfLetter.toString();
                strValueOfAscii = strValueOfAscii.substring(0, 1);

                generatedAccountNumber += strValueOfAscii;
            } else { // Case where the length is less than 3 and is not standard ASCII
                generatedAccountNumber += "0";
            }
        }

        // Guarentee an 8 digit number. 10000000 is floor and max rng int is at most 89999999. Combined they total 99999999
        Random rng = new Random();
        Integer randInteger = 10000000 + rng.nextInt(89999999);
        generatedAccountNumber += randInteger;

        return generatedAccountNumber;
    }

    // the below functions must be given a key generated from the above function or they will combust into
    // not less than one million pieces! :)
    /////////////////////////////////////////////////////////////////////////////
    /// @fn         GetFinancialSymbolFromId
    ///
    /// @param[in]  accountId is the generated account number
    ///
    /// @brief      Gets the financial symbol from the account id
    ///
    /// @return     String representation of financial symbol
    /////////////////////////////////////////////////////////////////////////////
    public static String GetFinancialSymbolFromId(String accountId) {
        return accountId.substring(0, 4);
    }

    /////////////////////////////////////////////////////////////////////////////
    /// @fn         GetRoutingNumberFromId
    ///
    /// @param[in]  accountId is the generated account number
    ///
    /// @brief      Gets the routing number from the account id
    ///
    /// @return     Returns the integer of the account number
    /////////////////////////////////////////////////////////////////////////////
    public static Integer GetRoutingNumberFromId(String accountId) {
        return Integer.parseInt(accountId.substring(5, 9));
    }

    /////////////////////////////////////////////////////////////////////////////
    /// @fn         GetAccountNumberFromId
    ///
    /// @param[in]  accountId is the generated account number
    ///
    /// @brief      Gets the smaller account identifier from the entire account
    ///             identifier. This would be the ACCOUNT TYPE + GENERATED NUMBER
    ///             on the end of the whole identifier (so no financial symbol and
    ///             no routing number)
    ///
    /// @return     String representation of small account number
    /////////////////////////////////////////////////////////////////////////////
    public static String GetAccountNumberFromId(String accountId) {
        return accountId.substring(10);
    }

    /////////////////////////////////////////////////////////////////////////////
    /// @fn         GetAccountTypeFromId
    ///
    /// @param[in]  accountId is the generated account number
    ///
    /// @brief      Gets the account type from account ID
    ///
    /// @note       The string representation of a valid account ID will have
    ///             '0' - '9' (range) in this position; so, subtracting 48 from
    ///             the ASCII returns the actual account number as an integer.
    ///
    /// @return     Integer representing account type (0-9)
    /////////////////////////////////////////////////////////////////////////////
    public static Integer GetAccountTypeFromId(String accountId) {
        return ((int) accountId.charAt(10)) - 48; // ASCII 0 starts at 48. One must subtract 48 to be correct.
    }
}
