module JamRuby
  class Band < ActiveRecord::Base

    attr_accessible :name, :website, :biography, :city, :state, :country

    self.primary_key = 'id'

    validates :biography, no_profanity: true

    # musicians
    has_many :band_musicians, :class_name => "JamRuby::BandMusician"
    has_many :users, :through => :band_musicians, :class_name => "JamRuby::User"

    # genres
    has_and_belongs_to_many :genres, :class_name => "JamRuby::Genre", :join_table => "bands_genres"

    # recordings
    has_many :recordings, :class_name => "JamRuby::Recording", :foreign_key => "band_id"

    # likers
    has_many :likers, :class_name => "JamRuby::BandLiker", :foreign_key => "band_id", :inverse_of => :band
    has_many :inverse_likers, :through => :likers, :class_name => "JamRuby::User", :foreign_key => "liker_id"

    # followers
    has_many :band_followers, :class_name => "JamRuby::BandFollower", :foreign_key => "band_id"
    has_many :followers, :through => :band_followers, :class_name => "JamRuby::User"
    has_many :inverse_band_followers, :through => :followers, :class_name => "JamRuby::BandFollower", :foreign_key => "follower_id"
    has_many :inverse_followers, :through => :inverse_band_followers, :source => :band, :class_name => "JamRuby::Band"

    # invitations
    has_many :invitations, :inverse_of => :band, :class_name => "JamRuby::BandInvitation", :foreign_key => "band_id"

    # music_sessions
    has_many :music_sessions, :class_name => "JamRuby::MusicSession", :foreign_key => "band_id"
    has_many :music_session_history, :class_name => "JamRuby::MusicSessionHistory", :foreign_key => "band_id", :inverse_of => :band

    def liker_count
      return self.likers.size
    end

    def follower_count
      return self.followers.size
    end

    def recording_count
      return self.recordings.size
    end

    def session_count
      return self.music_sessions.size
    end

    def location
      loc = self.city.blank? ? '' : self.city
      loc = loc.blank? ? self.state : "#{loc}, #{self.state}" unless self.state.blank?
      #loc = loc.blank? ? self.country : "#{loc}, #{self.country}" unless self.country.blank?
      loc
    end

    def add_member(user_id, admin)
      BandMusician.create(:band_id => self.id, :user_id => user_id, :admin => admin)
    end

    def self.recording_index(current_user, band_id)
      hide_private = false
      band = Band.find(band_id)

      # hide private Recordings from anyone who's not in the Band
      unless band.users.exists? current_user
        hide_private = true
      end

      if hide_private
        recordings = Recording.joins(:band_recordings)
                              .where(:bands_recordings => {:band_id => "#{band_id}"}, :public => true)

      else
        recordings = Recording.joins(:band_recordings)
                              .where(:bands_recordings => {:band_id => "#{band_id}"})
      end

      return recordings
    end

    def self.search(query, options = { :limit => 10 })

      # only issue search if at least 2 characters are specified
      if query.nil? || query.length < 2
        return []
      end

      # create 'anded' statement
      query = Search.create_tsquery(query)

      if query.nil? || query.length == 0
        return []
      end

      return Band.where("name_tsv @@ to_tsquery('jamenglish', ?)", query).limit(options[:limit])
    end
    
    # helper method for creating / updating a Band
    def self.save(id, name, website, biography, city, state, country, genres, user_id, photo_url, logo_url)

      user = User.find(user_id)

      # new band
      if id.nil?

        # ensure person creating this Band is a Musician
        unless user.musician?
          raise JamRuby::PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
        end

        validate_genres(genres, false)
        band = Band.new()

      # band update
      else
        validate_genres(genres, true)
        band = Band.find(id)

        # ensure user updating Band details is a Band member
        unless band.users.exists? user
          raise PermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
        end
      end

      # name
      unless name.nil?
        band.name = name
      end

      # website
      unless website.nil?
        band.website = website
      end

      # biography
      unless biography.nil?
        band.biography = biography
      end

      # city
      unless city.nil?
        band.city = city
      end

      # state
      unless state.nil?
        band.state = state
      end

      # country
      unless country.nil?
        band.country = country
      end

      # genres
      unless genres.nil?
        ActiveRecord::Base.transaction do
          # delete all genres for this band first
          unless band.id.nil? || band.id.length == 0
            band.genres.delete_all
          end

          # loop through each genre in the array and save to the db
          genres.each do |genre_id|
            g = Genre.find(genre_id)
            band.genres << g
          end
        end
      end

      # photo url
      unless photo_url.nil?
        band.photo_url = photo_url
      end

      # logo url
      unless logo_url.nil?
        band.logo_url = logo_url
      end

      band.updated_at = Time.now.getutc
      band.save

      # add the creator as the admin
      if id.nil?
        BandMusician.create(:band_id => band.id, :user_id => user_id, :admin => true)
      end

      return band
    end

    private
      def self.validate_genres(genres, is_nil_ok)
        if is_nil_ok && genres.nil?
          return
        end

        if genres.nil?
          raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
        else
          if genres.size < Limits::MIN_GENRES_PER_BAND
            raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
          end

          if genres.size > Limits::MAX_GENRES_PER_BAND
            raise JamRuby::JamArgumentError, ValidationMessages::GENRE_LIMIT_EXCEEDED
          end
        end
      end
  end
end
