class Screenshot < ApplicationRecord
  belongs_to :package, inverse_of: :screenshots
  belongs_to :user, inverse_of: :screenshots

  # Default sorting:
  # - unapproved first (to see them at the top when moderating)
  # - otherwise show newest first
  default_scope { order(approved: :asc, hidden: :asc, created_at: :desc) }

  scope :approved, -> { where(approved: true) }
  scope :visible, -> { where(hidden: false) }
  scope :publicly, -> { where(hidden: false, approved: true) }

  # Shrine
  include ImageUploader::Attachment(:simage) # adds an `simage` virtual attribute

  # Return caption for full-screen screenshots.
  # Takes the description of a screenshot if available.
  # Otherwise it falls back to the general description of its package.
  def caption
    if description.present?
      description
    else
      package.description
    end
  end

  # Future use…
  # def uploader
  #   if self.user
  #     self.user.name
  #   else
  #     'Anonymous'
  #   end
  # end

  # Long status text for public users
  def status
    text = 'This image '

    text << if approved
              'is public'
            else
              'has to be moderated before being publicly visible'
            end

    text << ' (and was requested to be removed)' if markedfordelete

    text
  end

  # Brief text describing the status of this screenshots (for admins)
  def adminstatus
    if approved
      'Public'
    else
      # fa_icon('hourglass') + 'Waiting for approval'
      'Unapproved'
    end
  end

  # Publish a screenshot from the moderation queue
  def approve!
    self.approved = true
    save!
  end

  # Hide a screenshot from the public. Moderator level can do this.
  def hide!
    self.hidden = true
    save!
  end

  def unhide!
    self.hidden = false
    save!
  end

  # Get the newest screenshots regardless of the package it belongs to
  def self.newest
    order(created_at: :desc)
  end

  # Return the part of the version up to the first - or +
  def upstream_version
    version.split(/[-+]/).first
  end

  # Returns the path to this screenshot's image on disk
  def disk_path
    ActiveStorage::Blob.service.send(:path_for, image.key)
  end

  # Returns the MD5 hex digest of the current screenshot's data
  def checksum
    # local files stored on disk:
    # url = "#{Rails.root}/public/#{attachment.path}"
    Digest::MD5.hexdigest(disk_path)

    # remote files stored on another person's computer:
    # url = attachment.url
    # Digest::MD5.base64digest(Net::HTTP.get(URI(url)))
  end

  private

  # Validator that checks if the image has already been uploaded.
  # A generic uniqueness validator does not work because it would attribute
  # the error to the :image_fingerprint field and not the actual :image field.
  # Currently this check makes sure that the same screenshot is not uploaded
  # twice for the same package. However it allows the screenshot to be uploaded
  # for two different packages. Restricting that further may happen later.
  def validate_image_is_unique
    # Look for images with the same checksum / image_fingerprint
    if (screenshot = Screenshot.find_by(image_fingerprint: image_fingerprint,
                                        package_id: package.id)) && !(screenshot.id == id)
      errors.add(:image, 'has already been uploaded for this package')
    end
  end
end
