require_relative "version_cut"
require_relative "version_interval"

module VersionParser
  # A constraint is made of an operator followed by a version string.
  CONSTRAINT_REGEXP = Regexp.new("(?<op>[><=]+) *(?<version>#{SemanticVersion::VERSION_PATTERN})").freeze

  def self.parse(versionstring)
    if (versionstring == "=*")
      # special case = All Versions
      return VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), AboveAll.new())
    end

    version_items = versionstring.split(" ")
    interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), AboveAll.new())
    version_items.each do |version_item|
      matches = version_item.match CONSTRAINT_REGEXP
      raise SemverDialects::InvalidConstraintError, versionstring if matches.nil?
      version_string = matches[:version]
      case matches[:op]
      when ">="
        new_interval = VersionInterval.new(IntervalType::LEFT_CLOSED | IntervalType::RIGHT_OPEN, VersionCut.new(version_string), AboveAll.new())
        interval = interval.intersect(new_interval)
      when "<="
        new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_CLOSED, BelowAll.new(), VersionCut.new(version_string))
        interval = interval.intersect(new_interval)
      when "<"
        new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), VersionCut.new(version_string))
        interval = interval.intersect(new_interval)
      when ">"
        new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, VersionCut.new(version_string), AboveAll.new())
        interval = interval.intersect(new_interval)
      when "=", "=="
        new_interval = VersionInterval.new(IntervalType::LEFT_CLOSED | IntervalType::RIGHT_CLOSED, VersionCut.new(version_string), VersionCut.new(version_string))
        interval = interval.intersect(new_interval)
      end
    end
    interval
  end
end
