module JamRuby
  class QuickMixObserver < ActiveRecord::Observer

    # if you change the this class, tests really should accompany.  having alot of logic in observers is really tricky, as we do here
    observe JamRuby::QuickMix

    def before_validation(quick_mix)

      # if we see that a part was just uploaded entirely, validate that we can find the part that was just uploaded
      if quick_mix.is_part_uploading_was && !quick_mix.is_part_uploading
        begin
          aws_part = quick_mix.s3_manager.multiple_upload_find_part(quick_mix[:ogg_url], quick_mix.upload_id, quick_mix.next_part_to_upload - 1)
          # calling size on a part that does not exist will throw an exception... that's what we want
          aws_part.size
        rescue SocketError => e
          raise # this should cause a 500 error, which is what we want.  The client will retry later on 500.
        rescue Exception => e
          quick_mix.errors.add(:next_part_to_upload, ValidationMessages::PART_NOT_FOUND_IN_AWS)
        rescue RuntimeError => e
          quick_mix.errors.add(:next_part_to_upload, ValidationMessages::PART_NOT_FOUND_IN_AWS)
        rescue
          quick_mix.errors.add(:next_part_to_upload, ValidationMessages::PART_NOT_FOUND_IN_AWS)
        end

      end

      # if we detect that this just became fully uploaded -- if so, tell s3 to put the parts together
      if quick_mix.marking_complete && !quick_mix.fully_uploaded_was && quick_mix.fully_uploaded

        multipart_success = false
        begin
          quick_mix.s3_manager.multipart_upload_complete(quick_mix[:ogg_url], quick_mix.upload_id)
          multipart_success = true
        rescue SocketError => e
          raise # this should cause a 500 error, which is what we want.  The client will retry later.
        rescue Exception => e
            #quick_mix.reload
            quick_mix.reset_upload
            quick_mix.errors.add(:upload_id, ValidationMessages::BAD_UPLOAD)
        end
      end
    end

    def after_commit(quick_mix)

    end

    # here we tick upload failure counts, or revert the state of the model, as needed
    def after_rollback(quick_mix)
      # if fully uploaded, don't increment failures
      if quick_mix.fully_uploaded
        return
      end

      # increment part failures if there is a part currently being uploaded
      if quick_mix.is_part_uploading_was
       #quick_mix.reload # we don't want anything else that the user set to get applied
        quick_mix.increment_part_failures(quick_mix.part_failures_was)
        if quick_mix.part_failures >= APP_CONFIG.max_track_part_upload_failures
          # save upload id before we abort this bad boy
          upload_id = quick_mix.upload_id
          begin
            quick_mix.s3_manager.multipart_upload_abort(quick_mix[:ogg_url], upload_id)
          rescue => e
            puts e.inspect
          end
          quick_mix.reset_upload
          if quick_mix.upload_failures >= APP_CONFIG.max_track_upload_failures
            # do anything?
          end
        end
      end

    end

    def before_save(quick_mix)
      # if we are on the 1st part, then we need to make sure we can save the upload_id
      if quick_mix.next_part_to_upload == 1
        quick_mix.upload_id = quick_mix.s3_manager.multipart_upload_start(quick_mix[:ogg_url])
      end
    end
  end
end