/**
 * Nextcloud - Gallery
 *
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Olivier Paroz <galleryapps@oparoz.com>
 *
 * @copyright Olivier Paroz 2017
 */
/* global Handlebars, Gallery */
(function ($, OC, t, Gallery) {
	"use strict";

	var TEMPLATE =
		'{{#each crumbs}}' +
		'	<div class="crumb {{cssClass}}" data-dir="{{dir}}">' +
		'	{{#if link}}' +
		'		<a href="{{link}}">' +
		'		{{#if img}}' +
		'			{{#with img}}' +
		'			<img title="{{title}}" src="{{imageSrc}}">' +
		'			{{/with}}' +
		'		{{else}}' +
		'			{{name}}' +
		'		{{/if}}' +
		'		</a>' +
		'	{{else}}' +
		'		<span>{{name}}</span>' +
		'	{{/if}}' +
		'	</div>' +
		'{{/each}}';

	/**
	 * Breadcrumbs that represent the path to the current album
	 *
	 * @constructor
	 */
	var Breadcrumb = function () {
		this.breadcrumbsElement = $('#breadcrumbs');
	};

	Breadcrumb.prototype = {
		breadcrumbs: [],
		breadcrumbsElement: null,
		ellipsis: null,
		albumPath: null,
		availableWidth: 0,
		onClick: null,
		droppableOptions: {
			accept: "#gallery > .row > a",
			activeClass: 'breadcrumbs-droppable',
			hoverClass: 'breadcrumbs-droppable-hover',
			tolerance: 'pointer'
		},

		/**
		 * Initialises the breadcrumbs for the current album
		 *
		 * @param {string} albumPath
		 * @param {int} availableWidth
		 */
		init: function (albumPath, availableWidth) {
			this.albumPath = albumPath;
			this.availableWidth = availableWidth;
			this.breadcrumbs = [];
			if (!this._template) {
				this._template = Handlebars.compile(TEMPLATE);
			}
			this._build();
			this._resize(this.availableWidth);
		},

		/**
		 * Defines the maximum available width in which we can build the breadcrumb and resizes it
		 *
		 * @param {int} availableWidth
		 */
		setMaxWidth: function (availableWidth) {
			if (this.availableWidth > availableWidth || this.ellipsis.is(":visible")) {
				this.availableWidth = availableWidth;
				this._resize(this.availableWidth);
			}
		},

		/**
		 * Processes UI elements dropped on the breadcrumbs
		 *
		 * @param event
		 * @param ui
		 */
		onDrop: function (event, ui) {
			var $item = ui.draggable;
			var $clone = ui.helper;
			var $target = $(event.target);
			if (!$target.is('.crumb')) {
				$target = $target.closest('.crumb');
			}
			var targetPath = $(event.target).data('dir').toString();
			var dir = Gallery.currentAlbum;

			while (dir.substr(0, 1) === '/') {//remove extra leading /'s
				dir = dir.substr(1);
			}
			dir = '/' + dir;
			if (dir.substr(-1, 1) !== '/') {
				dir = dir + '/';
			}
			// Do nothing if dragged on current dir
			if (targetPath === dir || targetPath + '/' === dir) {
				return;
			}
			var filePath = $item.data('path').toString();
			var fileName = OC.basename(filePath);

			$clone.fadeOut("normal", function () {
				Gallery.move($item, fileName, filePath, $target, targetPath);
			});
		},

		/**
		 * Shows the dark spinner on the crumb
		 */
		showLoader: function () {
			$(this).addClass("icon-loading-small-dark");
		},

		/**
		 * Builds the breadcrumbs array
		 *
		 * @private
		 */
		_build: function () {
			var i, crumbs, name, path, currentAlbum;
			var albumName = $('#content').data('albumname');
			if (!albumName) {
				albumName = t('gallery', 'Gallery');
			}
			path = '';
			name = '';
			crumbs = this.albumPath.split('/');
			currentAlbum = crumbs.pop();

			// This adds the home button
			this._addHome(albumName, currentAlbum);
			// We always add a hidden ellipsis
			this._pushCrumb('...', '', null, 'ellipsis');

			if (currentAlbum) {
				// This builds the crumbs between home and the current folder
				var crumbsLength = crumbs.length;
				if (crumbsLength > 0) {
					// We add all albums to the breadcrumbs array
					for (i = 0; i < crumbsLength; i++) {
						if (crumbs[i]) {
							name = crumbs[i];
							if (path) {
								path += '/' + crumbs[i];
							} else {
								path += crumbs[i];
							}
							this._pushCrumb(name, path, null, '');
						}
					}
				}
				// We finally push the current folder
				this._pushCrumb(currentAlbum, '', null, 'last');
			}

			this._render();
		},

		/**
		 * Adds the Home button
		 *
		 * @param {string} albumName
		 * @param {string} currentAlbum
		 * @private
		 */
		_addHome: function (albumName, currentAlbum) {
			var crumbImg = {
				imageSrc: OC.imagePath('core', 'places/home'),
				title: albumName
			};
			var cssClass = 'home';
			if (!currentAlbum) {
				cssClass += ' last';
			}

			this._pushCrumb('', '', crumbImg, cssClass);
		},

		/**
		 * Pushes crumb objects to the breadcrumbs array
		 *
		 * @param {string} name
		 * @param {string|boolean} link
		 * @param {Object} img
		 * @param {string} cssClass
		 * @private
		 */
		_pushCrumb: function (name, link, img, cssClass) {
			var hash = '';

			// Prevent the last crumb from getting a link unless the last crumb is 'home'.
			if ( cssClass.indexOf('last') === -1 || cssClass.indexOf('home') > -1 ) {
				hash = '#' + encodeURIComponent(link);
			}

			this.breadcrumbs.push({
				name: name,
				dir: link,
				link: hash,
				img: img,
				cssClass: cssClass
			});
		},

		/**
		 * Renders the full breadcrumb based on crumbs we have collected
		 *
		 * @private
		 */
		_render: function () {
			this.breadcrumbsElement.children().remove();

			var breadcrumbs = this._template({
				crumbs: this.breadcrumbs
			});

			this.breadcrumbsElement.append(breadcrumbs);

			this.droppableOptions.drop = this.onDrop.bind(this);
			this.breadcrumbsElement.find('.crumb:not(.last)').droppable(this.droppableOptions);
		},

		/**
		 * Alters the breadcrumb to make it fit within the asked dimensions
		 *
		 * @param {int} availableWidth
		 *
		 * @private
		 */
		_resize: function (availableWidth) {
			var crumbs = this.breadcrumbsElement.children();
			var shorten = false;
			var ellipsisPath = '';
			var self = this;

			// Hide everything first, so that we can check the width after adding each crumb
			crumbs.hide();

			// We go through the array in reverse order
			var crumbsElement = crumbs.get().reverse();
			$(crumbsElement).each(function () {
				if ($(this).hasClass('home')) {
					$(this).show();
					if (self.breadcrumbs.length > 2) {
						$(this).click(self.showLoader);
					}
					return;
				}
				// 1st sub-album has no-parent and the breadcrumbs contain home, ellipsis and last
				if (self.breadcrumbs.length > 3) {
					$(this).click(self.showLoader);
				}
				if ($(this).hasClass('ellipsis')) {
					self.ellipsis = $(this);
					return;
				}
				if (!shorten) {
					$(this).show();
				}

				// If we've reached the maximum width, we start hiding crumbs
				if (self.breadcrumbsElement.width() > availableWidth) {
					shorten = true;
					$(this).hide();
					if (!ellipsisPath) {
						ellipsisPath = $(this).data('dir');
					}
				}
			});

			// If we had to hide crumbs, we add a way to go to the parent folder
			if (shorten) {
				this.ellipsis.show();

				if (!ellipsisPath) {
					ellipsisPath = OC.dirname(this.albumPath);
				}

				this.ellipsis.children('a').attr('href', '#' + encodeURIComponent(ellipsisPath));
				this.ellipsis.attr('data-original-title', ellipsisPath).tooltip({
					fade: true,
					placement: 'bottom',
					delay: {
						hide: 5
					}
				});
			}
		}
	};

	Gallery.Breadcrumb = Breadcrumb;
})(jQuery, OC, t, Gallery);
