# frozen_string_literal: true

# Copyright (C) 2014 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas 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 Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas 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 Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along

require_relative "../../spec_helper"

module Utils
  describe DatetimeRangePresenter do
    def overridden_presenter(datetime, zone_name)
      zone = ActiveSupport::TimeZone[zone_name]
      DatetimeRangePresenter.new(datetime, nil, :event, zone)
    end

    describe "#as_string" do
      it "can display a single datetime if theres no range" do
        datetime = Time.zone.parse("#{Time.zone.now.year}-01-01 12:00:00")
        presenter = DatetimeRangePresenter.new(datetime)
        expect(presenter.as_string).to eq("Jan 1 at 12pm")
      end

      it "does not include an extra space in the returned time" do
        time = Time.zone.parse("Tue, 14 Dec 2021 13:32:00 UTC +00:00")
        presenter = DatetimeRangePresenter.new(time)
        expect(presenter.as_string).to eq("Dec 14, 2021 at 1:32pm")
      end

      describe "with shortened midnight" do
        around do |example|
          Timecop.freeze(Time.zone.local(2014, 10, 1, 9, 30), &example)
        end

        it "omits the time for events when midnight is specified as shortened" do
          datetime = Time.zone.now.midnight
          presenter = DatetimeRangePresenter.new(datetime)
          expect(presenter.as_string(shorten_midnight: true)).to eq("Oct 1")
        end

        it "omits the time for due dates when midnight is shortened" do
          datetime = Time.zone.now.midnight - 1.minute
          presenter = DatetimeRangePresenter.new(datetime, nil, :due_date)
          expect(presenter.as_string(shorten_midnight: true)).to eq("Sep 30")
        end
      end

      it "ignores ranges for due dates" do
        datetime = Time.zone.parse("#{Time.zone.now.year}-01-01 12:00:00")
        endtime = datetime + 1.hour
        presenter = DatetimeRangePresenter.new(datetime, endtime, :due_date)
        expect(presenter.as_string).to eq("Jan 1 by 12pm")
      end

      it "handles ranges" do
        datetime = Time.zone.parse("#{Time.zone.now.year}-01-01 12:00:00")
        end_datetime = datetime + 2.days
        presenter = DatetimeRangePresenter.new(datetime, end_datetime)
        expect(presenter.as_string).to eq("Jan 1 at 12pm to Jan 3 at 12pm")
      end

      it "omits second date if start and end are on the same day" do
        datetime = Time.zone.parse("#{Time.zone.now.year}-01-01 12:00:00")
        end_datetime = datetime.advance(hours: 1)
        presenter = DatetimeRangePresenter.new(datetime, end_datetime)
        expect(presenter.as_string).to eq("Jan 1 from 12pm to 1pm")
      end

      it "includes the year if the current year isn't the same" do
        Timecop.travel(Time.utc(2014, 10, 1, 9, 30)) do
          nextyear = Time.zone.now.advance(years: 1)
          presenter = DatetimeRangePresenter.new(nextyear)
          expect(presenter.as_string).to eq("Oct 1, 2015 at 9:30am")
        end
      end

      it "accepts a timezone override" do
        datetime = Time.zone.parse("#{Time.zone.now.year}-01-01 12:00:00")
        mountain_presenter = overridden_presenter(datetime, "America/Denver")
        central_presenter = overridden_presenter(datetime, "America/Chicago")
        expect(mountain_presenter.as_string).to eq("Jan 1 at 5am")
        expect(central_presenter.as_string).to eq("Jan 1 at 6am")
      end

      it "uses the default timezone if none provided" do
        datetime = Time.zone.parse("#{Time.zone.now.year}-01-01 12:00:00")
        pre_zone = Time.zone
        Time.zone = "Mountain Time (US & Canada)"
        nilzone_presenter = DatetimeRangePresenter.new(datetime, nil, :event, nil)
        expect(nilzone_presenter.as_string).to eq("Jan 1 at 5am")
      ensure
        Time.zone = pre_zone
      end

      it "can deal with date boundaries in the override on time objects" do
        pre_zone = Time.zone
        Time.zone = "Alaska"
        Timecop.freeze(Time.utc(2014, 10, 1, 7, 30)) do
          datetime = Time.zone.now

          alaskan_presenter = DatetimeRangePresenter.new(datetime)
          mountain_presenter = overridden_presenter(datetime, "America/Denver")
          expect(alaskan_presenter.as_string).to eq("Sep 30 at 11:30pm")
          expect(mountain_presenter.as_string).to eq("Oct 1 at 1:30am")
        end
      ensure
        Time.zone = pre_zone
      end
    end
  end
end
