describe "screen properties" do

  before do
    # Simulate AppDelegate setup of main screen
    @screen = HomeScreen.new modal: true, nav_bar: true
    @screen.on_load
  end

  it "does not have a default title" do
    screen = UntitledScreen.new
    screen.title.should == nil
  end

  it "does not display a default title in the nav bar" do
    screen = UntitledScreen.new
    screen.navigationItem.title.should == nil
  end

  it "should store title" do
    HomeScreen.title.should == "Home"
  end

  it "should set default title on new instances" do
    @screen.title.should == "Home"
  end

  it "should let the instance set its title" do
    @screen.title = "instance method"
    @screen.title.should == 'instance method'
  end

  it "should not let the instance reset the default title" do
    @screen.title = "instance method"
    HomeScreen.title.should != 'instance method'
  end

  it "should set the tab bar item with a system item" do
    @screen.set_tab_bar_item system_item: :contacts
    comparison = UITabBarItem.alloc.initWithTabBarSystemItem(UITabBarSystemItemContacts, tag: 0)
    @screen.tabBarItem.systemItem.should == comparison.systemItem
    @screen.tabBarItem.tag.should == comparison.tag
    @screen.tabBarItem.image.should == comparison.image
  end

  it "should set the tab bar item with a custom item and title" do
    @screen.set_tab_bar_item title: "My Screen", item: "list"

    item_image = UIImage.imageNamed("list")
    comparison = UITabBarItem.alloc.initWithTitle("My Screen", image: item_image, tag: 0)

    @screen.tabBarItem.systemItem.should == comparison.systemItem
    @screen.tabBarItem.tag.should == comparison.tag
    @screen.tabBarItem.image.should == comparison.image
  end

  it "#modal? should be true" do
    @screen.modal?.should == true
  end

  it "should know it is the first screen" do
    @screen.first_screen?.should == true
  end

  it "#should_autorotate should default to 'true'" do
    @screen.should_autorotate.should == true
  end

  it "should allow opening and closing a modal screen" do
    parent_screen = BasicScreen.new(nav_bar: true)
    parent_screen.mock!(:"presentViewController:animated:completion:") do |controller, animated, completion|
      controller.should == @screen.navigationController
    end
    parent_screen.open_modal @screen
    parent_screen.mock!(:"dismissViewControllerAnimated:completion:") do |animated, completion|
      animated.should == true
    end
    @screen.close
  end

  it "should push another screen with animation by default" do
    parent_screen = BasicScreen.new(nav_bar: true)
    parent_screen.navigationController.mock!(:"pushViewController:animated:") do |controller, animated|
      animated.should == true
    end
    parent_screen.open @screen
  end

  it "should push another screen with animation when animated: true" do
    parent_screen = BasicScreen.new(nav_bar: true)
    parent_screen.navigationController.mock!(:"pushViewController:animated:") do |controller, animated|
      animated.should == true
    end
    parent_screen.open @screen, animated: true
  end

  it "should push another screen without animation when animated: false" do
    parent_screen = BasicScreen.new(nav_bar: true)
    parent_screen.navigationController.mock!(:"pushViewController:animated:") do |controller, animated|
      animated.should == false
    end
    parent_screen.open @screen, animated: false
  end

  # Issue https://github.com/clearsightstudio/ProMotion/issues/109
  it "#should_autorotate should fire when shouldAutorotate fires when in a navigation bar" do
    parent_screen = BasicScreen.new(nav_bar: true)
    parent_screen.open @screen, animated: false
    @screen.mock!(:should_autorotate) { true.should == true }
    parent_screen.navigationController.shouldAutorotate
  end

  it "#should_autorotate shouldn't crash when NavigationController's visibleViewController is nil" do
    parent_screen = BasicScreen.new(nav_bar: true)
    parent_screen.open @screen, animated: false
    @screen.navigationController.mock!(:visibleViewController) { nil }
    parent_screen.navigationController.shouldAutorotate
  end

  # <= iOS 5 only
  it "#should_rotate(orientation) should fire when shouldAutorotateToInterfaceOrientation(orientation) fires" do
    @screen.mock!(:should_rotate) { |orientation| orientation.should == UIInterfaceOrientationMaskPortrait }
    @screen.shouldAutorotateToInterfaceOrientation(UIInterfaceOrientationMaskPortrait)
  end

  describe "iOS lifecycle methods" do

    it "-viewDidLoad" do
      @screen.mock!(:view_did_load) { true }
      @screen.viewDidLoad.should == true
    end

    it "-viewWillAppear" do
      @screen.mock!(:view_will_appear) { |animated| animated.should == true }
      @screen.viewWillAppear(true)
    end

    it "-viewDidAppear" do
      @screen.mock!(:view_did_appear) { |animated| animated.should == true }
      @screen.viewDidAppear(true)
    end

    it "-viewWillDisappear" do
      @screen.mock!(:view_will_disappear) { |animated| animated.should == true }
      @screen.viewWillDisappear(true)
    end

    it "-viewDidDisappear" do
      @screen.mock!(:view_did_disappear) { |animated| animated.should == true }
      @screen.viewDidDisappear(true)
    end

    it "-shouldAutorotateToInterfaceOrientation" do
      @screen.mock!(:should_rotate) { |o| o.should == UIInterfaceOrientationPortrait }
      @screen.shouldAutorotateToInterfaceOrientation(UIInterfaceOrientationPortrait)
    end

    it "-shouldAutorotate" do
      @screen.mock!(:should_autorotate) { true }
      @screen.shouldAutorotate.should == true
    end

    it "-willRotateToInterfaceOrientation" do
      @screen.mock! :will_rotate do |orientation, duration|
        orientation.should == UIInterfaceOrientationPortrait
        duration.should == 0.5
      end
      @screen.willRotateToInterfaceOrientation(UIInterfaceOrientationPortrait, duration: 0.5)
    end

    it "-didRotateFromInterfaceOrientation" do
      @screen.mock!(:on_rotate) { true }
      @screen.didRotateFromInterfaceOrientation(UIInterfaceOrientationPortrait).should == true
    end

  end

  describe "memory warnings" do

    it "should call didReceiveMemoryWarning when exists" do
      memory_screen = MemoryWarningScreenSelfImplemented.new
      memory_screen.memory_warning_from_uikit.should.be.nil
      memory_screen.didReceiveMemoryWarning
      memory_screen.memory_warning_from_uikit.should == true
    end

    it "should call super up the chain" do
      memory_screen = MemoryWarningNotSoSuperScreen.new

      memory_screen.memory_warning_from_super.should.be.nil
      memory_screen.didReceiveMemoryWarning
      memory_screen.memory_warning_from_super.should == true
    end

    it "should call on_memory_warning when implemented" do
      memory_screen = MemoryWarningScreen.new

      memory_screen.memory_warning_from_pm.should.be.nil
      memory_screen.didReceiveMemoryWarning
      memory_screen.memory_warning_from_pm.should == true
    end

  end

  describe "navigation controller behavior" do

    it "should have a navigation bar" do
      @screen.navigationController.should.be.kind_of UINavigationController
    end

    it "should let the instance set the nav_controller" do
      screen = HomeScreen.new nav_bar: true, nav_controller: CustomNavigationController
      screen.on_load
      screen.navigationController.should.be.instance_of CustomNavigationController
    end

    it "#navigationController should return a navigation controller" do
      @screen.navigationController.should.be.instance_of ProMotion::NavigationController
    end

    it "should have a nav bar" do
      @screen.nav_bar?.should == true
    end

    it "have a right bar button item" do
      @screen.navigationItem.rightBarButtonItem.should.not == nil
    end

    it "should have a left bar button item" do
      @screen.navigationItem.leftBarButtonItem.should.not == nil
    end

    it "should set the given action on a left bar button item" do
      @screen.navigationItem.leftBarButtonItem.action.should == :save_something
    end

    it "should set the given action on a right bar button item" do
      @screen.navigationItem.rightBarButtonItem.action.should == :return_to_some_other_screen
    end
  end

  describe "bar button behavior" do
    describe "system bar buttons" do
      before do
        @screen.set_nav_bar_button :right, title: nil, action: :add_something, system_item: UIBarButtonSystemItemAdd
      end

      it "has a right bar button item of the correct type" do
        @screen.navigationItem.rightBarButtonItem.should.be.instance_of UIBarButtonItem
      end

      it "is an add button" do
        @screen.navigationItem.rightBarButtonItem.action.should == :add_something
      end
    end

    describe "bar button tint colors" do
      before do
        @screen.set_nav_bar_button :right, title: nil, action: :add_something, system_item: UIBarButtonSystemItemAdd, tint_color: UIColor.blueColor
      end

      it "sets the tint color" do
        CGColorEqualToColor(@screen.navigationItem.rightBarButtonItem.tintColor, UIColor.blueColor).should == true
      end
    end

    describe 'titled bar buttons' do
      before do
        @screen.set_nav_bar_button :right, title: "Save", action: :save_something, style: UIBarButtonItemStyleDone
      end

      it "has a right bar button item of the correct type" do
        @screen.navigationItem.rightBarButtonItem.should.be.instance_of UIBarButtonItem
      end

      it "has a right bar button item of the correct style" do
        @screen.navigationItem.rightBarButtonItem.style.should == UIBarButtonItemStyleDone
      end

      it "is titled correctly" do
        @screen.navigationItem.rightBarButtonItem.title.should == 'Save'
      end
    end

    describe 'image bar buttons' do
      before do
        @image = UIImage.alloc.init
        @screen.set_nav_bar_button :right, title: @image, action: :save_something, style: UIBarButtonItemStyleDone
      end

      it "has a right bar button item of the correct type" do
        @screen.navigationItem.rightBarButtonItem.should.be.instance_of UIBarButtonItem
      end

      it "is has the right image" do
        @screen.navigationItem.rightBarButtonItem.title.should == nil
      end
    end

    describe 'custom view bar buttons' do
      before do
        @activity = UIActivityIndicatorView.alloc.initWithActivityIndicatorStyle(UIActivityIndicatorViewStyleWhite)
        @screen.set_nav_bar_button :right, {custom_view: @activity}
      end

      it "has a right bar button item of the correct type" do
        @screen.navigationItem.rightBarButtonItem.should.be.instance_of UIBarButtonItem
        @screen.navigationItem.rightBarButtonItem.customView.should.be.instance_of UIActivityIndicatorView
      end
    end

  end

end

describe "screen with toolbar" do

  it "showing" do
    # Simulate AppDelegate setup of main screen
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    screen.on_load
    screen.navigationController.toolbarHidden?.should == false
  end

  it "hidden" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: false)
    screen.on_load
    screen.navigationController.toolbarHidden?.should == true
  end

  it "adds a single item" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    screen.on_load
    screen.set_toolbar_button([{title: "Testing Toolbar"}])

    screen.navigationController.toolbar.items.should.be.instance_of Array
    screen.navigationController.toolbar.items.count.should == 1
    screen.navigationController.toolbar.items.first.should.be.instance_of UIBarButtonItem
    screen.navigationController.toolbar.items.first.title.should == "Testing Toolbar"
  end

  it "adds multiple items" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    screen.set_toolbar_buttons [{title: "Testing Toolbar"}, {title: "Another Test"}]

    screen.navigationController.toolbar.items.should.be.instance_of Array
    screen.navigationController.toolbar.items.count.should == 2
    screen.navigationController.toolbar.items.first.title.should == "Testing Toolbar"
    screen.navigationController.toolbar.items.last.title.should == "Another Test"
  end

  it "shows the toolbar when setting items" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: false)
    screen.on_load
    screen.navigationController.toolbarHidden?.should == true
    screen.set_toolbar_button([{title: "Testing Toolbar"}], false)
    screen.navigationController.toolbarHidden?.should == false
  end

  it "doesn't show the toolbar when passed nil" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    screen.on_load
    screen.set_toolbar_button(nil, false)
    screen.navigationController.toolbarHidden?.should == true
  end

  it "doesn't show the toolbar when passed false" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    screen.on_load
    screen.set_toolbar_button(false, false)
    screen.navigationController.toolbarHidden?.should == true
  end

  it "hides the toolbar when passed nil" do
    screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    screen.on_load
    screen.set_toolbar_button([{title: "Testing Toolbar"}], false)
    screen.navigationController.toolbarHidden?.should == false
    screen.set_toolbar_button(nil, false)
    screen.navigationController.toolbarHidden?.should == true
  end

end

describe "toolbar tinted buttons" do
  before do
    @screen = HomeScreen.new(nav_bar: true, modal: true, toolbar: true)
    @screen.on_load
  end

  it "creates string toolbar buttons with tint colors" do
    @screen.set_toolbar_button([{title: "Testing Toolbar", tint_color: UIColor.redColor}])
    @screen.navigationController.toolbar.items.first.tintColor.should == UIColor.redColor
  end

  it "creates image toolbar buttons with tint colors" do
    @screen.set_toolbar_button([{image: UIImage.imageNamed("list"), tint_color: UIColor.redColor}])
    @screen.navigationController.toolbar.items.first.tintColor.should == UIColor.redColor
  end

  it "creates system item toolbar buttons with tint colors" do
    @screen.set_toolbar_button([{system_item: :reply, tint_color: UIColor.redColor}])
    @screen.navigationController.toolbar.items.first.tintColor.should == UIColor.redColor
  end

end

describe "child screen management" do
  before do
    @screen = HomeScreen.new
    @child = BasicScreen.new
  end

  it "#add_child_screen" do
    autorelease_pool do
      @screen.add_child_screen @child
    end
    @screen.childViewControllers.should.include(@child)
    @screen.childViewControllers.length.should == 1
    @child.parent_screen.should == @screen
  end

  it "#remove_child_screen" do
    @screen.add_child_screen @child
    @screen.childViewControllers.should.include(@child)
    @screen.remove_child_screen @child
    @screen.childViewControllers.length.should == 0
    @child.parent_screen.should == nil
  end

end


