window.jQuery = window.jQuery || {};
window.instasScript = window.instasScript || {};

( function( window, document, $, app, undefined ) {
	'use strict';

	/**
	 * Instagram Downloader Script
	 *
	 * Instructions:
	 *
	 * 1. Go to your Instagram profile url (e.g. https://instagram.com/jtsternberg/)
	 * 2. Scroll to the bottom, and click the "LOAD MORE" button. This triggers the auto-loading on scroll - http://b.ustin.co/142xL (if you forget, it will prompt you)
	 * 3. Copy this entire thing to your javascript console. (only tested on chrome)
	 * 4. Hit enter and watch your images download.
	 * 5. To stop the process, close the tab or refresh (or hit your escape key).
	 */


	/**
	 * instagram image - http://b.ustin.co/1aLvI
	 *
	 * @type {String}
	 */
	app.instaImageSelector = '._22yr2';

	/**
	 * Full-size instagram image after the modal opens - http://b.ustin.co/18xhe
	 *
	 * @type {String}
	 */
	app.modalImageSelector = '._n3cp9._d20no ._jjzlb img';

	/**
	 * Full-size instagram video after the modal opens
	 *
	 * @type {String}
	 */
	app.modalVideoSelector = '._n3cp9._d20no ._2tomm video';

	/**
	 * "Load More" button selector
	 *
	 * @type {String}
	 */
	app.loadMoreSelector = '._oidfu';

	/**
	 * Closes the modal
	 *
	 * @type {String}
	 */
	app.closeButtonSelector = '._3eajp';

	/**
	 * Amount of time to allow the image to download. May need to increase this value on a slow connection.
	 *
	 * @type {Number}
	 */
	app.downloadBufferTime = 800;

	/**
	 * Amount of time to allow the freshly-loaded images (after scroll) to load. May need to increase this value on a slow connection.
	 *
	 * @type {Number}
	 */
	app.loadMoreBufferTime = 2000;

	/**
	 * Amount of time to allow the modal to load after triggering it.
	 *
	 * @type {Number}
	 */
	app.waitForModalTime = 200;


	var notified = false;
	var stop = false;

	app.dowloaded = [];

	app.init = function() {

		var go = function() {
			alert( "Ok, we're about to begin! Press the 'escape' key to stop the the downloads." );
			$ = jQuery;

			// Listen for escape to stop the import
			$( document ).on( 'keyup', function( evt ) {
				if ( 27 === evt.keyCode ) {
					console.warn( 'STOP dowload script' );
					stop = true;
				}
			});

			app.processNext();
		};

		if ( ! window.jQuery || ! window.jQuery.fn ) {
			app.loadjQuery();
			setTimeout( go, 1000 );
		} else {
			setTimeout( go, 200 );
		}
	};

	app.start = function() {
		stop = false;
		app.processNext();
	};

	app.loadjQuery = function() {
		var script = document.createElement('script');
		script.async = 1;
		script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js';
		var otherscript = document.getElementsByTagName('script')[0];
		otherscript.parentNode.insertBefore(script, otherscript);
	};

	app.processNext = function() {

		if ( stop ) {
			$( app.closeButtonSelector ).trigger( 'click' );
			return alert( "Ok, it's stopped! `instasScript.start()` in your JS console to continue." );
		}

		app.$toClick = $( app.instaImageSelector + ':not(.instadone )' ).first();
		if ( ! app.$toClick.length ) {
			return app.triggerMore();
		}

		app.$toClick.trigger( 'click' );

		setTimeout( app.processThis, app.waitForModalTime );
	};

	app.processThis = function() {

		var $media = $( app.modalImageSelector );
		if ( ! $media.length ) {
			$media = $( app.modalVideoSelector );
		}

		if ( $media.hasClass( 'instadone' ) ) {
			return app.processNext();
		}

		if ( ! $media.length ) {
			return app.processNext();
		}

		var src = $media.attr('src');
		var haveIt = $.inArray( src, app.dowloaded );

		if ( ! src || -1 !== haveIt ) {
			if ( ! src ) {
				console.warn('! src',$media);
			}
			if ( -1 !== haveIt ) {
				console.warn('We have this image!', haveIt, src);
			}
			return app.processNext();
		}

		app.$toClick.addClass( 'instadone' );
		$media.addClass( 'instadone' );

		app.dowloaded.push( app.saveToDisk( src ) );

		$( app.closeButtonSelector ).trigger( 'click' );

		// Wait a bit to give adequate time to download
		setTimeout( app.processNext, app.downloadBufferTime );
	};

	app.triggerMore = function() {

		if ( $( app.loadMoreSelector ).length ) {
			return app.needToClickLoadMore();
		}

		var y = $(window).scrollTop();  // your current y position on the page

		// Jigger the scrolling to trigger the load-more
		$( 'html, body' ).animate( { scrollTop: y-250 }, 200, 'swing', function() {
			$( 'html, body' ).animate( { scrollTop: $( document ).height() }, 200 );
		});

		// Start the processing on the new batch
		setTimeout( app.processNext, app.loadMoreBufferTime );
	};

	app.needToClickLoadMore = function() {
		if ( ! notified ) {
			notified = true;

			$( app.closeButtonSelector ).trigger( 'click' );

			setTimeout( function() {
				$( app.loadMoreSelector ).css({ 'box-shadow' : '0px 2px 108px red', 'border-radius' : '100%' });
				alert( 'click the "LOAD MORE" button! The download script will continue automatically once "infinite scroll" is triggered.' );
			}, 500 );

			$( 'html, body' ).animate( { scrollTop: $( document ).height() }, 200 );
		}

		setTimeout( app.triggerMore, app.downloadBufferTime * 2 );
	};

	app.saveToDisk = function( fileUrl, fileName ) {
		var hyperlink = document.createElement('a');
		hyperlink.href = fileUrl;
		hyperlink.target = '_blank';
		hyperlink.download = fileName || fileUrl;

		console.log( app.dowloaded.length + ') download', hyperlink.download );

		var mouseEvent = new MouseEvent('click', {
			view: window,
			bubbles: true,
			cancelable: true
		});

		hyperlink.dispatchEvent(mouseEvent);
		(window.URL || window.webkitURL).revokeObjectURL(hyperlink.href);

		return fileUrl;
	};

	app.init();

} )( window, document, window.jQuery, window.instasScript );