<commit_before>require 'zip'
require 'datacite/acts_as_doi_mintable'
require 'zenodo/acts_as_zenodo_depositable'

# Investigation "snapshot"
class Snapshot < ActiveRecord::Base

  belongs_to :resource, polymorphic: true
  has_one :content_blob, as: :asset, foreign_key: :asset_id

  before_create :set_snapshot_number

  # Must quack like an asset version to behave with DOI code
  alias_attribute :parent, :resource
  alias_attribute :parent_id, :resource_id
  alias_attribute :version, :snapshot_number

  delegate :md5sum, :sha1sum, to: :content_blob

  validates :snapshot_number, :uniqueness => { :scope =>  [:resource_type, :resource_id] }

  acts_as_doi_mintable
  acts_as_zenodo_depositable do |snapshot|
    snapshot.content_blob # The thing to be deposited
  end

  def metadata
    @ro_metadata ||= parse_metadata
  end

  def title
    metadata['title']
  end

  def description
    metadata['description']
  end

  def contributor
    Person.find(metadata['contributor']['uri'].match(/people\/([1-9][0-9]*)/)[1])
  end

  def creators
    if metadata['creators']
      metadata['creators'].map do |contributor|
        Person.find_by_id(contributor['uri'].match(/people\/([1-9][0-9]*)/)[1])
      end
    else
      []
    end
  end

  def related_people
    ([contributor] + creators).uniq
  end

  def all_related_people(node = metadata)
    people = []

    node.each do |k, v|
      if k == 'contributor'
        people << Person.find_by_id(v['uri'].match(/people\/([1-9][0-9]*)/)[1])
      elsif k == 'creators'
        people |= v.map { |p| Person.find_by_id(p['uri'].match(/people\/([1-9][0-9]*)/)[1]) }
      elsif v.is_a?(Hash)
        people |= all_related_people(v)
      elsif v.is_a?(Array)
        people |= v.map { |n| all_related_people(n) if n.is_a?(Hash) }.flatten
      end
    end

    people.uniq.compact
  end

  def research_object
    ROBundle::File.open(content_blob.filepath) do |ro|
      yield ro if block_given?
    end
  end

  def can_mint_doi?
    Seek::Config.doi_minting_enabled &&
         (resource.created_at + (Seek::Config.time_lock_doi_for || 0).to_i.days) <= Time.now
  end

  private

  def set_snapshot_number
    self.snapshot_number ||= (resource.snapshots.maximum(:snapshot_number) || 0) + 1
  end

  def doi_resource_type
    resource_type.downcase
  end

  def doi_resource_id
    "#{resource_id}.#{snapshot_number}"
  end

  def doi_target_url
    investigation_snapshot_url(resource, snapshot_number,
                               :host => Seek::Config.host_with_port,
                               :protocol => Seek::Config.host_scheme)<commit_msg>Use polymorphic_url<commit_after>require 'zip'
require 'datacite/acts_as_doi_mintable'
require 'zenodo/acts_as_zenodo_depositable'

# Investigation "snapshot"
class Snapshot < ActiveRecord::Base

  belongs_to :resource, polymorphic: true
  has_one :content_blob, as: :asset, foreign_key: :asset_id

  before_create :set_snapshot_number

  # Must quack like an asset version to behave with DOI code
  alias_attribute :parent, :resource
  alias_attribute :parent_id, :resource_id
  alias_attribute :version, :snapshot_number

  delegate :md5sum, :sha1sum, to: :content_blob

  validates :snapshot_number, :uniqueness => { :scope =>  [:resource_type, :resource_id] }

  acts_as_doi_mintable
  acts_as_zenodo_depositable do |snapshot|
    snapshot.content_blob # The thing to be deposited
  end

  def to_param
    snapshot_number.to_s
  end

  def metadata
    @ro_metadata ||= parse_metadata
  end

  def title
    metadata['title']
  end

  def description
    metadata['description']
  end

  def contributor
    Person.find(metadata['contributor']['uri'].match(/people\/([1-9][0-9]*)/)[1])
  end

  def creators
    if metadata['creators']
      metadata['creators'].map do |contributor|
        Person.find_by_id(contributor['uri'].match(/people\/([1-9][0-9]*)/)[1])
      end
    else
      []
    end
  end

  def related_people
    ([contributor] + creators).uniq
  end

  def all_related_people(node = metadata)
    people = []

    node.each do |k, v|
      if k == 'contributor'
        people << Person.find_by_id(v['uri'].match(/people\/([1-9][0-9]*)/)[1])
      elsif k == 'creators'
        people |= v.map { |p| Person.find_by_id(p['uri'].match(/people\/([1-9][0-9]*)/)[1]) }
      elsif v.is_a?(Hash)
        people |= all_related_people(v)
      elsif v.is_a?(Array)
        people |= v.map { |n| all_related_people(n) if n.is_a?(Hash) }.flatten
      end
    end

    people.uniq.compact
  end

  def research_object
    ROBundle::File.open(content_blob.filepath) do |ro|
      yield ro if block_given?
    end
  end

  def can_mint_doi?
    Seek::Config.doi_minting_enabled &&
         (resource.created_at + (Seek::Config.time_lock_doi_for || 0).to_i.days) <= Time.now
  end

  private

  def set_snapshot_number
    self.snapshot_number ||= (resource.snapshots.maximum(:snapshot_number) || 0) + 1
  end

  def doi_resource_type
    resource_type.downcase
  end

  def doi_resource_id
    "#{resource_id}.#{snapshot_number}"
  end

  def doi_target_url
    polymorphic_url([resource, self],
                    :host => Seek::Config.host_with_port,
                    :protocol => Seek::Config.host_scheme)
{'fraction_non_alphanumeric': 0.12464210727238023, 'fraction_numerical': 0.00954380606986066, 'mean_word_length': 3.2740619902120716, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, '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': '6473656', 'n_tokens_mistral': 1879, 'n_tokens_neox': 1803, 'n_words': 362}