module Spotlight
  ##
  # Base page class. See {Spotlight::AboutPage}, {Spotlight::FeaturePage}, {Spotlight::HomePage}
  # rubocop:disable Metrics/ClassLength
  class Page < ActiveRecord::Base
    MAX_PAGES = 50

    extend FriendlyId
    friendly_id :title, use: [:slugged, :scoped, :finders, :history], scope: [:exhibit, :locale]

    belongs_to :exhibit, touch: true
    belongs_to :created_by, class_name: Spotlight::Engine.config.user_class, optional: true
    belongs_to :last_edited_by, class_name: Spotlight::Engine.config.user_class, optional: true
    belongs_to :thumbnail, class_name: 'Spotlight::FeaturedImage', dependent: :destroy, optional: true
    belongs_to :default_locale_page, class_name: 'Spotlight::Page', optional: true, inverse_of: :translated_pages
    has_many :translated_pages,
             class_name: 'Spotlight::Page',
             foreign_key: :default_locale_page_id,
             dependent: :destroy,
             inverse_of: :default_locale_page

    validates :weight, inclusion: { in: proc { 0..Spotlight::Page::MAX_PAGES } }

    default_scope { order('weight ASC') }
    scope :at_top_level, -> { where(parent_page_id: nil) }
    scope :published, -> { where(published: true) }
    scope :recent, -> { order('updated_at DESC').limit(10) }
    scope :for_locale, ->(locale = I18n.locale) { unscope(where: :locale).where(locale: locale) }
    scope :for_default_locale, -> { for_locale(I18n.default_locale) }

    has_one :lock, as: :on, dependent: :destroy
    sir_trevor_content :content
    has_paper_trail

    accepts_nested_attributes_for :thumbnail, update_only: true, reject_if: proc { |attr| attr['iiif_tilesource'].blank? }

    # display_sidebar should be set to true by default
    before_create do
      self.content ||= [].to_json
      self.display_sidebar = true
    end

    after_update :update_translated_pages_weights_and_parent_page

    def content_changed!
      @content = nil
    end

    def content=(content)
      if content.is_a? Array
        super content.to_json
      else
        super
      end
      content_changed!
    end

    def content?
      self[:content].present? && content.present?
    end
    alias has_content? content?

    def display_sidebar?
      true
    end

    def featured_image
      nil
    end

    def thumbnail_image_url
      return unless thumbnail && thumbnail.iiif_url
      thumbnail.iiif_url
    end

    # explicitly set the partial path so that
    # we don't have to duplicate view logic.
    def to_partial_path
      'spotlight/pages/page'
    end

    def feature_page?
      is_a? FeaturePage
    end

    def about_page?
      is_a? AboutPage
    end

    def home_page?
      is_a? HomePage
    end

    def top_level_page?
      try(:parent_page).blank?
    end

    def top_level_page_or_self
      parent_page || self
    end

    def should_generate_new_friendly_id?
      super || (title_changed? && persisted?)
    end

    def should_display_title?
      title.present?
    end

    def lock!(user)
      create_lock(by: user).tap(&:current_session!) unless lock.present?
    end

    def updated_after?(other_page)
      return false unless other_page
      updated_at > other_page.updated_at
    end

    def translated_page_for(locale)
      translated_pages.for_locale(locale).first
    end

    def clone_for_locale(locale)
      dup.tap do |np|
        np.locale = locale
        np.default_locale_page = self
        np.published = false

        if !top_level_page? && (parent_translation = parent_page.translated_page_for(locale)).present?
          np.parent_page = parent_translation
        end

        child_pages.for_locale(locale).update(parent_page: np) if top_level_page? && respond_to?(:child_pages)
      end
    end

    private

    def update_translated_pages_weights_and_parent_page
      return unless locale.to_sym == I18n.default_locale
      return unless saved_change_to_weight? || saved_change_to_parent_page_id?
      update_params = {}
      update_params[:weight] = weight if saved_change_to_weight?
      update_params[:parent_page_id] = parent_page_id if saved_change_to_parent_page_id?
      translated_pages.update(update_params)
    end
  end
  # rubocop:enable Metrics/ClassLength
end