# frozen_string_literal: true

require_relative "route/version"
require "sinatra/base"

module Sinatra
  module Resilient
    module Route
      class Error < StandardError; end

      module Helpers
        def ensure_sinatra_route
          unless env["sinatra.resilient.route"]
            Array(settings.routes[@request.request_method]).each do |pattern, conditions, _|
              break if process_route(pattern, conditions) { :found_route } == :found_route
            end
          end

          env["sinatra.route"] = env["sinatra.resilient.route"]
        end
      end

      Sinatra1StyleRenderer = ::Mustermann::AST::Translator.create do
        translate(:named_splat)      { "{+#{name}}"                           }
        translate(:splat)            { "*"                                    }
        translate(:char, :separator) { ::Mustermann::Sinatra.escape(payload)  }
        translate(:root)             { t(payload)                             }
        translate(:group)            { "(#{t(payload)})"                      }
        translate(:union)            { "(#{t(payload, join: "|")})" }
        translate(:optional)         { "#{t(payload)}?"                       }
        translate(Array)             { |join: ""| map { |e| t(e) }.join(join) }

        translate(:capture) do
          raise Mustermann::Error, "cannot render variables"      if node.is_a? :variable
          raise Mustermann::Error, "cannot translate constraints" if constraint || qualifier || convert

          ":#{name}"
        end
      end

      def self.registered(app)
        app.helpers Helpers

        app.before do
          ensure_sinatra_route
        end

        app.after do
          ensure_sinatra_route
        end
      end

      def route(verb, path, *)
        path = Mustermann.new(path) if path.is_a?(String)
        munged_path = Sinatra1StyleRenderer.translate(path.to_ast).to_s

        condition do
          env["sinatra.resilient.route"] = "#{verb} #{munged_path}"
          true
        end

        super
      end
    end
  end

  register Resilient::Route
end