app/models/photo.rb
# frozen_string_literal: true

#   Copyright (c) 2009, Diaspora Inc.  This file is
#   licensed under the Affero General Public License version 3 or later.  See
#   the COPYRIGHT file.

class Photo < ApplicationRecord
  include Diaspora::Federated::Base
  include Diaspora::Shareable

  # NOTE API V1 to be extracted
  acts_as_api
  api_accessible :backbone do |t|
    t.add :id
    t.add :guid
    t.add :created_at
    t.add :author
    t.add lambda { |photo|
      {
        small:  photo.url(:thumb_small),
        medium: photo.url(:thumb_medium),
        large:  photo.url(:scaled_full),
        raw:    photo.url
      }
    }, as: :sizes
    t.add lambda { |photo|
      {
        height: photo.height,
        width:  photo.width
      }
    }, as: :dimensions
    t.add lambda { |photo|
      {
        id: photo.status_message.id
      } if photo.status_message
    }, as: :status_message
  end

  mount_uploader :processed_image, ProcessedImage
  mount_uploader :unprocessed_image, UnprocessedImage
  attr_accessor :keep_original_format

  belongs_to :status_message, foreign_key: :status_message_guid, primary_key: :guid, optional: true
  validates_associated :status_message
  delegate :author_name, to: :status_message, prefix: true

  validate :ownership_of_status_message

  before_destroy :ensure_user_picture
  after_destroy :clear_empty_status_message

  after_commit on: :create do
    queue_processing_job if author.local?
  end

  scope :on_statuses, ->(post_guids) {
    where(status_message_guid: post_guids)
  }

  def clear_empty_status_message
    if status_message&.text_and_photos_blank?
      status_message.destroy
    else
      true
    end
  end

  def ownership_of_status_message
    message = StatusMessage.find_by(guid: status_message_guid)
    return unless status_message_guid && message && diaspora_handle != message.diaspora_handle

    errors.add(:base, "Photo must have the same owner as status message")
  end

  def self.diaspora_initialize(params={})
    photo = new(params.to_hash.stringify_keys.slice(*column_names, "author"))
    photo.random_string = SecureRandom.hex(10)

    if params[:user_file]
      image_file = params.delete(:user_file)
      photo.unprocessed_image.store! image_file
    elsif params[:image_url]
      photo.remote_unprocessed_image_url = params[:image_url]
      photo.unprocessed_image.store!
    end

    photo.update_remote_path

    photo
  end

  def processed?
    processed_image.path.present?
  end

  def update_remote_path
    remote_path = if unprocessed_image.url.match(%r{^https?://})
                    unprocessed_image.url
                  else
                    "#{AppConfig.pod_uri.to_s.chomp('/')}#{unprocessed_image.url}"
                  end

    name_start = remote_path.rindex "/"
    self.remote_photo_path = "#{remote_path.slice(0, name_start)}/"
    self.remote_photo_name = remote_path.slice(name_start + 1, remote_path.length)
  end

  def url(name=nil)
    if remote_photo_path.present? && remote_photo_name.present?
      name = "#{name}_" if name
      image_url = remote_photo_path + name.to_s + remote_photo_name
      camo_image_url(image_url)
    elsif processed?
      processed_image.url(name)
    else
      unprocessed_image.url(name)
    end
  end

  def ensure_user_picture
    profiles = Profile.where(image_url: url(:thumb_large))
    profiles.each { |profile|
      profile.image_url = nil
      profile.save
    }
  end

  def queue_processing_job
    Workers::ProcessPhoto.perform_async(id)
  end

  def self.visible(current_user, person, limit=:all, max_time=nil)
    photos = if current_user
               current_user.photos_from(person, limit: limit, max_time: max_time)
             else
               Photo.where(author_id: person.id, public: true)
             end
    photos.where(pending: false).order("created_at DESC")
  end

  private

  def camo_image_url(image_url)
    if AppConfig.privacy.camo.proxy_remote_pod_images?
      Diaspora::Camo.image_url(image_url)
    else
      image_url
    end
  end
end
