module JamRuby
  class JamTrackSearch < BaseSearch

    cattr_accessor :jschema, :search_meta
    attr_accessor :user_counters

    KEY_QUERY = 'query'
    KEY_SEARCH_STR = 'search_str'
    KEY_RESULT_TYPES = 'result_types'
    KEY_SONGS = 'songs'
    KEY_ARTISTS = 'artists'
    KEY_RESULTS = 'results'
    KEY_RESULT_SETS = 'result_sets'
    KEY_PAGE_NUM = 'page_num'
    KEY_TOTAL_COUNT = 'total_count'
    KEY_PAGE_COUNT = 'page_count'
    KEY_PER_PAGE = 'per_page'
    PER_PAGE = 'development'==Rails.env ? 8 : 20
    KEY_GENRES = 'genres'
    KEY_INSTRUMENTS = 'instruments'
    KEY_LANGUAGE = 'language'
    KEY_ORIGINAL_ARTIST = 'original_artist'

    def self.json_schema
      return @@jschema ||= {
        KEY_QUERY => {
          KEY_SEARCH_STR => '',
          KEY_INSTRUMENTS => [],
          KEY_GENRES => [],
          KEY_LANGUAGE => '',
          KEY_ORIGINAL_ARTIST => '',
          KEY_RESULT_TYPES => [],
          KEY_PAGE_NUM => 1,
          KEY_PER_PAGE => PER_PAGE,
        },
        KEY_RESULT_SETS => {
          KEY_SONGS => {
            KEY_RESULTS => [],
            KEY_PAGE_NUM => 1,
            KEY_TOTAL_COUNT => 0,
            KEY_PAGE_COUNT => 0,
          },
          KEY_ARTISTS => {
            KEY_RESULTS => [],
            KEY_PAGE_NUM => 1,
            KEY_TOTAL_COUNT => 0,
            KEY_PAGE_COUNT => 0,
          },
        },
      }
    end

    def self.search_target_class
      JamTrack
    end

    def do_search(query) 
      rel = JamTrack.unscoped

      unless (gids = query[KEY_GENRES]).blank?
        allgids = self.class.genre_ids
        gids = gids.select { |gg| allgids.has_key?(gg) }
        
        unless gids.blank?
          sqlstr = "'#{gids.join("','")}'"
          rel = rel.joins(:genres_jam_tracks)
          rel = rel.where("genres_jam_tracks.genre_id IN (#{sqlstr})")
        end
      end
      unless (instruments = query[KEY_INSTRUMENTS]).blank?
        instrids = self.class.instrument_ids
        instruments = instruments.select { |ii| instrids.has_key?(ii['instrument_id']) }

        unless instruments.blank?
          sqlstr = "'#{instruments.join("','")}'"
          rel = rel.joins(:jam_track_tracks)
          rel = rel.where("jam_track_tracks.instrument_id IN (#{sqlstr})")
          rel = rel.where("jam_track_tracks.track_type = 'Track'")
        end
      end

      unless (artist_name = query[KEY_ORIGINAL_ARTIST]).blank?
        rel = rel.where(original_artist: artist_name)
      end

      rel
    end

    def search_results_page(query=nil)
      filter = { 
        KEY_QUERY => query,
      }
      result_types = query[KEY_RESULT_TYPES]
      if result_types
        has_songs, has_artists = result_types.index(KEY_SONGS), result_types.index(KEY_ARTISTS)
      else
        has_songs, has_artists = true, true
      end
      result_sets = filter[KEY_RESULT_SETS] = self.class.json_schema[KEY_RESULT_SETS].clone
      if has_songs
        rel = do_search(query)
        unless (val = query[KEY_SEARCH_STR]).blank?
          tsquery = Search.create_tsquery(val)
          rel = rel.where("(search_tsv @@ to_tsquery('jamenglish', ?))", tsquery) if tsquery
        end
        rel = rel.order(:name).includes(:genres)

        pgnum = [query[KEY_PAGE_NUM].to_i, 1].max
        rel = rel.paginate(:page => pgnum, :per_page => query[KEY_PER_PAGE])

        results = rel.all.collect do |jt|
          {
            'id' => jt.id,
            'name' => jt.name,
            'artist' => jt.original_artist,
            'genre' => jt.genres.map(&:description).join(', '),
            'plan_code' => jt.plan_code,
            'year' => jt.year
          }
        end

        result_sets[KEY_SONGS] = {
          KEY_RESULTS => results,
          KEY_PAGE_NUM => pgnum,
          KEY_TOTAL_COUNT => rel.total_entries,
          KEY_PAGE_COUNT => rel.total_pages,
        }
      end

      if has_artists
        rel = do_search(query)
        counter = rel.select("DISTINCT(jam_tracks.original_artist)")
        rel = rel.select("DISTINCT ON(jam_tracks.original_artist) jam_tracks.id, jam_tracks.original_artist")

        unless (val = query[KEY_SEARCH_STR]).blank?
          rel = rel.where("original_artist ILIKE ?","%#{val}%")
          counter = counter.where("original_artist ILIKE ?","%#{val}%")
        end
        rel = rel.order(:original_artist)
        
        pgnum = [query[KEY_PAGE_NUM].to_i, 1].max
        rel = rel.paginate(:page => pgnum, :per_page => query[KEY_PER_PAGE])

        results = rel.all.collect do |jt|
          { 'id' => jt.id, 'artist' => jt.original_artist }
        end
        
        artist_count = counter.count

        result_sets[KEY_ARTISTS] = {
          KEY_RESULTS => results,
          KEY_PAGE_NUM => pgnum,
          KEY_TOTAL_COUNT => artist_count,
          KEY_PAGE_COUNT => (artist_count / query[KEY_PER_PAGE].to_f).ceil,
        }
      end

      filter
    end

    def self.all_languages
      JamTrack.select("SELECT DISTINCT(language)").order(:language).collect do |lang|
        { description: ISO_639.find_by_code(lang), id: lang }
      end
    end
    
  end
end
