module RunbyPace

  class PaceTime
    attr_reader :time_s, :minutes_part, :seconds_part

    def initialize(time)
      if time.is_a?(String) || time.is_a?(Symbol)
        init_from_string(time)
      elsif time.is_a?(PaceTime)
        init_from_clone(time)
      end
    end

    # @param [numeric] total_seconds
    def self.from_seconds(total_seconds)
      minutes = total_seconds.abs.to_i / 60
      seconds = total_seconds.abs.to_i % 60
      PaceTime.new("#{'%02d' % minutes}:#{'%02d' % seconds}")
    end

    # @param [numeric] total_minutes
    def self.from_minutes(total_minutes)
      self.from_seconds(total_minutes * 60.0)
    end

    def to_s
      @time_s
    end

    def total_seconds
      @minutes_part * 60 + @seconds_part
    end

    def total_minutes
      @minutes_part + (@seconds_part / 60.0)
    end

    # @param [PaceTime] value
    def -(value)
      if value.is_a?(PaceTime)
        PaceTime.from_seconds(total_seconds - value.total_seconds)
      end
    end

    # @param [PaceTime] value
    def +(value)
      if value.is_a?(PaceTime)
        PaceTime.from_seconds(total_seconds + value.total_seconds)
      end
    end

    def ==(value)
      if value.is_a?(PaceTime)
        total_seconds == value.total_seconds
      elsif value.is_a?(String)
        @time_s == value
      end
    end

    def almost_equals?(other_time, tolerance_time = '00:01')
      if other_time.is_a?(String)
        other_time = PaceTime.new(other_time)
      end
      tolerance = PaceTime.new(tolerance_time)
      self >= (other_time - tolerance) && self <= (other_time + tolerance)
    end

    def >(value)
      if value.is_a?(PaceTime)
        total_seconds > value.total_seconds
      end
    end

    def >=(value)
      if value.is_a?(PaceTime)
        total_seconds >= value.total_seconds
      end
    end

    def <(value)
      if value.is_a?(PaceTime)
        total_seconds < value.total_seconds
      end
    end

    def <=(value)
      if value.is_a?(PaceTime)
        total_seconds <= value.total_seconds
      end
    end

    private

    def init_from_string(time)
      time = time.to_s.strip.chomp
      is_negative = false

      if time[0] == '-'
        is_negative = true
        time = time[1..-1]
      end

      if time.match(/^\d?\d:\d\d$/)
        parts = time.split(':')
        @minutes_part = parts[0].to_i
        @seconds_part = parts[1].to_i
      elsif time.match(/^\d+$/)
        @minutes_part = time.to_i
        @seconds_part = 0
      elsif time.match(/^\d+[,\. ]\d+$/)
        parts = time.split(/[,\. ]/)
        @minutes_part = parts[0].to_i
        @seconds_part = (parts[1].to_i / 10.0 * 60).to_i
      else
        raise 'Invalid time format'
      end

      raise 'Minutes must be less than 100' if @minutes_part > 99
      raise 'Seconds must be less than 60' if @seconds_part > 59
      if is_negative
        @minutes_part *= -1
        @seconds_part *= -1
      end
      @time_s = "#{@minutes_part.to_s.rjust(2, '0')}:#{@seconds_part.to_s.rjust(2, '0')}"
    end

    # @param [PaceTime] time
    def init_from_clone(time)
      @time_s = time.time_s
      @minutes_part = time.minutes_part
      @seconds_part = time.seconds_part
    end
  end
end