/* eslint key-spacing: 0 */
/* eslint quote-props: 0 */

import { arrayLength, pInt } from 'Common/Utils';

export const RFC822 = 'message/rfc822';

const
	cache = {},
	app = 'application/',
	msOffice = app+'vnd.openxmlformats-officedocument.',
	openDoc = app+'vnd.oasis.opendocument.',
	sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'],
	lowerCase = text => text.toLowerCase().trim(),

	exts = {
		eml: RFC822,
		mime: RFC822,
		vcard: 'text/vcard',
		vcf: 'text/vcard',
		htm: 'text/html',
		html: 'text/html',
		csv: 'text/csv',
		ics: 'text/calendar',
		xml: 'text/xml',
		json: app+'json',
//		asc: app+'pgp-signature',
//		asc: app+'pgp-keys',
		p10: app+'pkcs10',
		p7c: app+'pkcs7-mime',
		p7m: app+'pkcs7-mime',
		p7s: app+'pkcs7-signature',
		p12: app+'pkcs12',
		pfx: app+'x-pkcs12',
		torrent: app+'x-bittorrent',

		// scripts
		js: app+'javascript',
		pl: 'text/perl',
		css: 'text/css',
		asp: 'text/asp',
		php: app+'x-php',

		// images
		jpg: 'image/jpeg',
		ico: 'image/x-icon',
		tif: 'image/tiff',
		svg: 'image/svg+xml',
		svgz: 'image/svg+xml',

		// archives
		zip: app+'zip',
		'7z': app+'x-7z-compressed',
		rar: app+'x-rar-compressed',
		cab: app+'vnd.ms-cab-compressed',
		gz: app+'x-gzip',
		tgz: app+'x-gzip',
		bz: app+'x-bzip',
		bz2: app+'x-bzip2',
		deb: app+'x-debian-package',

		// audio
		mp3: 'audio/mpeg',
		wav: 'audio/x-wav',
		mp4a: 'audio/mp4',
		weba: 'audio/webm',
		m3u: 'audio/x-mpegurl',

		// video
		qt: 'video/quicktime',
		mov: 'video/quicktime',
		wmv: 'video/windows-media',
		avi: 'video/x-msvideo',
		'3gp': 'video/3gpp',
		'3g2': 'video/3gpp2',
		mp4v: 'video/mp4',
		mpg4: 'video/mp4',
		ogv: 'video/ogg',
		m4v: 'video/x-m4v',
		asf: 'video/x-ms-asf',
		asx: 'video/x-ms-asf',
		wm: 'video/x-ms-wm',
		wmx: 'video/x-ms-wmx',
		wvx: 'video/x-ms-wvx',
		movie: 'video/x-sgi-movie',

		// adobe
		pdf: app+'pdf',
		psd: 'image/vnd.adobe.photoshop',
		ai: app+'postscript',
		eps: app+'postscript',
		ps: app+'postscript',

		// ms office
		doc: app+'msword',
		rtf: app+'rtf',
		xls: app+'vnd.ms-excel',
		ppt: app+'vnd.ms-powerpoint',
		docx: msOffice+'wordprocessingml.document',
		xlsx: msOffice+'spreadsheetml.sheet',
		dotx: msOffice+'wordprocessingml.template',
		pptx: msOffice+'presentationml.presentation',

		// open office
		odt: openDoc+'text',
		ods: openDoc+'spreadsheet',
		odp: openDoc+'presentation'
	};

export const FileType = {
	Unknown: 'unknown',
	Text: 'text',
	Code: 'code',
	Eml: 'eml',
	Word: 'word',
	Pdf: 'pdf',
	Image: 'image',
	Audio: 'audio',
	Video: 'video',
	Spreadsheet: 'spreadsheet',
	Presentation: 'presentation',
	Certificate: 'certificate',
	Archive: 'archive',
	Calendar: 'calendar'
};

export const FileInfo = {
	/**
	 * @param {string} fileName
	 * @returns {string}
	 */
	getExtension: fileName => {
		fileName = lowerCase(fileName);
		const result = fileName.split('.').pop();
		return result === fileName ? '' : result;
	},

	getContentType: fileName => {
		fileName = lowerCase(fileName);
		if ('winmail.dat' === fileName) {
			return app + 'vnd.ms-tnef';
		}
		let ext = fileName.split('.').pop();
		if (/^(txt|text|def|list|in|ini|log|sql|cfg|conf)$/.test(ext))
			return 'text/plain';
		if (/^(mpe?g|mpe|m1v|m2v)$/.test(ext))
			return 'video/mpeg';
		if (/^aif[cf]?$/.test(ext))
			return 'audio/aiff';
		if (/^(aac|flac|midi|ogg)$/.test(ext))
			return 'audio/'+ext;
		if (/^(h26[134]|jpgv|mp4|webm)$/.test(ext))
			return 'video/'+ext;
		if (/^(otf|sfnt|ttf|woff2?)$/.test(ext))
			return 'font/'+ext;
		if (/^(png|jpeg|gif|tiff|webp)$/.test(ext))
			return 'image/'+ext;

		return exts[ext] || app+'octet-stream';
	},

	/**
	 * @param {string} sExt
	 * @param {string} sMimeType
	 * @returns {string}
	 */
	getType: (ext, mimeType) => {
		ext = lowerCase(ext);
		mimeType = lowerCase(mimeType).replace('csv/plain', 'text/csv').replace('x-','');

		let key = ext + mimeType;
		if (cache[key]) {
			return cache[key];
		}

		let result = FileType.Unknown;
		const mimeTypeParts = mimeType.split('/'),
			type = mimeTypeParts[1].replace('-compressed',''),
			match = str => mimeType.includes(str),
			archive = /^(zip|7z|tar|rar|gzip|bzip|bzip2)$/;

		switch (true) {
			case 'image' == mimeTypeParts[0] || ['png', 'jpg', 'jpeg', 'gif', 'webp'].includes(ext):
				result = FileType.Image;
				break;
			case 'audio' == mimeTypeParts[0] || ['mp3', 'ogg', 'oga', 'wav'].includes(ext):
				result = FileType.Audio;
				break;
			case 'video' == mimeTypeParts[0] || 'mkv' == ext || 'avi' == ext:
				result = FileType.Video;
				break;
			case ['php', 'js', 'css', 'xml', 'html'].includes(ext) || 'text/html' == mimeType:
				result = FileType.Code;
				break;
			case 'eml' == ext || ['message/delivery-status', RFC822].includes(mimeType):
				result = FileType.Eml;
				break;
			case 'ics' == ext || mimeType == 'text/calendar':
				result = FileType.Calendar;
				break;
			case 'text' == mimeTypeParts[0] || 'txt' == ext || 'log' == ext:
				result = FileType.Text;
				break;
			case archive.test(type) || archive.test(ext):
				result = FileType.Archive;
				break;
			case 'pdf' == type || 'pdf' == ext:
				result = FileType.Pdf;
				break;
			case [app+'pgp-signature', app+'pgp-keys', exts.p7m, exts.p7s, exts.p12, exts.pfx].includes(mimeType)
				|| ['asc', 'pem', 'ppk', 'p7s', 'p7m', 'p12', 'pfx'].includes(ext):
				result = FileType.Certificate;
				break;
			case match(msOffice+'.wordprocessingml') || match(openDoc+'.text') || match('vnd.ms-word')
				|| ['rtf', 'msword', 'vnd.msword'].includes(type):
				result = FileType.Word;
				break;
			case match(msOffice+'.spreadsheetml') || match(openDoc+'.spreadsheet') || match('ms-excel'):
				result = FileType.Spreadsheet;
				break;
			case match(msOffice+'.presentationml') || match(openDoc+'.presentation') || match('ms-powerpoint'):
				result = FileType.Presentation;
				break;
			// no default
		}

		return cache[key] = result;
	},

	/**
	 * @param {string} sFileType
	 * @returns {string}
	 */
	getTypeIconClass: fileType => {
		let result = 'icon-file';
		switch (fileType) {
			case FileType.Text:
			case FileType.Eml:
			case FileType.Pdf:
			case FileType.Word:
				return result + '-text';
			case FileType.Code:
			case FileType.Image:
			case FileType.Audio:
			case FileType.Video:
			case FileType.Archive:
			case FileType.Certificate:
			case FileType.Spreadsheet:
			case FileType.Presentation:
			case FileType.Calendar:
				return result + '-' + fileType;
		}
		return result;
	},

	getIconClass: (ext, mime) => FileInfo.getTypeIconClass(FileInfo.getType(ext, mime)),

	/**
	 * @param {string} sFileType
	 * @returns {string}
	 */
	getAttachmentsIconClass: data => {
		if (arrayLength(data)) {
			let icons = data
				.map(item => item ? FileInfo.getIconClass(FileInfo.getExtension(item.fileName), item.mimeType) : '')
				.validUnique();

			return (1 === icons?.length && 'icon-file' !== icons[0])
				 ? icons[0]
				 : 'icon-attachment';
		}

		return '';
	},

	friendlySize: bytes => {
		bytes = pInt(bytes);
		let i = bytes ? Math.floor(Math.log(bytes) / Math.log(1024)) : 0;
		return (bytes / Math.pow(1024, i)).toFixed(2>i ? 0 : 1) + ' ' + sizes[i];
	}

};
