class SvelteOnRails::Lib::ViewHelperSupport

def cache_key

def cache_key
  @cache_key
end

def cache_key_primary

def cache_key_primary
  @cache_key_primary
end

def custom_cache_key

def custom_cache_key
  if @options[:cache_key]
    k2 = (@options[:cache_key])
    keys = k2.is_a?(Array) ? k2 : [k2]
    keys.map do |k|
      if k.is_a?(ActiveRecord::Base)
        "#{k.class.name}#{k.id}"
      elsif k == nil
        'nil'
      elsif k.present?
        k.to_s
      else
        "empty-#{k.class}"
      end
    end.join('-')
  end
end

def debug?

def debug?
  @options[:debug]
end

def debug_log(message)

def debug_log(message)
  if debug?
    Rails.logger.debug("  [svelte_component] #{message} (#{elapsed_milliseconds} ms)")
  end
end

def determine_ssr

def determine_ssr
  _ssr = if @options.key?(:ssr)
           if @conf.watch_changes?
             unless [true, false, :auto].include?(@options[:ssr])
               raise "Only true, false, or :auto are allowed for the argument #ssr"
             end
           end
           @options[:ssr]
         else
           @conf.ssr
         end
  _ssr == :auto ? request.headers[conf.non_ssr_request_header].blank? : _ssr
end

def elapsed_milliseconds

def elapsed_milliseconds
  ((Time.now - @start_time) * 1000).round(1)
end

def generate_cache_key

def generate_cache_key
  filename_part = [
    "#{filename.split('/').last}.svelte",
    Zlib.crc32(filename).to_s(36),
    custom_cache_key
  ].compact.join('-')
  @cache_key_primary = [
    conf.redis_cache_store[:namespace] ? conf.redis_cache_store[:namespace] : "svelte-on-rails:#{Rails.env rescue 'unknown'}",
    filename_part,
  ].join(':')
  last_part = [
    (@conf.watch_changes? ? Zlib.crc32(File.read(@conf.ssr_dist_folder.join('last_mtime'))).to_s(36) : nil),
    @args_checksum
  ].compact.join('-')
  @cache_key = [@cache_key_primary, last_part].join(':')
end

def initialize(file, props, html_options, options, request, caching = false)

def initialize(file, props, html_options, options, request, caching = false)
  @start_time = Time.now
  @conf = SvelteOnRails::Configuration.instance
  utils = SvelteOnRails::Lib::Utils
  utils.validate_filename(file) if @conf.watch_changes?
  @filename = (file.match(/\.svelte$/) ? file[0..-8] : file)
  @args_checksum = [
    Zlib.crc32(props.to_json).to_s(36),
    Zlib.crc32(options.to_json).to_s(36)
  ].join('-')
  @svelte_props = props ||= {}
  @options, @html_options = prepare_options(
    options,
    html_options,
    RENDER_OPTIONS
  )
  @request = request
  @ssr = determine_ssr
  # precompile
  if !Dir.exist?(@conf.ssr_dist_folder) || @conf.watch_changes?
    SvelteOnRails::Lib::Utils.watch_changes_and_precompile
  end
  # caching
  if caching
    raise '[svelte-on-rails] Caching required but Redis is not defined' unless defined?(Redis)
  else
    raise '[svelte-on-rails] :expires_in is not allowed for this helper' if @options.key?(:expires_in)
    raise '[svelte-on-rails] :cache_key is not allowed for this helper' if @options.key?(:cache_key)
    return
  end
  generate_cache_key
end

def log_rendering(message)

def log_rendering(message)
  Rails.logger.info "  #{message} (#{elapsed_milliseconds}ms)"
end

def prepare_options(options, html_options, available_options)

def prepare_options(options, html_options, available_options)
  # html options
  ht_opts = html_options.dup.deep_merge(
    {
      data: {
        svelte_component: "/#{conf.components_folder + filename}",
        controller: 'svelte-on-rails'
      }
    }
  )
  ht_opts[:class] = "#{ht_opts[:class]} svelte-component".strip
  ht_opts[:data][:props] = @svelte_props.to_json
  ht_opts[:data][:svelte_status] = 'do-not-hydrate-me' if options[:hydrate] == false
  # render options
  opts = {}
  options.each do |k, v|
    _k = k.to_sym
    if available_options.include?(_k)
      opts[_k] = v
    else
      raise("Unknown option: #{k}")
    end
  end
  
  [opts, ht_opts]
end

def redis_expiration_seconds

def redis_expiration_seconds
  (conf.redis_cache_store[:expires_in] || @options[:expires_in] || 1.hour).to_i
end

def render(view_context, &block)

def render(view_context, &block)
  debug_log("Rendering component: #{filename}")
  r = view_context.instance_eval(&block)
  log_rendering("Rendered #{filename}.svelte #{'as empty element that will be mounted on the client side' unless ssr?}")
  r
end

def render_cached(view_context, &block)

def render_cached(view_context, &block)
  cached_content = conf.redis_instance.get(cache_key)
  # debug
  if debug?
    debug_log("Rendering component: «#{filename}», cache_key: «#{custom_cache_key}»")
    debug_log("Redis configuration: #{conf.redis_cache_store}")
    ttl = conf.redis_instance.ttl(cache_key)
    key_stat = if cached_content.present?
                 'has content'
               elsif conf.redis_instance.exists(cache_key)
                 'exists but no content'
               else
                 'not exists'
               end
    ttl_stat = if conf.redis_instance.exists(cache_key)
                 ", ttl was: #{ttl} seconds, now set to: #{redis_expiration_seconds} seconds"
               end
    debug_log("Cache key: «#{cache_key}» (#{key_stat}#{ttl_stat})")
  end
  # increase expired time
  conf.redis_instance.expire(cache_key, redis_expiration_seconds)
  # render
  log_message = '?'
  res = if cached_content
          log_message = "Returned #{filename}.svelte from cache"
          cached_content.html_safe
        else
          log_message = "Rendered #{filename}.svelte and stored to cache"
          debug_log("cache recalculating for key: #{cache_key}")
          r = view_context.instance_eval(&block)
          debug_log("cache recalculated")
          conf.redis_instance.set(cache_key, r)
          r
        end
  log_rendering(log_message)
  res
end

def render_ssr

def render_ssr
  renderer = SvelteOnRails::Renderer.new(filename)
  res = renderer.render(@svelte_props)
  if res['html'].is_a?(Array)
    res['html'] = res['html'].join
    res
  else
    res
  end
end

def ssr?

def ssr?
  @ssr
end