<commit_before># frozen_string_literal: true

require_relative "../browser"
require "rack"
require "erb"
require "json"

module RubyEventStore
  module Browser
    class App
      def self.for(
        event_store_locator:,
        host: nil,
        path: nil,
        api_url: nil,
        environment: nil,
        related_streams_query: DEFAULT_RELATED_STREAMS_QUERY
      )
        Rack::Builder.new do
          use Rack::Static,
              urls: {
                "/ruby_event_store_browser.js" => "ruby_event_store_browser.js",
                "/bootstrap.js" => "bootstrap.js"
              },
              root: "#{__dir__}/../../../public"
          run App.new(
                event_store_locator: event_store_locator,
                related_streams_query: related_streams_query,
                host: host,
                root_path: path,
                api_url: api_url
              )
        end
      end

      def initialize(event_store_locator:, related_streams_query:, host:, root_path:, api_url:)
        @event_store_locator = event_store_locator
        @related_streams_query = related_streams_query
        @host = host
        @root_path = root_path
        @api_url = api_url
      end

      def call(env)
        request = Rack::Request.new(env)
        routing = Routing.from_configuration(host, root_path).with_request(request)

        router = Router.new
        router.add_route("GET", "/api/events/:event_id") do |params|
          json Event.new(event_store: event_store, event_id: params.fetch("event_id"))
        end
        router.add_route("GET", "/api/streams/:stream_name") do |params|
          json GetStream.new(
                 stream_name: params.fetch("stream_name"),
                 routing: routing,
                 related_streams_query: related_streams_query
               )
        end
        router.add_route("GET", "/api/streams/:stream_name/relationships/events") do |params|
          json GetEventsFromStream.new(
                 event_store: event_store,
                 routing: routing,
                 stream_name: params.fetch("stream_name"),
                 page: params["page"]
               )
        end
        %w[/ /events/:event_id /streams/:stream_name].each do |starting_route|
          router.add_route("GET", starting_route) do
            erb bootstrap_html, root_path: routing.root_path, settings: settings(routing)
          end
        end
        router.handle(request)
      rescue EventNotFound, Router::NoMatch
        not_found
      end

      private

      attr_reader :event_store_locator, :related_streams_query, :host, :root_path, :api_url

      def event_store
        event_store_locator.call
      end

      def bootstrap_html
        <<~HTML
        <!DOCTYPE html>
        <html>
          <head>
            <title>RubyEventStore::Browser</title>
            <meta name="ruby-event-store-browser-settings" content="<%= Rack::Utils.escape_html(JSON.dump(settings)) %>">
          </head><commit_msg>Reduce surface area a bit more<commit_after># frozen_string_literal: true

require_relative "../browser"
require "rack"
require "erb"
require "json"

module RubyEventStore
  module Browser
    class App
      def self.for(
        event_store_locator:,
        host: nil,
        path: nil,
        api_url: nil,
        environment: nil,
        related_streams_query: DEFAULT_RELATED_STREAMS_QUERY
      )
        Rack::Builder.new do
          use Rack::Static,
              urls: {
                "/ruby_event_store_browser.js" => "ruby_event_store_browser.js",
                "/bootstrap.js" => "bootstrap.js"
              },
              root: "#{__dir__}/../../../public"
          run App.new(
                event_store_locator: event_store_locator,
                related_streams_query: related_streams_query,
                host: host,
                root_path: path,
                api_url: api_url
              )
        end
      end

      def initialize(event_store_locator:, related_streams_query:, host:, root_path:, api_url:)
        @event_store_locator = event_store_locator
        @related_streams_query = related_streams_query
        @api_url = api_url
        @routing = Routing.from_configuration(host, root_path)
      end

      def call(env)
        request = Rack::Request.new(env)
        routing = @routing.with_request(request)

        router = Router.new
        router.add_route("GET", "/api/events/:event_id") do |params|
          json Event.new(event_store: event_store, event_id: params.fetch("event_id"))
        end
        router.add_route("GET", "/api/streams/:stream_name") do |params|
          json GetStream.new(
                 stream_name: params.fetch("stream_name"),
                 routing: routing,
                 related_streams_query: related_streams_query
               )
        end
        router.add_route("GET", "/api/streams/:stream_name/relationships/events") do |params|
          json GetEventsFromStream.new(
                 event_store: event_store,
                 routing: routing,
                 stream_name: params.fetch("stream_name"),
                 page: params["page"]
               )
        end
        %w[/ /events/:event_id /streams/:stream_name].each do |starting_route|
          router.add_route("GET", starting_route) do
            erb bootstrap_html, root_path: routing.root_path, settings: settings(routing)
          end
        end
        router.handle(request)
      rescue EventNotFound, Router::NoMatch
        not_found
      end

      private

      attr_reader :event_store_locator, :related_streams_query, :api_url

      def event_store
        event_store_locator.call
      end

      def bootstrap_html
        <<~HTML
        <!DOCTYPE html>
        <html>
          <head>
            <title>RubyEventStore::Browser</title>
            <meta name="ruby-event-store-browser-settings" content="<%= Rack::Utils.escape_html(JSON.dump(settings)) %>">
          </head>
{'fraction_non_alphanumeric': 0.09906759906759907, 'fraction_numerical': 0.0, 'mean_word_length': 1.951842751842752, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2274265', 'n_tokens_mistral': 1780, 'n_tokens_neox': 1727, 'n_words': 330}