package dsAlgo.string;

interface Alphabet {
  char toChar(int index);
  int toIndex(char r);
  boolean contains(char c);
  int R();
  int lgR();
  int[] toIndices(String s);
  String toChars(int[] indices);

  static Lazy<Alphabet> binary() {
    return Lazy.of(() -> new AlphabetImpl("01"));
  }

  static Lazy<Alphabet> octal() {
    return Lazy.of(() -> new AlphabetImpl("01234567"));
  }

  static Lazy<Alphabet> decimal() {
    return Lazy.of(() -> new AlphabetImpl("0123456789"));
  }

  static Lazy<Alphabet> hexadecimal() {
    return Lazy.of(() -> new AlphabetImpl("0123456789ABCDEF"));
  }

  static Lazy<Alphabet> dna() {
    return Lazy.of(() -> new AlphabetImpl("ACTG"));
  }

  static Lazy<Alphabet> lowercase() {
    return Lazy.of(() -> new AlphabetImpl("abcdefghijklmnopqrstuvwxyz"));
  }

  static Lazy<Alphabet> uppercase() {
    return Lazy.of(() -> new AlphabetImpl("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
  }

  static Lazy<Alphabet> protein() {
    return Lazy.of(() -> new AlphabetImpl("ACDEFGHIKLMNPQRSTVWY"));
  }

  static Lazy<Alphabet> base64() {
    return Lazy.of(() -> new AlphabetImpl("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"));
  }

  static Lazy<Alphabet> ascii() {
    return Lazy.of(() -> new AlphabetImpl(128));
  }

  static Lazy<Alphabet> extended_ascii() {
    return Lazy.of(() -> new AlphabetImpl(256));
  }

  static Lazy<Alphabet> unicode16() {
    return Lazy.of(() -> new AlphabetImpl(65536));
  }
}
