#-- copyright
# OpenProject Backlogs Plugin
#
# Copyright (C)2013-2014 the OpenProject Foundation (OPF)
# Copyright (C)2011 Stephan Eckardt, Tim Felgentreff, Marnen Laibow-Koser, Sandro Munda
# Copyright (C)2010-2011 friflaj
# Copyright (C)2010 Maxime Guilbot, Andrew Vit, Joakim Kolsjö, ibussieres, Daniel Passos, Jason Vasquez, jpic, Emiliano Heyns
# Copyright (C)2009-2010 Mark Maglana
# Copyright (C)2009 Joe Heck, Nate Lowrie
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3.
#
# OpenProject Backlogs is a derivative work based on ChiliProject Backlogs.
# The copyright follows:
# Copyright (C) 2010-2011 - Emiliano Heyns, Mark Maglana, friflaj
# Copyright (C) 2011 - Jens Ulferts, Gregor Schmidt - Finn GmbH - Berlin, Germany
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++

When /^I create the impediment$/ do
  page.driver.post backlogs_project_sprint_impediments_url(
    *@impediment_params.values_at('project_id', 'fixed_version_id')
  ), @impediment_params
end

When /^I create the story$/ do
  page.driver.post backlogs_project_sprint_stories_url(
    *@story_params.values_at('project_id', 'fixed_version_id')
  ), @story_params
end

When /^I create the task$/ do
  page.driver.post backlogs_project_sprint_tasks_url(
    *@task_params.values_at('project_id', 'fixed_version_id')
  ), @task_params
end

When /^I move the (story|item|task) named (.+) below (.+)$/ do |type, story_subject, prev_subject|
  work_package_class = if type.strip == 'task' then Task else Story end
  story = work_package_class.find_by(subject: story_subject.strip)
  prev  = work_package_class.find_by(subject: prev_subject.strip)

  attributes = story.attributes
  attributes[:prev]             = prev.id

  if type == 'task'
    # #attributes returns the parent_id to always be nil
    attributes['parent_id'] = story.parent_id
  else
    attributes[:fixed_version_id] = prev.fixed_version_id
  end

  project = Project.find(attributes['project_id'])
  sprint  = prev.fixed_version

  page.driver.post polymorphic_url(
    [:backlogs, project, sprint.becomes(Sprint), story]
  ), attributes.merge('_method' => 'put')
end

When /^I move the story named (.+) (up|down) to the (\d+)(?:st|nd|rd|th) position of the sprint named (.+)$/ do |story_subject, direction, position, sprint_name|
  position = position.to_i
  story = Story.find_by(subject: story_subject)
  sprint = Sprint.find_by(name: sprint_name)
  story.fixed_version = sprint

  attributes = story.attributes
  attributes[:prev] = if position == 1
                        ''
                      else
                        stories = Story.where(fixed_version_id: sprint.id, type_id: Story.types).order(Arel.sql('position ASC'))
                        raise "You indicated an invalid position (#{position}) in a sprint with #{stories.length} stories" if 0 > position or position > stories.length
                        stories[position - (direction == 'up' ? 2 : 1)].id
                      end

  page.driver.post backlogs_project_sprint_story_url(
    *attributes.values_at('project_id', 'fixed_version_id', 'id')
  ), attributes.merge('_method' => 'put')
end

When /^I move the (\d+)(?:st|nd|rd|th) story to the (\d+|last)(?:st|nd|rd|th)? position$/ do |old_pos, new_pos|
  @story_ids = page.all(:css, '#owner_backlogs_container .stories .story .id')

  story = @story_ids[old_pos.to_i - 1]
  story.should_not == nil

  prev = if new_pos.to_i == 1
           nil
         elsif new_pos == 'last'
           @story_ids.last
         elsif old_pos.to_i > new_pos.to_i
           @story_ids[new_pos.to_i - 2]
         else
           @story_ids[new_pos.to_i - 1]
         end

  @story = Story.find(story.text.to_i)

  page.driver.post backlogs_project_sprint_story_url(
    @project.id,
    @story.fixed_version_id,
    @story.id
  ), prev: (prev.nil? ? '' : prev.text), '_method' => 'put'
end

When /^I update the impediment$/ do
  page.driver.post backlogs_project_sprint_impediment_url(
    *@impediment_params.values_at('project_id', 'fixed_version_id', 'id')
  ), @impediment_params.merge('_method' => 'put')
end

When /^I update the sprint$/ do
  page.driver.post backlogs_project_sprint_url(
    *@sprint_params.values_at('project_id', 'id')
  ), @sprint_params.merge('_method' => 'put')
end

When /^I update the story$/ do
  page.driver.post backlogs_project_sprint_story_url(
    *@story_params.values_at('project_id', 'fixed_version_id', 'id')
  ), @story_params.merge('_method' => 'put')
end

When /^I update the task$/ do
  page.driver.post backlogs_project_sprint_task_url(
    *@task_params.values_at('project_id', 'fixed_version_id', 'id')
  ), @task_params.merge('_method' => 'put')
end

When /^I view the master backlog$/ do
  visit url_for(controller: '/projects', action: :show, id: @project)
  click_link('Backlogs')
end

When /^I view the stories of (.+) in the work_packages tab/ do |sprint_name|
  sprint = Sprint.find_by(name: sprint_name)
  visit url_for(controller: '/rb_queries', action: :show, project_id: sprint.project, sprint_id: sprint, only_path: true)
end

When /^I view the stories in the work_packages tab/ do
  visit url_for(controller: '/rb_queries', action: :show, project_id: @project, only_path: true)
end

# WARN: Depends on deprecated behavior of path_for('the task board for
#       "sprint name"')
When /^I view the sprint notes$/ do
  visit url_for(controller: '/rb_wikis', action: 'show', sprint_id: @sprint, project_id: @project)
end

# WARN: Depends on deprecated behavior of path_for('the task board for
#       "sprint name"')
When /^I edit the sprint notes$/ do
  visit url_for(controller: '/rb_wikis', action: 'edit', sprint_id: @sprint, project_id: @project)
end

When /^I follow "(.+?)" of the "(.+?)" (?:backlogs )?menu$/ do |link, backlog_name|
  sprint = Sprint.find_by(name: backlog_name)
  step %{I follow "#{link}" within "#backlog_#{sprint.id} .menu"}
end

When /^I open the "(.+?)" backlogs(?: )?menu/ do |backlog_name|
  sprint = Sprint.find_by(name: backlog_name)
  find(:css, "#backlog_#{sprint.id} .menu > div").click
end

When /^I close the "(.+?)" backlogs(?: )?menu/ do |backlog_name|
  sprint = Sprint.find_by(name: backlog_name)
  step %{I stop hovering over "#backlog_#{sprint.id} .menu"}
end

When /^I click on the text "(.+?)"$/ do |locator|
  expect(page)
    .to have_content(locator)
  find(:xpath, %{//*[contains(text(), "#{locator}")]}).click
end

When /^I click on the link on the modal window with text "(.+?)"$/ do |locator|
  browser = page.driver.browser
  browser.switch_to.frame('modalIframe')
  click_link(locator)
end

When /^I click on the element with class "([^"]+?)"$/ do |locator|
  find(:css, ".#{locator}").click
end

When /^I confirm the story form$/ do
  find(:css, 'input[name=subject]').native.send_key :return
  step 'I wait for AJAX requests to finish'
  step 'I should not see ".saving"'
end

When /^I fill in the ids of the (tasks|work_packages|stories) "(.+?)" for "(.+?)"$/ do |model_name, subjects, field|
  model = Kernel.const_get(model_name.classify)
  ids = subjects.split(/,/).map { |subject| model.find_by(subject: subject).id }

  step %{I fill in "#{ids.join(', ')}" for "#{field}"}
end

When /^I click on the impediment called "(.+?)"$/ do |impediment_name|
  step %{I click on the text "#{impediment_name}"}
end

When /^I click to add a new task for story "(.+?)"$/ do |story_name|
  expect(page)
    .to have_content(story_name)

  story = Story.find_by(subject: story_name)

  find("tr.story_#{story.id} td.add_new").click
end

When /^I fill in the id of the work_package "(.+?)" as the parent work_package$/ do |work_package_name|
  work_package = WorkPackage.find_by(subject: work_package_name)

  # TODO: Simplify once the work_package#edit/update action is implemented
  find('#work_package_parent_id, #work_package_parent_id', visible: false).set(work_package.id)
end

When /^the request on task "(.+?)" is finished$/ do |task_name|
  # Wait for the modal link of this task to appear...
  elements = page.find(:xpath, "//div[contains(., '#{task_name}') and contains(@class,'task')]/descendant::a[contains(@href, .)]")
  # ...by selecting the task board card for a specific task and then go for the
  # link with the id only appearing after the task was saved
end

When /^I follow the link to add a subtask$/ do
  step 'I follow "Relations"'
  step 'I click "Children"'
  step 'I press "Add child"'
end

When /^I change the fold state of a version$/ do
  find('.backlog .toggler').click
end

When /^I click on the Export link$/ do
  click_link('Export')
end

When(/^I click on the link for the story "(.*?)"$/) do |subject|
  story = Story.find_by(subject: subject)

  within("#story_#{story.id}") do
    click_link(story.id)
  end
end
