module JamRuby
  class Feed < ActiveRecord::Base

    belongs_to :recording, class_name: "JamRuby::Recording", inverse_of: :feed, foreign_key: 'recording_id'
    belongs_to :music_session, class_name: "JamRuby::MusicSession", inverse_of: :feed, foreign_key: 'music_session_id'

    FIXNUM_MAX = (2**(0.size * 8 -2) -1)
    SORT_TYPES = ['date', 'plays', 'likes']
    TIME_RANGES = { "today" => 1 , "week" => 7, "month" => 30, "all" => 0}
    TYPE_FILTERS = ['music_session', 'recording', 'all']

    def self.index(user, params = {})

      limit = params[:limit]
      limit ||= 20
      limit = limit.to_i

      # validate sort
      sort = params[:sort]
      sort ||= 'date'
      raise "not valid sort #{sort}" unless SORT_TYPES.include?(sort)

      time_range = params[:time_range]
      time_range ||= 'all'
      raise "not valid time_range #{time_range}" unless TIME_RANGES.has_key?(time_range)

      type_filter = params[:type]
      type_filter ||= 'all'
      raise "not valid type #{type_filter}" unless TYPE_FILTERS.include?(type_filter)

      target_user = params[:user]
      target_band = params[:band]

      # TODO: SPEED UP QUERY. CURRENTLY TAKES FOR EVER.
      #if target_user or target_band
      #  return { query: [], next_page: nil}
      #end

      #query = Feed.includes([:recording]).includes([:music_session]).limit(limit)
      query = Feed.joins("LEFT OUTER JOIN recordings ON recordings.id = feeds.recording_id")
                  .joins("LEFT OUTER JOIN music_sessions ON music_sessions.id = feeds.music_session_id")
                  .limit(limit)
                  .where('feeds.recording_id is NULL OR (recordings.all_discarded = false AND recordings.deleted = false)') # remove any 'all_discarded recordings from the search results' or 'deleted'

      query = Search.scope_schools_together_feeds(query, user)

      # handle sort
      if sort == 'date'
        query = query.order('feeds.id DESC')
      elsif sort == 'plays'
        query = query.order("COALESCE(recordings.play_count, music_sessions.play_count) DESC")
      elsif sort == 'likes'
        query = query.order("COALESCE(recordings.like_count, music_sessions.like_count) DESC")
      else
        raise "sort not implemented: #{sort}"
      end

      # handle time range
      days = TIME_RANGES[time_range]
      if days > 0
        query = query.where("feeds.created_at > NOW() - '#{days} day'::INTERVAL")
      end

      # handle type filters
      if type_filter == 'music_session'
        query = query.where('feeds.music_session_id is not NULL')
      elsif type_filter == 'recording'
        query = query.where('feeds.recording_id is not NULL')
      end


      if target_user
        query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND claimed_recordings.discarded = FALSE AND (claimed_recordings.user_id = '#{target_user}' OR (recordings.band_id IN (SELECT band_id FROM bands_musicians where user_id='#{target_user}')))")
        query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions.id = music_sessions_user_history.music_session_id AND music_sessions_user_history.user_id = '#{target_user}'")
        query = query.group("feeds.id")
        if sort == 'plays'
          query = query.group("COALESCE(recordings.play_count, music_sessions.play_count)")
        elsif sort == 'likes'
          query = query.group("COALESCE(recordings.like_count, music_sessions.like_count)")
        end
        query = query.where('feeds.recording_id is NULL OR claimed_recordings.id IS NOT NULL')
        query = query.where('feeds.music_session_id is NULL OR music_sessions_user_history.id IS NOT NULL')

      elsif target_band

        query = query.joins("LEFT OUTER JOIN claimed_recordings ON feeds.recording_id = claimed_recordings.recording_id AND claimed_recordings.discarded = FALSE AND recordings.band_id = '#{target_band}'")
        query = query.where("feeds.music_session_id IS NULL OR music_sessions.band_id = '#{target_band}'")
        query = query.group("feeds.id")
        if sort == 'plays'
          query = query.group("COALESCE(recordings.play_count, music_sessions.play_count)")
        elsif sort == 'likes'
          query = query.group("COALESCE(recordings.like_count, music_sessions.like_count)")
        end
        query = query.where('feeds.recording_id is NULL OR claimed_recordings.id IS NOT NULL')
        #query = query.where('music_sessions.id is NULL OR music_sessions_user_history.id IS NOT NULL')
      else
        query = query.joins('LEFT OUTER JOIN claimed_recordings ON feeds.recording_id = claimed_recordings.recording_id AND claimed_recordings.discarded = FALSE')
        query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions.id = music_sessions_user_history.music_session_id")
        query = query.group("feeds.id")
        if sort == 'plays'
          query = query.group("COALESCE(recordings.play_count, music_sessions.play_count)")
        elsif sort == 'likes'
          query = query.group("COALESCE(recordings.like_count, music_sessions.like_count)")
        end
        query = query.where('feeds.recording_id is NULL OR claimed_recordings.is_public = TRUE')
        query = query.where('feeds.music_session_id is NULL OR music_sessions.musician_access = TRUE')
        query = query.where('feeds.music_session_id is NULL OR music_sessions_user_history.id IS NOT NULL')
      end

      current_page = params[:next_page].nil? ? 1 : params[:next_page].to_i
      next_page = current_page + 1

      # will_paginate gem0
      query = query.limit(limit).offset((current_page - 1)* limit)

      if params[:hash]
        if query.length == 0  # no more results
          { query: query, next_page: nil}
        elsif query.length < limit  # no more results
          { query: query, next_page: nil}
        else
          { query: query, next_page: next_page }
        end
      else
        if query.length == 0  # no more results
          [query, nil]
        elsif query.length < limit  # no more results
          [query, nil]
        else
          [query, next_page]
        end
      end
    end
  end
end