/**
 * plugin.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/*global tinymce:true */

// Internal unload handler will be called before the page is unloaded
// Needs to be outside the plugin since it would otherwise keep
// a reference to editor in closue scope
/*eslint no-func-assign:0 */
tinymce._beforeUnloadHandler = function() {
	var msg;

	tinymce.each(tinymce.editors, function(editor) {
		// Store a draft for each editor instance
		if (editor.plugins.autosave) {
			editor.plugins.autosave.storeDraft();
		}

		// Setup a return message if the editor is dirty
		if (!msg && editor.isDirty() && editor.getParam("autosave_ask_before_unload", true)) {
			msg = editor.translate("You have unsaved changes are you sure you want to navigate away?");
		}
	});

	return msg;
};

tinymce.PluginManager.add('autosave', function(editor) {
	var settings = editor.settings, LocalStorage = tinymce.util.LocalStorage, prefix, started;

	prefix = settings.autosave_prefix || 'tinymce-autosave-{path}{query}-{id}-';
	prefix = prefix.replace(/\{path\}/g, document.location.pathname);
	prefix = prefix.replace(/\{query\}/g, document.location.search);
	prefix = prefix.replace(/\{id\}/g, editor.id);

	function parseTime(time, defaultTime) {
		var multipels = {
			s: 1000,
			m: 60000
		};

		time = /^(\d+)([ms]?)$/.exec('' + (time || defaultTime));

		return (time[2] ? multipels[time[2]] : 1) * parseInt(time, 10);
	}

	function hasDraft() {
		var time = parseInt(LocalStorage.getItem(prefix + "time"), 10) || 0;

		if (new Date().getTime() - time > settings.autosave_retention) {
			removeDraft(false);
			return false;
		}

		return true;
	}

	function removeDraft(fire) {
		LocalStorage.removeItem(prefix + "draft");
		LocalStorage.removeItem(prefix + "time");

		if (fire !== false) {
			editor.fire('RemoveDraft');
		}
	}

	function storeDraft() {
		if (!isEmpty() && editor.isDirty()) {
			LocalStorage.setItem(prefix + "draft", editor.getContent({format: 'raw', no_events: true}));
			LocalStorage.setItem(prefix + "time", new Date().getTime());
			editor.fire('StoreDraft');
		}
	}

	function restoreDraft() {
		if (hasDraft()) {
			editor.setContent(LocalStorage.getItem(prefix + "draft"), {format: 'raw'});
			editor.fire('RestoreDraft');
		}
	}

	function startStoreDraft() {
		if (!started) {
			setInterval(function() {
				if (!editor.removed) {
					storeDraft();
				}
			}, settings.autosave_interval);

			started = true;
		}
	}

	settings.autosave_interval = parseTime(settings.autosave_interval, '30s');
	settings.autosave_retention = parseTime(settings.autosave_retention, '20m');

	function postRender() {
		var self = this;

		self.disabled(!hasDraft());

		editor.on('StoreDraft RestoreDraft RemoveDraft', function() {
			self.disabled(!hasDraft());
		});

		startStoreDraft();
	}

	function restoreLastDraft() {
		editor.undoManager.beforeChange();
		restoreDraft();
		removeDraft();
		editor.undoManager.add();
	}

	editor.addButton('restoredraft', {
		title: 'Restore last draft',
		onclick: restoreLastDraft,
		onPostRender: postRender
	});

	editor.addMenuItem('restoredraft', {
		text: 'Restore last draft',
		onclick: restoreLastDraft,
		onPostRender: postRender,
		context: 'file'
	});

	function isEmpty(html) {
		var forcedRootBlockName = editor.settings.forced_root_block;

		html = tinymce.trim(typeof html == "undefined" ? editor.getBody().innerHTML : html);

		return html === '' || new RegExp(
			'^<' + forcedRootBlockName + '[^>]*>((\u00a0|&nbsp;|[ \t]|<br[^>]*>)+?|)<\/' + forcedRootBlockName + '>|<br>$', 'i'
		).test(html);
	}

	if (editor.settings.autosave_restore_when_empty !== false) {
		editor.on('init', function() {
			if (hasDraft() && isEmpty()) {
				restoreDraft();
			}
		});

		editor.on('saveContent', function() {
			removeDraft();
		});
	}

	window.onbeforeunload = tinymce._beforeUnloadHandler;

	this.hasDraft = hasDraft;
	this.storeDraft = storeDraft;
	this.restoreDraft = restoreDraft;
	this.removeDraft = removeDraft;
	this.isEmpty = isEmpty;
});