/*
   * Check new subclass classId for validity
   * (villagemaster race/type, is not contains in previous subclasses,
   * is contains in allowed subclasses)
   * Base class not added into allowed subclasses.
   */
  private final boolean isValidNewSubClass(L2PcInstance player, int classId) {
    if (!checkVillageMaster(classId)) return false;

    final ClassId cid = ClassId.values()[classId];
    for (Iterator<SubClass> subList = iterSubClasses(player); subList.hasNext(); ) {
      SubClass sub = subList.next();
      ClassId subClassId = ClassId.values()[sub.getClassId()];

      if (subClassId.equalsOrChildOf(cid)) return false;
    }

    // get player base class
    final int currentBaseId = player.getBaseClass();
    final ClassId baseCID = ClassId.values()[currentBaseId];

    // we need 2nd occupation ID
    final int baseClassId;
    if (baseCID.level() > 2) baseClassId = baseCID.getParent().ordinal();
    else baseClassId = currentBaseId;

    Set<PlayerClass> availSubs = PlayerClass.values()[baseClassId].getAvailableSubclasses(player);
    if (availSubs == null || availSubs.isEmpty()) return false;

    boolean found = false;
    for (Iterator<PlayerClass> availSub = availSubs.iterator(); availSub.hasNext(); ) {
      PlayerClass pclass = availSub.next();
      if (pclass.ordinal() == classId) {
        found = true;
        break;
      }
    }

    return found;
  }
  /*
   * Returns list of available subclasses
   * Base class and already used subclasses removed
   */
  private final Set<PlayerClass> getAvailableSubClasses(L2PcInstance player) {
    // get player base class
    final int currentBaseId = player.getBaseClass();
    final ClassId baseCID = ClassId.values()[currentBaseId];

    // we need 2nd occupation ID
    final int baseClassId;
    if (baseCID.level() > 2) baseClassId = baseCID.getParent().ordinal();
    else baseClassId = currentBaseId;

    /**
     * If the race of your main class is Elf or Dark Elf, you may not select each class as a
     * subclass to the other class.
     *
     * <p>If the race of your main class is Kamael, you may not subclass any other race If the race
     * of your main class is NOT Kamael, you may not subclass any Kamael class
     *
     * <p>You may not select Overlord and Warsmith class as a subclass.
     *
     * <p>You may not select a similar class as the subclass. The occupations classified as similar
     * classes are as follows:
     *
     * <p>Treasure Hunter, Plainswalker and Abyss Walker Hawkeye, Silver Ranger and Phantom Ranger
     * Paladin, Dark Avenger, Temple Knight and Shillien Knight Warlocks, Elemental Summoner and
     * Phantom Summoner Elder and Shillien Elder Swordsinger and Bladedancer Sorcerer, Spellsinger
     * and Spellhowler
     *
     * <p>Also, Kamael have a special, hidden 4 subclass, the inspector, which can only be taken if
     * you have already completed the other two Kamael subclasses
     */
    Set<PlayerClass> availSubs = PlayerClass.values()[baseClassId].getAvailableSubclasses(player);

    if (availSubs != null && !availSubs.isEmpty()) {
      for (Iterator<PlayerClass> availSub = availSubs.iterator(); availSub.hasNext(); ) {
        PlayerClass pclass = availSub.next();

        // check for the village master
        if (!checkVillageMaster(pclass)) {
          availSub.remove();
          continue;
        }

        // scan for already used subclasses
        int availClassId = pclass.ordinal();
        ClassId cid = ClassId.values()[availClassId];
        for (Iterator<SubClass> subList = iterSubClasses(player); subList.hasNext(); ) {
          SubClass prevSubClass = subList.next();
          ClassId subClassId = ClassId.values()[prevSubClass.getClassId()];

          if (subClassId.equalsOrChildOf(cid)) {
            availSub.remove();
            break;
          }
        }
      }
    }

    return availSubs;
  }
 /*
  * Returns true if this classId allowed for master
  */
 public final boolean checkVillageMaster(int classId) {
   return checkVillageMaster(PlayerClass.values()[classId]);
 }