module JamRuby
  class Retailer < ActiveRecord::Base

    GUITAR_CENTER = 'guitar_center'

    include HtmlSanitize
    html_sanitize strict: [:name]

    attr_accessor     :updating_avatar, :password, :should_validate_password
    attr_accessible   :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection

    belongs_to :posa_cards, class_name: 'JamRuby::PosaCard'
    belongs_to :user, class_name: ::JamRuby::User, inverse_of: :owned_retailer
    belongs_to :affiliate_partner, class_name: "JamRuby::AffiliatePartner"
    has_many :teachers, class_name: "JamRuby::Teacher"
    has_many :retailer_invitations, class_name: 'JamRuby::RetailerInvitation'
    has_many :teacher_payments, class_name: 'JamRuby::TeacherPayment'
    has_many :teacher_distributions, class_name: 'JamRuby::TeacherDistribution'
    has_many :sales, class_name: 'JamRuby::Sale'
    has_many :sale_line_items, class_name: 'JamRuby::SaleLineItem'
    has_many :lesson_bookings, class_name: 'JamRuby::LessonBooking'

    validates :user, presence: true
    #validates :slug, presence: true
    validates :enabled, inclusion: {in: [true, false]}
    validates_length_of :password, minimum: 6, maximum: 100, :if => :should_validate_password

    after_create :create_affiliate
    after_create :create_slug
   # before_save :stringify_avatar_info, :if => :updating_avatar

    def create_slug
      if self.slug.blank?
        self.slug = self.id.to_s
      end

      self.save!
    end

    def create_affiliate
      if affiliate_partner.nil?
        AffiliatePartner.create_from_retailer(self)
      end

    end

    def encrypt(password)
      BCrypt::Password.create(password, cost: 12).to_s
    end

    def matches_password(password)

      if password.blank?
        return false
      end

      begin
        # we init passwordfield as a UUID, which is a bogus hash; so if we see UUId, we know retailer has no password yet
        UUIDTools::UUID.parse(self.encrypted_password)
        return false
      rescue ArgumentError
      end

      BCrypt::Password.new(self.encrypted_password) == password
    end

    def update_payment(split)
      if split[:teacher] && split[:teacher].is_a?(Integer) && split[:retailer] && split[:retailer].is_a?(Integer)
        teacher_split = split[:teacher]
        retailer_split = split[:retailer]
        if (teacher_split >= 0 && teacher_split <= 100) && (retailer_split >= 0 && retailer_split <= 100) && (teacher_split + retailer_split == 100)
          self.payment = split.to_json
        end
      end
    end
    def update_from_params(params)
      self.name = params[:name] if params[:name].present?
      self.city = params[:city]
      self.state = params[:state]
      self.slug = params[:slug] if params[:slug].present?
      if params[:split]
        self.update_payment(params[:split])
      end

      if params[:password].present?
        self.should_validate_password = true
        self.password = params[:password]
        self.encrypted_password = encrypt(params[:password])
      end
      self.save
    end

    # should be of form {teacher: 0-100, retailer: 0-100}
    def  payment_details
      if self.payment
        JSON.parse(self.payment)
      else
        {"teacher" =>100, "retailer" => 0}
      end
    end

    def owner
      user
    end

    def self.guitar_center
      Retailer.find_by_special(GUITAR_CENTER)
    end
    def is_guitar_center?
      return special == GUITAR_CENTER
    end

    def validate_avatar_info
      if updating_avatar
        # we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io)
        errors.add(:original_fpfile, ValidationMessages::INVALID_FPFILE) if self.original_fpfile.nil? || self.original_fpfile["key"].nil? || self.original_fpfile["url"].nil?
        errors.add(:cropped_fpfile, ValidationMessages::INVALID_FPFILE) if self.cropped_fpfile.nil? || self.cropped_fpfile["key"].nil? || self.cropped_fpfile["url"].nil?
        errors.add(:cropped_large_fpfile, ValidationMessages::INVALID_FPFILE) if self.cropped_large_fpfile.nil? || self.cropped_large_fpfile["key"].nil? || self.cropped_large_fpfile["url"].nil?
      end
    end

    def escape_filename(path)
      dir = File.dirname(path)
      file = File.basename(path)
      "#{dir}/#{ERB::Util.url_encode(file)}"
    end

    def update_avatar(original_fpfile, cropped_fpfile, cropped_large_fpfile, crop_selection, aws_bucket)
      self.updating_avatar = true

      cropped_s3_path = cropped_fpfile["key"]
      cropped_large_s3_path = cropped_large_fpfile["key"]

      self.update_attributes(
          :original_fpfile => original_fpfile.to_json,
          :cropped_fpfile => cropped_fpfile.to_json,
          :cropped_large_fpfile => cropped_large_fpfile.to_json,
          :cropped_s3_path => cropped_s3_path,
          :cropped_large_s3_path => cropped_large_s3_path,
          :crop_selection => crop_selection.to_json,
          :photo_url => S3Util.url(aws_bucket, escape_filename(cropped_s3_path), :secure => true),
          :large_photo_url => S3Util.url(aws_bucket, escape_filename(cropped_large_s3_path), :secure => true)
      )
    end

    def delete_avatar(aws_bucket)

      User.transaction do

        unless self.cropped_s3_path.nil?
          S3Util.delete(aws_bucket, File.dirname(self.cropped_s3_path) + '/cropped.jpg')
          S3Util.delete(aws_bucket, self.cropped_s3_path)
          S3Util.delete(aws_bucket, self.cropped_large_s3_path)
        end

        return self.update_attributes(
            :original_fpfile => nil,
            :cropped_fpfile => nil,
            :cropped_large_fpfile => nil,
            :cropped_s3_path => nil,
            :cropped_large_s3_path => nil,
            :photo_url => nil,
            :crop_selection => nil,
            :large_photo_url => nil
        )
      end
    end

    def stringify_avatar_info
      # fpfile comes in as a hash, which is a easy-to-use and validate form.  However, we store it as a VARCHAR,
      # so we need t oconvert it to JSON before storing it (otherwise it gets serialized as a ruby object)
      # later, when serving this data out to the REST API, we currently just leave it as a string and make a JSON capable
      # client parse  it, because it's very rare when it's needed at all
      self.original_fpfile = original_fpfile.to_json if !original_fpfile.nil? && original_fpfile.class != String
      self.cropped_fpfile = cropped_fpfile.to_json if !cropped_fpfile.nil? && cropped_fpfile.class != String
      self.crop_selection = crop_selection.to_json if !crop_selection.nil? && crop_selection.class != String
    end
  end
end
