require_relative './page_partial_context'

class NestedPagePartialContext < PagePartialContext

  def given_nested_page_partial(partial_name, parent_partial_name)
    parent = Partial.find_by(name: parent_partial_name)
    empty_field = get_first_empty_partial_field(parent)
    nested_partial = given_page_partial(partial_name, nil, empty_field.id)
    empty_field.update!({value: nested_partial.id})
    @parent_partial_id = parent.id
  end

  def change_field(field, text)
    page_partial = PagePartial.find_by(page_id: @page_id, partial_id: @partial_id) || PagePartial.find_by(page_id: nil, partial_id: @partial_id)
    set_page_partial_field_values(page_partial, text, field)
    expand_page_partial("#partial-#{page_partial.id}")
    find("[data-fieldname='#{field}']").set(text, {clear: :backspace})
    click_and_wait('Save')
  end

  def add_partial_to_field(partial, field)
    page_partial = PagePartial.find_by(partial_id: @partial_id, page_id: @page_id)
    set_page_partial_field_values(page_partial, (PagePartial.last.id + 1).to_s, field)
    within("#partial-#{page_partial.id}") do
      partial_field_id = PartialField.find_by(partial_id: @partial_id, name: field).id
      within("[data-partial-field-id='#{partial_field_id}'") do
        click_a_tag('Add Nested Partial')
      end
    end
    @partial_id = Partial.find_by(name: partial).id
    click_and_wait(partial)
  end

  def delete_parent_partial
    parent_page_partial = PagePartial.find_by(partial_id: @parent_partial_id, page_id: @page_id)
    @nested_page_partial_ids = get_nested_page_partial_ids(parent_page_partial).compact
    delete(parent_page_partial)
  end

  def delete_nested_partial(field_name)
    parent_page_partial = PagePartial.find_by(partial_id: @parent_partial_id, page_id: @page_id)
    expand_page_partial("#partial-#{parent_page_partial.id}")
    @parent_page_partial_field_id = get_parent_field_id(field_name, parent_page_partial)
    @nested_page_partial_id = PagePartialField.find_by(page_partial_id: parent_page_partial.id, partial_field_id: @parent_page_partial_field_id).value
    delete_and_wait("#partial-#{@nested_page_partial_id}")
  end

  def expect_all_pages
    all_pages = get_all_pages.uniq
    all_pages.each {|name| expect_content_on_page(name)}
  end

  def expect_empty_field_in_database
    expect(PagePartialField.find(@parent_page_partial_field_id).value).to eq('')
  end

  def expect_empty_field_on_page
    within("[data-partial-field-id='#{@parent_page_partial_field_id}'") do
      expect_content_on_page('Add Nested Partial')
    end
  end

  def expect_no_nested_page_partials
    @nested_page_partial_ids.each do |id|
      expect(PagePartial.find_by(id: id)).to be_falsey
    end
  end

  private

  def get_first_empty_partial_field(parent)
    empty_partial_field_ids = PartialField.where(partial_id: parent.id, field_type: 'page-partial').map(&:id)
    parent.page_partials.first.page_partial_fields.select do |field|
      empty_partial_field_ids.include?(field.partial_field_id)
    end.first
  end

  def get_all_pages
    Partial.find(@partial_id).page_partials.map do |instance|
      if instance.page_id
        Page.find(instance.page_id).name
      else
        PagePartialField.find(instance.page_partial_field_id).page.name
      end
    end
  end

  def get_parent_field_id(name, parent_page_partial)
    parent_page_partial.page_partial_fields.select do |page_partial_field|
      partial_field_name = page_partial_field.partial_field.name
      return page_partial_field.id if partial_field_name == name
    end
  end

  def get_nested_page_partial_ids(parent_page_partial)
    parent_page_partial.page_partial_fields.map do |field|
      PagePartial.find_by(page_id: nil, page_partial_field_id: field.id).try(:id) if PartialField.find(field.partial_field_id).field_type == 'page-partial'
    end
  end

  def set_page_partial_field_values(page_partial, text, field)
    @field_values ||= {}
    field_values_hash = page_partial.field_values_hash
    field_values_hash[field] = text
    @field_values[page_partial.partial.name] = field_values_hash
  end

end
