# frozen_string_literal: true
require 'pp'
require_relative '../lib/mac/say'

# ===== Class level =====

# Get all the voices
pp Mac::Say.voices

# Collect the separate attributes lists
pp Mac::Say.voices.collect { |v| v[:name] }
pp Mac::Say.voices.collect { |v| v[:language] }
pp Mac::Say.voices.collect { |v| v[:sample] }

# Look for voices by an attribute
pp Mac::Say.voice(:singing, true)
pp Mac::Say.voice(:joke, false)
pp Mac::Say.voice(:gender, :female)

# Look for voices by multiple attributes
pp Mac::Say.voice { |v| v[:joke] == true && v[:gender] == :female }
pp Mac::Say.voice { |v| v[:language] == :en && v[:gender] == :male && v[:quality] == :high && v[:joke] == false }

# Find a voice (returns a Hash)
pp Mac::Say.voice(:name, :alex)
pp Mac::Say.voice(:country, :scotland)

# Find the voices by the feature (returns an Array)
pp Mac::Say.voice(:language, :en)

# Work with the voices collection
indian_english = Mac::Say.voice(:country, :in).select { |v| v[:language] == :en }.first[:name]

# Use multiline text
puts Mac::Say.say <<-DATA, indian_english
  Invokes the given block passing in successive elements from self, deleting elements for which the block returns a false value.
  The array may not be changed instantly every time the block is called.
  If changes were made, it will return self, otherwise it returns nil.
DATA

# ===== Instance level =====

# with constant name in the constructor and custom rate
talker = Mac::Say.new(voice: :alex, rate: 300)
talker.say string: 'Hello world'

# with the voice name from the class method + dynamic sample
talker = Mac::Say.new(voice: Mac::Say.voice(:country, :scotland)[:name])
talker.say string: talker.voice(:country, :scotland)[:sample]

# with the dynamic voice name selected from the multiple voices
talker = Mac::Say.new
voice = talker.voice(:language, :en)&.sample(1)&.first&.fetch :name
talker.say string: 'Hello world!', voice: voice

# changing voice in runtime for an instance of talker (while saying something)
voice = talker.voice(:country, :kr)
talker.say string: voice[:sample], voice: voice[:name]

# or change the voice without saying anything
talker.say voice: :"ting-ting"
talker.say string: '您好，我叫Ting-Ting。我讲中文普通话。'

# Listen to all the languages with the dynamic voices + dynamic samples
polyglot = Mac::Say.new
voices = polyglot.voices

voices.each_with_index do |v, i|
  puts "#{i + 1} :: #{v[:name]} :: '#{v[:sample]}'"
  polyglot.say string: v[:sample], voice: v[:name]
end

# Or perform a roll call
roll_call = Mac::Say.new
voices = roll_call.voices

voices.each_with_index do |v, i|
  puts "#{i + 1} :: #{v[:name]}"
  roll_call.say string: v[:name], voice: v[:name]
end

# ===== Reading files =====

# Read the file (prior to the string)
file_path = File.absolute_path '../test/fixtures/text/en_gb.txt', File.dirname(__FILE__)

# with a voice from the class
voice = Mac::Say.voice(:country, :gb)&.first&.fetch(:name)
reader = Mac::Say.new(file: file_path, voice: voice)
reader.read

# with a dynamic voice from the class
voice = Mac::Say.voice(:country, :scotland)[:name]
reader = Mac::Say.new(file: file_path)
reader.read voice: voice

# with a dynamic voice from the instance
reader = Mac::Say.new(file: file_path)
reader.read(voice: reader.voice(:country, :us)[2][:name])

# with a dynamic voice from the instance
new_file_path = File.absolute_path '../test/fixtures/text/en_us.txt', File.dirname(__FILE__)

# with a dynamic file change
reader = Mac::Say.new(file: file_path)
reader.read voice: :alex
reader.read file: new_file_path

# ===== Exceptions =====

# wrong file
begin
  reader = Mac::Say.new(file: 'wrong')
  reader.read
rescue Mac::Say::FileNotFound => e
  puts e.message
end

# wrong file
begin
  reader = Mac::Say.new
  reader.read file: 'too_wrong'
rescue Mac::Say::FileNotFound => e
  puts e.message
end

# wrong path
begin
  Mac::Say.new(say_path: '/usr/bin/wrong_say')
rescue Mac::Say::CommandNotFound => e
  puts e.message
end

# wrong voice
begin
  talker = Mac::Say.new(voice: :wrong)
  talker.say string: 'OMG! I lost my voice!'
rescue Mac::Say::VoiceNotFound => e
  puts e.message
end

# wrong voice
begin
  talker = Mac::Say.new
  talker.say string: 'OMG! I lost my voice!', voice: :too_wrong
rescue Mac::Say::VoiceNotFound => e
  puts e.message
end

# wrong voice
begin
  Mac::Say.say 'OMG! I lost my voice!', :still_wrong
rescue Mac::Say::VoiceNotFound => e
  puts e.message
end

# wrong feature
begin
  Mac::Say.voice(:tone, :enthusiastic)
rescue Mac::Say::UnknownVoiceAttribute => e
  puts e.message
end

# wrong feature
begin
  Mac::Say.new.voice(:articulation, :nostalgic)
rescue Mac::Say::UnknownVoiceAttribute => e
  puts e.message
end
