Given(/^I am on the Project::DigitalProductTracksPage for a product with track fixtures$/) do
  # This is used for a product that should have fixtures in place and shouldn't be modified
  @product_id = 2_020_312
  step "I am on the Project::DigitalProductTracksPage for the product #{@product_id}"
end

Given(/^I am on the Project::DigitalProductTracksPage for a product with (.*?) tracks?$/) do |has_track|
  # This is used for a product that can have tracks added and deleted from it
  @product_id = 2_042_681
  step "I am on the Project::DigitalProductTracksPage for the product #{@product_id}"
  on(Project::DigitalProductTracksPage) do |page|
    @browser.alert.ok if @browser.alert.exists?
    page.wait_until { page.file_field_elements.any? }
    if has_track == "no"
      while page.track_elements.any?
        step "I delete a track from a tracklist grid"
      end
    else
      step "I import a valid track via \"upload from computer\" dialog box" unless page.tracklist?
    end
  end
end

And(/^I add (\d+) new tracks? to an existing product$/) do |tracks_number|
  step "I am on the Project::DigitalProductTracksPage for a product with no tracks"
  (1..tracks_number.to_i).each do
    step "I import a valid track via \"upload from computer\" dialog box"
    step "I can see the track in the tracklist table"
  end
end

Then(/^I can see when there was an error during the track upload$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until(500) { page.file_processing_elements.none? }
    expect(page.upload_error_element.element.present?).to be true
  end
end

When(/^I replace track's audio file$/) do
  @track_file = File.join(Support::Paths.assets, "a.wav")
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until(30) { page.track_elements.any? }
    page.track_elements.first.click
    page.wait_until { page.file_replace? }
    page.upload_file(page.file_replace_element, @track_file)
  end
end

When(/^I replace my track's audio file if file is missing or in error$/) do
  if on(Project::DigitalProductTracksPage).track_edit_form_element.exists?
    step "I replace track's audio file"
  end
end

Then(/^I can see the track is replaced$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until { page.file_processing_elements.any? }
  end
end

Then(/^I can see the track is processed/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until { page.file_processing_elements.any? }
    page_refresh = proc do |exception, try|
      puts "#{exception.class}: '#{exception.message}' - Retry attempt for processed track: #{try}"
      page.refresh
    end
    Retriable.retriable(on: RSpec::Expectations::ExpectationNotMetError, tries: 5, on_retry: page_refresh) do
      @browser.alert.ok if @browser.alert.exists?
      eventually(timeout: 130) { expect(page.tracklist_element.element.present?).to be true }
      eventually(timeout: 200) { expect(page.file_processing_elements.none?).to be true }
    end
  end
end

When(/^I import an? (valid|invalid) track via "upload from computer" dialog box$/) do |track_case|
  case track_case
  when "valid"
    @track_file = File.join(Support::Paths.assets, "a.wav")
  when "invalid"
    @track_file = File.join(Support::Paths.assets, "a_bad.wav")
  end
  on(Project::DigitalProductTracksPage) do |page|
    page.digital_product_next_element.when_present

    # workaround to be able to call this step multiple times not depending on page state
    page.upload_file_when_ready(@track_file)

    # additional check that uploading progress bar is displayed
    step "I can see uploading progress"

    page.wait_until { page.file_processing_elements.any? }
  end
end

Given(/^I have a new and complete track$/) do
  step "I am on the Project::DigitalProductTracksPage for the product"
  step "I import a valid track via \"upload from computer\" dialog box"
  step "I can see the track is processed"
  step "I fill in all the required track builder fields"
  step "I save my track"
end

Then(/^I can see the tracks? in the tracklist table$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.tracklist_element.when_present

    if !@track_files.nil?
      @track_files.each do |track|
        expect(page.tracklist).to include File.basename(track, ".*")
      end
    elsif !@track_file.nil?
      expect(page.tracklist).to include File.basename(@track_file, ".*")
    end
  end
end

When(/^I delete a track from a tracklist grid$/) do
  on(Project::DigitalProductTracksPage) do |page|
    if page.tracklist_element.element.present?
      page.initiate_delete_tracks
      page.confirm_delete_element.when_present.click
      page.wait_until(120) { page.confirm_delete_element.present? == false }
    end
  end
end

When(/^I initiate track deletion$/) do
  on(Project::DigitalProductTracksPage) do |page|
    if page.tracklist_element.element.present?
      @tracks_before_delete = page.track_elements.length
      page.initiate_delete_tracks
    end
  end
end

When(/^I cancel track deletion$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.cancel_delete_element.when_present.click
  end
end

Then(/^I can see that the track is deleted$/) do
  on(Project::DigitalProductTracksPage) do |page|
    expect(page.tracklist_element.element.present?).to be false
  end
end

Then(/^I can see that the track has not been deleted$/) do
  on(Project::DigitalProductTracksPage) do |page|
    expect(@tracks_before_delete).to eq(page.track_elements.length)
  end
end

When(/^I upload (\d+) tracks via track builder$/) do |track_amount|
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until { page.current_product_step? }
    page.tracks unless page.current_product_step_element.text == "Tracks"
    page.delete_all_tracks
    # start multiple audio upload
    upload_dir = Support::Paths.uploads
    @track_files = []
    (1..track_amount.to_i).each do |track_number|
      src = File.join(Support::Paths.assets, "a.wav")
      track_number = track_number.to_s.rjust(3, "0")
      dst = File.join(Support::Paths.uploads, "#{track_number}.wav")
      FileUtils.copy_entry(src, dst)
      @track_files.push(dst)
    end
    page.wait_until { Dir.glob(upload_dir + "/*.wav").size == track_amount.to_i }
    audio_files = Dir.glob(upload_dir + "/*.wav").join(" \n ")
    page.upload_file_when_ready(audio_files)
    page.wait_until { page.file_processing_elements.size == track_amount.to_i }
  end
end

When(/^I upload 5 tracks via track builder bulk upload field$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until { page.current_product_step? }
    page.tracks unless page.current_product_step_element.text == "Tracks"
    page.delete_all_tracks
    audio_files = File.join(Support::Paths.assets, "bulk/001.wav")
    audio_files = audio_files + "\n" + File.join(Support::Paths.assets, "bulk/002.wav")
    audio_files = audio_files + "\n" + File.join(Support::Paths.assets, "bulk/003.wav")
    audio_files = audio_files + "\n" + File.join(Support::Paths.assets, "bulk/004.wav")
    audio_files = audio_files + "\n" + File.join(Support::Paths.assets, "bulk/005.wav")
    page.upload_file_when_ready(audio_files)
    page.wait_until(120) { page.file_processing_elements.size == 5 }
  end
end

Then(/^I should not see any track builder issues$/) do
  pending # Write code here that turns the phrase above into concrete actions
end

When(/^I drag the last track to the top position$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until { page.current_product_step? }
    page.tracks unless page.current_product_step_element.text == "Tracks"
    page.wait_until { page.file_field_elements.any? }
    page.wait_until(120) { page.file_processing_elements.none? }
    @last_track_name = page.tracklist_element[-1]["TRACK"].text
    page.drag_last_track_to_first
    page.wait_until { page.tracklist_element[1]["TRACK"].text == @last_track_name }
    # sleep required since the only indicator of success is a put request to the arrange endpoint
    sleep 5
  end
end

Then(/^the track order should persist after a page refresh$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.refresh
    page.wait_until { page.file_field_elements.any? }
    expect(page.tracklist_element[1]["TRACK"].text).to eql @last_track_name
  end
end

And(/^there are no volume dividers present$/) do
  on(Project::DigitalProductTracksPage) do |page|
    @browser.alert.ok if @browser.alert.exists?
    page.wait_until { page.file_field_elements.any? }
    if page.volume_divider_elements.any?
      page.volume_divider_elements.each do |divider|
        if divider.div_element(class: "checkbox").present?
          divider.div_element(class: "checkbox").click
        end
      end
      page.initiate_delete_tracks
      page.confirm_delete_element.when_present.click
    end
    eventually { expect(page.volume_divider_elements.none?) }
  end
end

When(/^I add a volume divider$/) do
  on(Project::DigitalProductTracksPage) do |page|
    original_divider_count = page.volume_divider_elements.size
    page.add_volume_divider
    if original_divider_count.zero?
      eventually { expect(page.volume_divider_elements.size).to equal 2 }
    else
      eventually { expect(page.volume_divider_elements.size).to equal(original_divider_count + 1) }
    end
  end
end

And(/^I move the volume divider between the tracks$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.drag_volume_divider_between_tracks
    page.wait_until { page.tracklist_element[-1].attribute "class" }
  end
  # sleep required since the only indicator of success is a put request to the arrange endpoint
  sleep 3
end

Then(/^the tracks are still separated by volumes after a page refresh$/) do
  on(Project::DigitalProductTracksPage) do |page|
    divide_again = proc do |exception, try|
      Kernel.puts "#{exception.class}: '#{exception.message}' - Retries: #{try}"
      step "I add a volume divider"
      step "I move the volume divider between the tracks"
    end
    Retriable.retriable(on: RSpec::Expectations::ExpectationNotMetError, tries: 3, on_retry: divide_again) do
      page.refresh
      page.wait_until { page.file_field_elements.any? }
      page.expect(page.first_track_of_volume(1).cell_element.text).to eql "1"
      page.expect(page.first_track_of_volume(2).cell_element.text).to eql "1"
    end
  end
end

Then(/^the tracks are separated by volumes$/) do
  on(Project::DigitalProductTracksPage) do |page|
    eventually { expect(page.volume_divider_elements.size).to equal 2 }
  end
end

Given(/^I have a blank track with all required fields for label (.*)$/) do |label_id|
  session_token = Support::Services::GrassAuth.instance.workstation_session_token("label_" + label_id)
  track_response = Support::Services::OwsTrack.create_new_track(@product_id, session_token)
  @track_id = track_response["items"][0]["tuid"]
  Support::Services::OwsTrack.add_performers(@track_id, session_token)
  Support::Services::OwsTrack.add_publishing_obligation(@track_id, @product_id, session_token)
end

And(/^I can see uploading progress$/) do
  on(Project::DigitalProductTracksPage) do |page|
    page.progress_bar_element.wait_until(&:present?)
  end
end

When(/^I replace not a blank track's audio file$/) do
  @track_file = File.join(Support::Paths.assets, "big.wav")
  on(Project::DigitalProductTracksPage) do |page|
    page.wait_until(300) { page.play_icon_element.present? }
    page.wait_until(30) { page.track_elements.any? }
    page.track_elements.first.click
    page.wait_until { page.file_replace? }
    page.upload_file(page.file_replace_element, @track_file)
  end
end
