module JamRuby
  class DownloadTracker < ActiveRecord::Base

    @@log = Logging.logger[DownloadTracker]

    belongs_to :user, :class_name => "JamRuby::User"
    belongs_to :mixdown, :class_name => "JamRuby::JamTrackMixdownPackage", foreign_key: 'mixdown_id'
    belongs_to :stem, :class_name => "JamRuby::JamTrackTrack", foreign_key: 'stem_id'
    belongs_to :jam_track, :class_name => "JamRuby::JamTrack"

    # one of mixdown or stem need to be specified. could validate this?
    validates :user, presence:true
    validates :remote_ip, presence: true
    #validates :paid, presence: true
    validates :jam_track, presence: :true

    def self.create(user, remote_ip, target, owned, fingerprint, is_client)
      dt = DownloadTracker.new
      dt.user = user
      dt.remote_ip = remote_ip
      dt.paid = owned
      dt.is_client = is_client
      dt.fingerprint = fingerprint
      if target.is_a?(JamTrack)
        dt.jam_track_id = target.id
      elsif target.is_a?(JamTrackTrack)
        dt.jam_track_id = target.jam_track_id
      elsif target.is_a?(JamTrackMixdownPackage)
        dt.jam_track_id = target.jam_track_mixdown.jam_track_id
      end
      if !dt.save
        @@log.error("unable to create Download Tracker: #{dt.errors.inspect}")
      end
      dt
    end

    def self.check(user, remote_ip, target, owned, fingerprint, is_client)

      return false unless APP_CONFIG.guard_against_browser_fraud

      return false if user.admin

      return false if UserWhitelist.listed(user)

      create(user, remote_ip, target, owned, fingerprint, is_client)

      # let's check the following
      blacklisted = alert_freebies_snarfer(remote_ip, owned)

      alert_user_sharer(user)

      blacklisted
    end

    # somebody who has shared account info with a large number of people
    # high number of downloads of the same user from different IP addresses that were or were not paid for
    # raw query created by this code:
    # SELECT distinct(user_id), count(user_id) FROM "download_trackers" WHERE (created_at > NOW() - '30 days'::interval) GROUP BY user_id HAVING count(distinct(remote_ip)) >= 2
    def self.check_user_sharer(max, user_id = nil)
      query = DownloadTracker.select('distinct(user_id), count(user_id)')
      query = query.where("created_at > NOW() - '#{APP_CONFIG.download_tracker_day_range} days'::interval")
      if !user_id.nil?
        query = query.where('user_id = ?', user_id)
      end

      query.group(:user_id).having("count(distinct(remote_ip)) >= #{max}")
    end




    # somebody who has figured out how to bypass cookie based method of identity checking, and is getting lots of free JamTracks
    # high number of downloads of different jam tracks from different users for the same IP address that weren't paid for
    # raw query created by this code:
    # SELECT distinct(remote_ip), count(remote_ip) FROM "download_trackers" WHERE (paid = false) AND (created_at > NOW() - '30 days'::interval) GROUP BY remote_ip HAVING count(distinct(jam_track_id)) >= 2
    def self.check_freebie_snarfer(max, remote_ip = nil)

      query = DownloadTracker.select('distinct(remote_ip), count(remote_ip)').where("paid = false")
      query = query.where("created_at > NOW() - '#{APP_CONFIG.download_tracker_day_range} days'::interval")
      if !remote_ip.nil?
        query = query.where('remote_ip = ?', remote_ip)
      end
      query.group(:remote_ip).having("count(distinct(jam_track_id)) >= #{max}")
    end

    def self.alert_user_sharer(user)
      violation = check_user_sharer(APP_CONFIG.max_user_ip_address, user.id)[0]

      if violation
        body = "User has downloaded from too many IP addresses #{user.id}\n"
        body << "Download Count: #{violation['count']}\n"
        body << "User URL #{user.admin_url}\n"
        body << "Add to blacklist: #{UserBlacklist.admin_url}"

        AdminMailer.alerts({
                               subject:"Account IP Access Violation. USER: #{user.email}",
                               body:body
                           }).deliver_now
      end
    end

    def self.alert_freebies_snarfer(remote_ip, owned)

      if owned
        return false
      end

      if !IpWhitelist.listed(remote_ip)
        violation = check_freebie_snarfer(APP_CONFIG.max_multiple_users_same_ip, remote_ip)[0]
      end


      if violation
        body = "IP Address: #{remote_ip}\n"
        body << "Download Count: #{violation['count']}\n"
        body << "Add to blacklist: #{IpBlacklist.admin_url}"
        body << "Check Activity: #{IpBlacklist.admin_activity_url(remote_ip)}"

        AdminMailer.alerts({
             subject:"Single IP Access Violation. IP:#{remote_ip}",
             body:body
         }).deliver_now

        # and now shut them down
        if Rails.application.config.ban_jamtrack_downloaders
          blacklist = IpBlacklist.new
          blacklist.remote_ip = remote_ip
          blacklist.notes = 'auto'
          blacklist.save
          return blacklist
        end
      end
      return false
    end

    def admin_url
      APP_CONFIG.admin_root_url + "/admin/download_trackers/" + id
    end

    def to_s
      if stem?
        "stem:#{stem} #{remote_ip} #{user}"
      else
        "mixdown:#{mixdown} #{remote_ip} #{user}"
      end
    end
  end
end