require "manifique"
require "down"

module AppCatalogManager
  class UpdateMetadata < AppCatalogManagerService
    def initialize(app:)
      @app = app
    end

    def call
      agent = Manifique::Agent.new(url: @app.url)
      metadata = agent.fetch_metadata

      @app.name = metadata.name

      [:name, :short_name, :description, :theme_color, :background_color,
       :display, :start_url, :scope, :share_target, :icons].each do |prop|
        @app.metadata[prop] = metadata.send(prop) if prop
      end

      @app.save!

      # TODO move icon downloads to separate, async job

      if icon = metadata.select_icon(sizes: "256x256") ||
         icon = metadata.select_icon(sizes: "192x192")
        attach_remote_image(:icon, icon)
        # TODO elsif get whatever is available
      end

      if apple_touch_icon = metadata.select_icon(purpose: "apple-touch-icon")
        attach_remote_image(:apple_touch_icon, apple_touch_icon)
      end
    rescue Manifique::Error => e
      msg = "Fetching web app manifest failed for #{e.url}: #{e.type}"
      Rails.logger.warn(msg)
      Sentry.capture_message(msg) if Setting.sentry_enabled?
      false
    end

    def attach_remote_image(attachment_name, icon)
      if icon['src'].start_with?("http")
        download_url = icon['src']
      else
        download_url = "#{@app.url}/#{icon["src"].gsub(/^\//,'')}"
      end
      filename = "#{attachment_name}-#{Time.now.to_i}.png"
      key = "web_apps/#{@app.id}/icons/#{filename}"

      begin
        tempfile = Down.download(download_url)
        @app.send(attachment_name).attach(key: key, io: tempfile, filename: filename)
      rescue Down::NotFound
        msg = "Download of \"#{attachment_name}\" failed: NotFound error for #{download_url}"
        Rails.logger.warn(msg)
        Sentry.capture_message(msg)
      rescue => e
        Rails.logger.warn "Saving attachment \"#{attachment_name}\" failed: \"#{e.message}\""
        Sentry.capture_exception(e) if Setting.sentry_enabled?
      end
    end
  end
end
