module BBLib

  SPECIAL_PLURALS = {
    addendum: :addenda,
    alga: :algae,
    alumnus: :alumni,
    amoeba: :amoebae,
    analysis: :analyses,
    antenna: :antennae,
    appendix: :appendices,
    auto: :autos,
    axis: :axes,
    bacterium: :bacteria,
    barracks: :barracks,
    basis: :bases,
    cactus: :cacti,
    calf: :calves,
    crisis: :crises,
    curriculum: :curricula,
    datum: :data,
    deer: :deer,
    diagnosis: :diagnoses,
    echo: :echoes,
    elf: :elves,
    ellipsis: :ellipses,
    embargo: :embargoes,
    emphasis: :emphases,
    fish: :fish,
    foot: :feet,
    fungus: :fungi,
    gallows: :gallows,
    genus: :genera,
    goose: :geese,
    half: :halves,
    hero: :heroes,
    hoof: :hooves,
    hypothesis: :hypotheses,
    index: :indices,
    kangaroo: :kangaroos,
    kilo: :kilos,
    knife: :knives,
    larva: :larvae,
    leaf: :leaves,
    life: :lives,
    loaf: :loaves,
    louse: :lice,
    man: :men,
    matrix: :matrices,
    means: :means,
    memo: :memos,
    memorandum: :memoranda,
    mouse: :mice,
    neurosis: :neuroses,
    oasis: :oases,
    offspring: :offspring,
    paralysis: :paralyses,
    parenthesis: :parentheses,
    person: :people,
    photo: :photos,
    piano: :pianos,
    pimento: :pimentos,
    potato: :potatoes,
    pro: :pros,
    self: :selves,
    series: :series,
    sheep: :sheep,
    shelf: :shelves,
    solo: :solos,
    soprano: :sopranos,
    species: :species,
    stimulus: :stimuli,
    studio: :studios,
    syllabus: :syllabi,
    tattoo: :tattoos,
    thesis: :theses,
    thief: :thieves,
    tomato: :tomatoes,
    tooth: :teeth,
    torpedo: :torpedoes,
    vertebra: :vertebrae,
    veto: :vetoes,
    video: :videos,
    wife: :wives,
    wolf: :wolves,
    woman: :women,
    zoo: :zoos
  }

  def self.pluralize(string, num = 2)
    full_string = string.to_s
    string = string.split(/\s+/).last
    sym = string.to_s.downcase.to_sym
    if plural = SPECIAL_PLURALS[sym]
      result = num == 1 ? string : plural
    else
      if string.end_with?(*%w{ch z s x o})
        result = num == 1 ? string : (string + 'es')
      elsif string =~ /[^aeiou]y$/i
        result = num == 1 ? string : string.sub(/y$/i, 'ies')
      else
        result = num == 1 ? string : (string + 's')
      end
    end
    full_string.sub(/#{Regexp.escape(string)}$/, copy_capitalization(string, result).to_s)
  end

  def self.singularize(string)
    full_string = string.to_s
    string = string.split(/\s+/).last
    sym = string.to_s.downcase.to_sym
    sym = string.to_s.downcase.to_sym
    if singular = SPECIAL_PLURALS.find { |k, v| v == sym }
      result = singular.first
    elsif string.downcase.end_with?(*%w{oes ches zes ses xes})
      result = string.sub(/es$/i, '')
    elsif string =~ /ies$/i
      result = string.sub(/ies$/i, 'y')
    elsif string =~ /s$/i && !(string =~ /s{2}$/i)
      result = string.sub(/s$/i, '')
    else
      result = string
    end
    full_string.sub(/#{Regexp.escape(string)}$/, copy_capitalization(string, result).to_s)
  end

  def self.custom_pluralize(num, base, plural = 's', singular = nil)
    num == 1 ? "#{base}#{singular}" : "#{base}#{plural}"
  end

  def self.plural_string(num, string)
    "#{num} #{pluralize(string, num)}"
  end

end

class String
  def pluralize(num = 2)
    BBLib.pluralize(self, num)
  end

  def singularize
    BBLib.singularize(self)
  end
end

class Symbol
  def pluralize(num = 2)
    BBLib.pluralize(self.to_s, num).to_sym
  end

  def singularize
    BBLib.singularize(self.to_s).to_sym
  end
end