require 'paperclip' 
require 'mp3info' 
require "digest"

class Song < ActiveRecord::Base
  has_and_belongs_to_many :tags
  belongs_to :user
  has_many :songs
  
  has_attached_file :audio,
                    :url => "/audios/:id",
                    :path => ":rails_root/public/audios/:id"
                    
  ajaxful_rateable :stars => 5, :dimensions => [:quality], :allow_update => false

  validates_presence_of :author, :description, :audio
  validates_numericality_of :listen_count,  :only_integer => true,
                                            :greater_than_or_equal_to => 0
                                            
  #check that the size of the file is less than or equal to 15 MB (size in bytes)
  validates_numericality_of :audio_file_size, :less_than_or_equal_to => 15728640, :message => "Audio file is too large. Max file size is 15 MB"
  
  
  attr_accessible :song_length, :author, :description, :audio, :md5sum, :audio_file_size
  
  after_save :get_song_info

  GENRES = [
    "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
    "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
    "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
    "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
    "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
    "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
    "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
    "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
    "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
    "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
    "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
    "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
    "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
    "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
    "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
    "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
    "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
    "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
    "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
    "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
    "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
    "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
    "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
    "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
    "SynthPop" ]




  def get_song_info
	  Mp3Info.open("#{RAILS_ROOT}/public/audios/#{id}") do |mp3info|
	     
	     #Tedious conversion of song length given in seconds.
	     #This code converts the seconds to minutes and parses it into a min:secs format
	     
	     #convert seconds into minutes and rounds to 2 decimal places
	     len_str = (((mp3info.length / 60.00) * (10.0**2)).round) / (10.0**2)
	     len_float = len_str.to_f
	     len_int = len_float.to_i
	     len_frac = (((len_float-len_int) * (10.0**2)).round) / (10.0**2)
	     len_frac_str = len_frac.to_s.split('.')
	     len_frac = len_frac_str[1].to_i
	     
	     if (len_frac  >= 70)
	     	len_frac = 100 - len_frac + 10
	     elsif (len_frac  > 59)
	     	len_frac  = 100 - len_frac 
	     elsif (len_frac < 10)
	     	len_frac = ("0" + "#{len_frac}").to_i
	     end
	     
	     if (len_frac < 10)
	     	len = "#{len_int}" + ":" + len_frac_str[1]
	     else
	     	len = "#{len_int}" + ":" + "#{len_frac}"
	     end
	     
	     update_attribute(:song_length, len) unless song_length
	     if not (GENRES.index mp3info.tag.genre_s).nil?
	     	write_attribute(:tags, tags << get_tag(mp3info.tag.genre_s)) unless mp3info.tag.genre_s.nil? or not tags.empty?
	     end
	  end
  end
  
  #def tags_attributes=(tags_attributes)
  #  tags_attributes.each do |attributes|
  #    tags.build(tags_attributes)
  #   end
  #end
  
  private
    def get_tag(genre)
      t = Tag.find(:first, :conditions => { :name => genre.downcase })
      return t if t
      t = Tag.new({:name => genre.downcase})
      t.save
      t
    end
    
    def make_md5sum
    
      	digest = Digest::MD5.new
    	File.open("#{RAILS_ROOT}/public/audios/#{id}", "r") do |f|
    	    digest.update f.read(8192) until f.eof
     	end
     	update_attribute(:md5sum, md5) unless md5sum
     	
    end
end 
